More Related Content
Similar to serverspecでサーバ環境のテストを書いてみよう (20)
More from Daisuke Ikeda (20)
serverspecでサーバ環境のテストを書いてみよう
- 2. Agenda
● 1. 基本の紹介
○ serverspecとは何か?
○ 導入方法の紹介
○ 設定方法の紹介
○ テストコードの書き方
● 2. 簡単なデモ
○ テスト実行
○ 結果の表示
● 3. 属性情報の扱い方
○ 属性情報を外出しして実行
● 4. カスタマイズしてみる
○ NTP時刻同期状況テストを作ってみる
- 3. serverspecの基本
● serverspecとは?
○ サーバの状態をテストするためのフレームワーク
○ Ruby実装 (8/14時点最新version 0.7.8 ※日々バージョンアップするので注意)
○ Rspecに準拠した形式で記述が可能→Rspecに慣れた方ならすぐに書けるかも
○ ChefやPuppet等環境の自動構成管理ツールと組み合わせて使うのに最適
○ serverspecは構成管理ツールに依存せずにテストコードが書ける
○ テスト実行方法は2種類
■ ローカルに対してテスト実行
■ SSH接続してテスト実行
○ テストコードを1箇所で集約管理
○ ただ単にSSH接続して実行するので特別なAgentの導入の必要がない
- 5. serverspecの導入方法
● gemコマンドで簡単にインストール可
● インストール後、テストコード初期設定実施
$ gem install serverspec
$ 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.xxx.xxx
+ spec/
+ spec/192.168.xxx.xxx/
+ spec/192.168.xxx.xxx/httpd_spec.rb
+ spec/spec_helper.rb
+ Rakefile
- 6. ● 事前設定
○ 1.SSH接続設定
○ 2.sudo設定
SSH接続設定
●
● 1. 公開鍵のキーペア作成 (NoPasswordで)
● 2. テスト対象機器側の鍵認証設定
● 3. serverspec実行機器側での.ssh/config設定
serverspecの設定方法
$ vim .ssh/config
Host 192.168.xxx.xxx
HostName 192.168.xxx.xxx
Port 22
IdentityFile ~/.ssh/serverspec_test
User maintain
serverspec-init実行時に指定したホスト名と
一致するように設定
- 8. ● 重要なのはリソースタイプとマッチャー
● この組み合わせで様々なテストが記述できる
● リソースタイプ
○ command,cron,default_gateway,file,group,host,interface,ipfilter,ipnat,
iptables,kernel_module,linux_kernel_parameter,package,php_config,port,
routing_table,selinux,service,user,yumrepo,zfs
● マッチャー
○ 例:commandリソースタイプの場合
■ return_stdout:あるコマンド実行時の標準出力の文字列確認テスト
■ return_stderr:あるコマンド実行時の標準エラー出力の文字列確認テスト
テストコードの書き方
詳しくはこちら: http://serverspec.org/
- 10. ● ソースコードが非常に見やすい
1. どのリソースタイプか?
- インストールディレクトリ/serverspec-バージョン/lib/serverspec/type以下を確認
- 先述の例のテストの場合、package.rbを確認
2. どのマッチャーか?
- be_installedの場合、def installed?を確認
- この中に処理が記述
- def installed?の内部ではcheck_installedメソッドが呼ばれている
3. 実際の処理メソッドを確認
- check_installedメソッドを確認(commands/redhat.rb,debian.rb...)
- OS毎にテスト実行コマンドが違う場合はOS毎に用意されているファイルに
- OS共通のテスト実行コマンドの場合はcommands/base.rbに
ソースコードの追い方
- 11. ● テスト実行時に実際にはどんなコマンドが実行されているの?
○ RedHat系の場合(lib/serverspec/commands/redhat.rb)
○ Debian系の場合(lib/serverspec/commands/debian.rb)
テスト実行時のコマンド
def check_installed(package,version=nil)
cmd = "rpm -q #{escape(package)}"
if ! version.nil?
cmd = "#{cmd} | grep -w -- #{escape(version)}"
end
cmd
end
def check_installed(package,version=nil)
escaped_package = escape(package)
"dpkg -s #{escaped_package} && ! dpkg -s #{escaped_package} | grep -E '^Status: .+ not-
installed$'"
end
- 12. ● テスト実行時に実際にはどんなコマンドが実行されているの?
○ RedHat系の場合(lib/serverspec/commands/redhat.rb)
○ Debian系の場合(lib/serverspec/commands/debian.rb)
テスト実行時のコマンド
def check_installed(package,version=nil)
cmd = "rpm -q #{escape(package)}"
if ! version.nil?
cmd = "#{cmd} | grep -w -- #{escape(version)}"
end
cmd
end
def check_installed(package,version=nil)
escaped_package = escape(package)
"dpkg -s #{escaped_package} && ! dpkg -s #{escaped_package} | grep -E '^Status: .+ not-
installed$'"
end
- 13. ● 実行されるコマンドが何であるかを理解した上で書きましょう
○ httpdパッケージのインストールバージョンをテストする場合の例
■ 極端な例ですが、以下2つはどちらもテストOKになる
テストコード作成時の注意点
実際にインストールされているパッケージ
$ rpm -q httpd
httpd-2.2.15-15.el6.centos.x86_64
バージョン指定した場合に実行されるコマンド
$ rpm -q httpd | grep -w -- 指定した文字列
describe package('httpd') do
it { should be_installed.with_version('2.2') }
end
describe package('httpd') do
it { should be_installed.with_version('2.15') }
end
- 14. ● 実行方法
● ~/.rspecファイルを編集して表示を見やすく
● テスト失敗時、どういったコマンドが実行されのかが表示される
デモ
$ rake spec
--color
--format documentation(またはs)
色付けをして表示
実行結果を文字列表記
Failures:
1) Port "80"
Failure/Error: it { should be_listening }
sudo netstat -tunl | grep -- :80
expected Port "80" to be listening
# ./spec/192.168.xxx.xxx/httpd_spec.rb:13:in `block (2 levels) in <top (required)>'
実際に実行されたコマンド
- 17. ● サーバ毎に異なるApacheのバージョンのテストを実施する場合の例
2. RakefileをYAMLファイルのキーの項目毎にテスト実行できるよう編集
設定情報を外だし
require 'rake'
require 'rspec/core/rake_task'
require 'yaml'
attributes = YAML.load_file('attributes.yml')
desc "Run serverspec to all services"
task :spec => 'spec:all'
namespace :spec do
task :all => attributes.keys.map {|key| 'spec:' + key }
attributes.keys.each do |key|
desc "Run serverspec to #{key}"
RSpec::Core::RakeTask.new(key.to_sym) do |t|
ENV['TARGET_HOST'] = key
t.pattern = "spec/#{key}/*_spec.rb"
end
end
end
attrubutes.yml読込み
キー毎にspecを実行するよう変更
spec_helperで利用するため
環境変数にキー情報を登録
- 21. ● リソースタイプを追加
○ lib/serverspec/helper/type.rbにリソースタイプを追加
○ 今回はntpというリソースタイプを新たに追加
カスタマイズしてみる
4: types = %w(
5: base yumrepo service package port file cron command linux_kernel_parameter iptables host
6: routing_table default_gateway selinux user group zfs ipnat ipfilter kernel_module interface php_config ntp
7: )
ここにタイプを追加することで
serverspec/type/ntp.rbが読み込まれてリソースタ
イプが有効になる。
- 23. ● 実行コマンド処理を記述
○ lib/serverspec/commands/linux.rbに実際の処理内容を記述
○ 各OSに依存する処理を書きたい場合はredhat.rbとかdebian.rbとかOS毎の
ファイルに処理を記載
カスタマイズしてみる
def get_ntp_status_of(name)
"ntpq -p -n | grep #{name} | head -c1"
end
実際に実行されるコマンド
$ sudo ntpq -p -n
remote refid st t when poll reach delay offset jitter
==================================================================
*172.xx.xx.xx 172.xx.xxx.xx 6 u 248 1024 377 0.799 25.298 20.663
ここのステータス情報を取得