[CentOS6] serverspec でインフラをテストする


Create: 2013/08/05
LastUpdate: 2013/08/05

ここでは、serverspec を使用して、サーバの状態をテストしてみます。

 [参考サイト]

serverspec を試すテスト環境では、「 [CentOS6] Chef11 + Chefspec で試すインフラの構成管理」で作成したクライアント・サーバ構成の Chef11 を使用します。

 [テスト環境]
  • Chef 管理サーバ
    192.168.1.67(chetos6g) ・・・ Chefサーバ + ワークステーション
  • Chef 管理対象
    192.168.1.68(centos6h) ・・・ ノード

1.ワークステーションに serverspec インストール


Chef 管理サーバに root ユーザでログインし、以下のように gem でインストールします。
# /opt/chef/embedded/bin/gem install serverspec --no-ri --no-rdoc
Fetching: rspec-core-2.13.1.gem (100%)
Fetching: rspec-expectations-2.13.0.gem (100%)
Fetching: rspec-mocks-2.13.1.gem (100%)
Fetching: rspec-2.13.0.gem (100%)
Fetching: serverspec-0.7.3.gem (100%)
Successfully installed rspec-core-2.13.1
Successfully installed rspec-expectations-2.13.0
Successfully installed rspec-mocks-2.13.1
Successfully installed rspec-2.13.0
Successfully installed serverspec-0.7.3
5 gems installed

2.serverspec のひな形作成


テスト対象のサーバ(192.168.1.68)に ssh 接続してテストするように serverspec のひな形を作成します。
# su - chef
$ serverspec-init
Select a backend type:

  1) SSH
  2) Exec (local)

Select number: 1

Vagrant instance y/n: n
Input target host name: 192.168.1.68
 + spec/
 + spec/192.168.1.68/
 + spec/192.168.1.68/httpd_spec.rb
 + spec/spec_helper.rb
 + Rakefile
これで、以下のようにディレクトリとファイルが作成されます。
/home/chef/spec
├── 192.168.1.68
│   └── httpd_spec.rb
└── spec_helper.rb
httpd_spec.rb はサンプルです。以下のような内容になっています。
require 'spec_helper'

describe package('httpd') do
  it { should be_installed }
end

describe service('httpd') do
  it { should be_enabled   }
  it { should be_running   }
end

describe port(80) do
  it { should be_listening }
end

describe file('/etc/httpd/conf/httpd.conf') do
  it { should be_file }
  it { should contain "ServerName 192.168.1.68" }
end
試しに、実行すると以下のようなエラーになります。
$ rake spec
/opt/chef/embedded/bin/ruby -S rspec spec/192.168.1.68/httpd_spec.rb
/opt/chef/embedded/lib/ruby/site_ruby/1.9.1/rubygems/specification.rb:1637:in `raise_if_conflicts': Unable to activate rspec-2.13.0, because rspec-core-2.14.3 conflicts with rspec-core (~> 2.13.0) (Gem::LoadError)
        from /opt/chef/embedded/lib/ruby/site_ruby/1.9.1/rubygems/specification.rb:746:in `activate'
        from /opt/chef/embedded/lib/ruby/site_ruby/1.9.1/rubygems/specification.rb:780:in `block in activate_dependencies'
        from /opt/chef/embedded/lib/ruby/site_ruby/1.9.1/rubygems/specification.rb:766:in `each'
        from /opt/chef/embedded/lib/ruby/site_ruby/1.9.1/rubygems/specification.rb:766:in `activate_dependencies'
        from /opt/chef/embedded/lib/ruby/site_ruby/1.9.1/rubygems/specification.rb:750:in `activate'
        from /opt/chef/embedded/lib/ruby/site_ruby/1.9.1/rubygems.rb:212:in `rescue in try_activate'
        from /opt/chef/embedded/lib/ruby/site_ruby/1.9.1/rubygems.rb:209:in `try_activate'
        from /opt/chef/embedded/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:59:in `rescue in require'
        from /opt/chef/embedded/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:35:in `require'
        from /home/chef/spec/spec_helper.rb:1:in `<top (required)>'
        from /opt/chef/embedded/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
        from /opt/chef/embedded/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
        from /home/chef/spec/192.168.1.68/httpd_spec.rb:1:in `<top (required)>'
        from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/rspec-core-2.14.3/lib/rspec/core/configuration.rb:896:in `load'
        from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/rspec-core-2.14.3/lib/rspec/core/configuration.rb:896:in `block in load_spec_files'
        from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/rspec-core-2.14.3/lib/rspec/core/configuration.rb:896:in `each'
        from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/rspec-core-2.14.3/lib/rspec/core/configuration.rb:896:in `load_spec_files'
        from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/rspec-core-2.14.3/lib/rspec/core/command_line.rb:22:in `run'
        from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/rspec-core-2.14.3/lib/rspec/core/runner.rb:80:in `run'
        from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/rspec-core-2.14.3/lib/rspec/core/runner.rb:17:in `block in autorun'
/opt/chef/embedded/bin/ruby -S rspec spec/192.168.1.68/httpd_spec.rb failed
rspec-2.14.3 がコンフリクトを起こしているようなので、削除してみます。
# /opt/chef/embedded/bin/gem uninstall -v 2.14.1 rspec
Successfully uninstalled rspec-2.14.1
# /opt/chef/embedded/bin/gem uninstall -v 2.14.3 rspec-core
Successfully uninstalled rspec-core-2.14.3
再度、rspec を実行すると、以下のとおり、一応、動いたようです。
ssh 接続の設定をしていないので、エラーがたくさんあります。
$ rspec spec

Package "httpd"
  example at ./spec/192.168.1.68/httpd_spec.rb:4 (FAILED - 1)

Service "httpd"
  example at ./spec/192.168.1.68/httpd_spec.rb:8 (FAILED - 2)
  example at ./spec/192.168.1.68/httpd_spec.rb:9 (FAILED - 3)

Port "80"
  example at ./spec/192.168.1.68/httpd_spec.rb:13 (FAILED - 4)
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/rspec-core-2.13.1/lib/rspec/core/formatters/base_text_formatter.rb:20:in `write': Broken pipe - <STDOUT> (Errno::EPIPE)
        from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/rspec-core-2.13.1/lib/rspec/core/formatters/base_text_formatter.rb:20:in `puts'
        from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/rspec-core-2.13.1/lib/rspec/core/formatters/base_text_formatter.rb:20:in `dump_failures'

~省略~

Finished in 0.07583 seconds
6 examples, 6 failures

Failed examples:

rspec ./spec/192.168.1.68/httpd_spec.rb:4 # Package "httpd"
rspec ./spec/192.168.1.68/httpd_spec.rb:8 # Service "httpd"
rspec ./spec/192.168.1.68/httpd_spec.rb:9 # Service "httpd"
rspec ./spec/192.168.1.68/httpd_spec.rb:13 # Port "80"
rspec ./spec/192.168.1.68/httpd_spec.rb:17 # File "/etc/httpd/conf/httpd.conf"
rspec ./spec/192.168.1.68/httpd_spec.rb:18 # File "/etc/httpd/conf/httpd.conf"
今回、Chef11のインストール環境(/opt/chef)に serverspec をインストールしたのでコンフリクトを起こしましたようです。
このあと、念のため、Chefspec も試しましたが、一応、動いていました。
CentOSに yum で ruby をインストールした環境であれば、コンフリクトを起こさないかもしれません。(試してはいません)

3.SSH接続の設定


今回は、serverspec をインストールした管理サーバ(192.168.1.67)から、テスト対象のサーバ(192.168.1.68)に root ユーザで ssh 接続してテストをすることにします。
なお、SSH鍵を使用して、パスフレーズなしで接続できるようにしますが、鍵は新しく作らないで、/etc/ssh にあるものを利用します。(とりあえず、動けばいいので)

3.1.管理サーバ側の設定


chef ユーザでテストを行うので ~/.ssh/config を作成して、以下の内容を記述します。
Host 192.168.1.68
  User root
  Port 22
  IdentityFile ~/.ssh/192.168.1.68.pem
  StrictHostKeyChecking no
  UserKnownHostsFile /dev/null
これで、chef ユーザで、192.168.1.68 にssh接続する場合は、root ユーザを使用して鍵認証を行うようになります。
~/.ssh/config のパーミションを以下のように変更します。
$ chmod 600 ~/.ssh/config 
次に、テスト対象のサーバから秘密鍵を取得して保存します。
$ ssh 192.168.1.68 'cat /etc/ssh/ssh_host_rsa_key' > 192.168.1.68.pem
$ chmod 600 ~/.ssh/192.168.1.68.pem
これで、.ssh ディレクトリは、以下のようになります。
$ ls -l ~/.ssh
合計 12
-rw------- 1 chef chef 1675  8月  5 11:07 2013 192.168.1.68.pem
-rw------- 1 chef chef  137  8月  5 10:46 2013 config
-rw-r--r-- 1 chef chef 1182  8月  2 14:57 2013 known_hosts

3.2.テスト対象サーバ側の設定


root ユーザに公開鍵を設定します。
# cat /etc/ssh/ssh_host_rsa_key.pub > ~/.ssh/authorized_keys
# chmod 600 ~/.ssh/authorized_keys
これで、.ssh ディレクトリは、以下のようになります。
# ls -l ~/.ssh
合計 4
-rw------- 1 root root 382  8月  5 11:11 2013 authorized_keys

3.3.動作確認


管理サーバの chef ユーザで、以下のように、ssh コマンドを実行して パスフレーズ入力なしで接続できればOKです。
[chef@centos6g ~]$ ssh 192.168.1.68
Warning: Permanently added '192.168.1.68' (RSA) to the list of known hosts.
Last login: Mon Aug  5 11:13:21 2013 from centos6g
[root@centos6h ~]# id
uid=0(root) gid=0(root) 所属グループ=0(root)
[root@centos6h ~]#
これで、serverspec を実行すると以下のように表示されます。
まだ、テストケースをちゃんと作っていないのでエラーになってますが、ssh接続の設定前よりはエラーが減りました。
$ rspec spec
...F.F

Failures:

  1) Port "80"
     Failure/Error: it { should be_listening }
       netstat -tunl | grep -- :80\
       expected Port "80" to be listening
     # ./spec/192.168.1.68/httpd_spec.rb:13:in `block (2 levels) in <top (required)>'

  2) File "/etc/httpd/conf/httpd.conf"
     Failure/Error: it { should contain "ServerName 192.168.1.68" }
       grep -q -- ServerName\ 192.168.1.68 /etc/httpd/conf/httpd.conf
       expected File "/etc/httpd/conf/httpd.conf" to contain "ServerName 192.168.1.68"
     # ./spec/192.168.1.68/httpd_spec.rb:18:in `block (2 levels) in <top (required)>'

Finished in 0.35597 seconds
6 examples, 2 failures

Failed examples:

rspec ./spec/192.168.1.68/httpd_spec.rb:13 # Port "80"
rspec ./spec/192.168.1.68/httpd_spec.rb:18 # File "/etc/httpd/conf/httpd.conf"


4.テストケース作成


管理サーバのワークステーションにログインして、私の環境に合わせて、サンプルの ~/spec/192.168.1.68/httpd_spec.rb を修正します。
内容は以下のとおり。(赤字部分)
require 'spec_helper'

describe package('httpd') do
  it { should be_installed }
end

describe service('httpd') do
  it { should be_enabled   }
  it { should be_running   }
end

describe port(8888) do
  it { should be_listening }
end

describe file('/etc/httpd/conf/httpd.conf') do
  it { should be_file }
  it { should contain "ServerName 127.0.0.1" }
end

以下の項目をチェックします。
  • httpd パッケージがインストール済みであること
  • httpdサービスが自動起動設定済みであること
  • httpdサービスが実行中であること
  • ポートが 8888 であること
  • 設定ファイルのパラメータが指定どおりであること(上記、赤字部分)

5.テストの実行


管理サーバのワークステーションにログインして、serverspec を実行します。
$ rspec -fd --color spec

Package "httpd"
  should be installed

Service "httpd"
  should be enabled
  should be running

Port "8888"
  should be listening

File "/etc/httpd/conf/httpd.conf"
  should be file
  should contain "ServerName 127.0.0.1"

Finished in 0.26284 seconds
6 examples, 0 failures

"0 failures" であれば、テストOKです。