複数サーバをテストするServerspecの構成
はじめに
Serverspecを使用することで、インフラ構成の単体テストを自動で実行できる。
特にテスト対象のサーバが増えていく場合には、手動確認では管理が煩雑になりやすく、構成テストの自動化を検討することになる。
本記事では、Serverspecの公式ドキュメントおよびリポジトリをもとに、複数台構成を前提としたServerspecの構成を整理した。
(公式の記載をベースにしているため、一定テンプレートとしてそのまま利用することもできると思う)
ディレクトリ構成
serverspec-template/
├── Rakefile
├── spec/
│ ├── spec_helper.rb
│ ├── web/
│ │ └── sample_spec.rb
│ └── db/
│ └── sample_spec.rb
└── hosts.yml
ファイル構成
hosts.yml(対象サーバ定義)
テスト対象のサーバ情報を記載するファイル。
SSH接続に必要な情報のほか、サーバ固有の属性やロール(役割)を付与することもできる。
これにより、テスト対象ごとに設定を切り替えたり、ロールに応じたspecを実行したりできる。
web:
host: 192.168.1.10
user: ec2-user
key: ~/.ssh/id_rsa
roles:
- base
- web
server_id: 101
db:
host: 192.168.1.20
user: ec2-user
key: ~/.ssh/id_rsa
roles:
- base
- db
server_id: 102
rolesやserver_idは任意項目であり、運用方針に合わせて拡張できる。
spec/spec_helper.rb
spec_helper.rbはServerspecの共通設定ファイルであり、テスト全体の実行方法や接続方式を定義する。
以下の例では、各ホストに対して順にSSH接続し検証を行う。
require 'serverspec'
require 'net/ssh'
require 'yaml'
# 環境変数 TARGET_HOST に指定されたホストを取得
target = ENV['TARGET_HOST'] || raise("ERROR: TARGET_HOST is not set")
hosts = YAML.load_file(File.expand_path('../../hosts.yml', __FILE__))
config = hosts[target] || raise("ERROR: no configuration for TARGET_HOST=#{target}")
# SSH経由で実行
set :backend, :ssh
set :host, config['host']
options = Net::SSH::Config.for(config['host'])
options[:user] = config['user']
options[:keys] = [File.expand_path(config['key'])]
set :ssh_options, options
# 共通設定
set :env, LANG: 'C'
set :path, '/sbin:/usr/sbin:$PATH'
# 任意:テスト内でホストプロパティ参照可
set_property config
set :backend, :ssh はリモートサーバをSSH経由で検証する設定。
ローカル検証(Serverspecの実行サーバ自身)を行う場合は :exec に変更する。
テストコード(例:spec/web/sample_spec.rb)
各サーバの設定検証を記述する。
以下はWebサーバ(nginx)を例にしたテストコードである。
require_relative '../spec_helper'
describe 'Web server configuration' do
describe package('nginx') do
it { should be_installed }
end
describe service('nginx') do
it { should be_enabled }
it { should be_running }
end
describe port(80) do
it { should be_listening }
end
end
package, service, portなどはServerspecで標準提供されている。
公式リファレンス:https://serverspec.org/resource_types.html
Rakefile
RakefileはRubyのビルドツールであるRakeの設定ファイルであり、テスト実行タスクを定義する。
Rakeを利用することで、複数ホストのテストを簡潔に実行・管理できる。
以下の例では、複数ホストを個別または一括でテストできるようにしている。
require 'rake'
require 'rspec/core/rake_task'
require 'yaml'
hosts = YAML.load_file('hosts.yml').keys
# すべてのホストを対象としたタスク
task :spec => 'spec:all'
namespace :spec do
task :all => hosts.map { |h| 'spec:' + h }
hosts.each do |host|
desc "Run serverspec to #{host}"
RSpec::Core::RakeTask.new(host) do |t|
ENV['TARGET_HOST'] = host
t.pattern = "spec/{#{host}}/*_spec.rb"
end
end
end
処理概要
-
rake spec:すべてのホストを一括テスト -
rake spec:web:特定ホストのみ実行 -
patternで対象specを動的に制御(例:ロール別)
実行環境の準備
ServerspecはRubyで動作するため、まずRuby実行環境が必要となる。
Linuxでは標準でインストールされていることが多いが、
ruby -v コマンドでバージョンを確認が可能。
ruby -v
# 例: ruby 3.1.4
テストを実行するためには、以下のGem(Rubyパッケージ)が必要になる。
| Gem名 | 用途 |
|---|---|
| serverspec | 構成テストの本体。RSpecを拡張してサーバの状態を検証する。 |
| rake | タスク実行ツール。Serverspecのテストをまとめて実行するために使用する。 |
これらをインストールする。
gem install serverspec rake
実行方法
環境が整ったら、Serverspecを実行してサーバ構成を検証する。
すべてのホストを対象にテストを実行
rake spec
特定のホストのみ実行
rake spec:web
参考ドキュメント
- Serverspec公式サイト
- Advanced Tips - Testing multiple hosts
- Serverspec GitHub Repository
- https://vincent.bernat.ch/en/blog/2014-serverspec-test-infrastructure
Discussion