serverspecでサーバ環境のテストを書いてみよう
Upcoming SlideShare
Loading in...5
×
 

serverspecでサーバ環境のテストを書いてみよう

on

  • 12,661 views

社内勉強会で発表した資料です。 ...

社内勉強会で発表した資料です。
serverspecの基本から属性値の管理、カスタマイズ方法まで紹介しています。
※2013/8/14 version 0.7.8時点の情報なので注意

Statistics

Views

Total Views
12,661
Views on SlideShare
12,574
Embed Views
87

Actions

Likes
40
Downloads
91
Comments
0

8 Embeds 87

https://twitter.com 27
http://feedblog.ameba.jp 23
https://openlink.to 18
http://ameblo.jp 8
http://kariblo.jp 4
http://blog.ameba.jp 4
http://ssecret.ameba.jp 2
http://secret.ameba.jp 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

serverspecでサーバ環境のテストを書いてみよう serverspecでサーバ環境のテストを書いてみよう Presentation Transcript

  • serverspecで サーバ環境のテストを書いてみよう TIS 池田 大輔( @ike_dai )
  • Agenda ● 1. 基本の紹介 ○ serverspecとは何か? ○ 導入方法の紹介 ○ 設定方法の紹介 ○ テストコードの書き方 ● 2. 簡単なデモ ○ テスト実行 ○ 結果の表示 ● 3. 属性情報の扱い方 ○ 属性情報を外出しして実行 ● 4. カスタマイズしてみる ○ NTP時刻同期状況テストを作ってみる
  • serverspecの基本 ● serverspecとは? ○ サーバの状態をテストするためのフレームワーク ○ Ruby実装 (8/14時点最新version 0.7.8 ※日々バージョンアップするので注意) ○ Rspecに準拠した形式で記述が可能→Rspecに慣れた方ならすぐに書けるかも ○ ChefやPuppet等環境の自動構成管理ツールと組み合わせて使うのに最適 ○ serverspecは構成管理ツールに依存せずにテストコードが書ける ○ テスト実行方法は2種類 ■ ローカルに対してテスト実行 ■ SSH接続してテスト実行 ○ テストコードを1箇所で集約管理 ○ ただ単にSSH接続して実行するので特別なAgentの導入の必要がない
  • serverspecの基本 ● どんな用途で使う? ○ 自動構築した結果、正しく稼働しているか確認 ○ 内部から見てどう動いているのかを確認するため、外から見てどうかは Zabbix等の監視ツールを利用 ■ ポートがリッスンしているか?iptablesでそのポートを開放する設定が されているか?はserverspecで確認 ■ 本当にそのポートにアクセスできるか?アクセスが拒否されるか?は 監視ツールで確認
  • 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
  • ● 事前設定 ○ 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実行時に指定したホスト名と 一致するように設定
  • sudo設定 ● SSHログイン後に実行されるテスト処理はsudoをつけて実行される ● 接続ユーザに対してsudo権限を付与(実行されるサーバ側で設定) ● serverspec実行サーバ上の環境変数指定 ● spec/spec_helper.rbを書き換えればパスワード認証のSSHログインも可能 serverspecの設定方法 # visudo maintain ALL=(ALL) NOPASSWD:ALL $ export SUDO_PASSWORD=”xxxxxxxx” or $ export ASK_SUDO_PASSWORD=1 sudo実行時のパスワードを環境変数にセット sudo実行時のパスワードを対話式入力有効化
  • ● 重要なのはリソースタイプとマッチャー ● この組み合わせで様々なテストが記述できる ● リソースタイプ ○ 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/
  • ● 例: 指定したパッケージがインストールされているかどうかのテスト テストコードの基本 $ vim spec/httpd_spec.rb require 'spec_helper' describe package('httpd') do it { should be_installed } end リソースタイプを指定 マッチャーを指定してテスト実行
  • ● ソースコードが非常に見やすい 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に ソースコードの追い方
  • ● テスト実行時に実際にはどんなコマンドが実行されているの? ○ 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
  • ● テスト実行時に実際にはどんなコマンドが実行されているの? ○ 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
  • ● 実行されるコマンドが何であるかを理解した上で書きましょう ○ 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
  • ● 実行方法 ● ~/.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)>' 実際に実行されたコマンド
  • ● テスト対象サーバ毎に変更する属性値を外だし管理可能 1. 属性値情報をまとめたYAMLファイル作成 2. RakefileをYAMLファイルのキーの項目毎にテスト実行できるよう編集 3. spec/spec_helper.rbを編集し、属性値を変数に格納 4. テストコード内部で3.で格納した変数を利用するよう変更 設定情報を外だし 詳しくはこちら: http://mizzy.org/blog/2013/05/12/2/
  • ● サーバ毎に異なるApacheのバージョンのテストを実施する場合の例 1. 属性値情報をまとめたYAMLファイル作成(attributes.yml) 設定情報を外だし 192.168.xxx.xxx: :apache_version: 2.2.15 192.168.yyy.yyy: :apache_version: 2.4.4 キー 属性値
  • ● サーバ毎に異なる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で利用するため 環境変数にキー情報を登録
  • ● サーバ毎に異なるApacheのバージョンのテストを実施する場合の例 3. spec/spec_helper.rbを編集し、属性値を変数に格納 設定情報を外だし require 'serverspec' require 'pathname' require 'net/ssh' require 'yaml' include Serverspec::Helper::Ssh include Serverspec::Helper::DetectOS include Serverspec::Helper::Attributes attributes = YAML.load_file('attributes.yml') RSpec.configure do |c| ・・・略 attr_set attributes[ENV['TARGET_HOST']] end attr_setで指定した キーの属性値を変数に格納
  • ● サーバ毎に異なるApacheのバージョンのテストを実施する場合の例 4. テストコード内部で3.で格納した変数を利用するよう変更 設定情報を外だし describe package('httpd') do it { should be_installed.with_version(attr[:apache_version]) } end attr[:属性名]という変数に値が格納
  • ● 簡単にカスタマイズすることも可能 ○ commandリソースを使えば任意のコマンド実行テストが可能だが ○ よく使うものは新たにリソースタイプ、マッチャーを作成すれば使い回しできる ● 参考例:ntpの時刻同期状況テストを新たに追加してみる ○ 目指す形 ■ テスト対象サーバ内の指定したntpサーバのステータスをテスト カスタマイズしてみる describe ntp('xxx.xxx.xxx.xxx') do its(:status) { should eq '*' } end
  • ● リソースタイプを追加 ○ 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が読み込まれてリソースタ イプが有効になる。
  • ● ntpリソースタイプの定義 ○ lib/serverspec/type/ntp.rbに定義内容を記述 カスタマイズしてみる module Serverspec module Type class Ntp< Base def status ret = backend.run_command(commands.get_ntp_status_of(@name)) val = ret[:stdout].strip val end end end end status情報を取得するためのメソッドを定義
  • ● 実行コマンド処理を記述 ○ 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 ここのステータス情報を取得
  • ● serverspecはサーバ内部の状況が正しいかどうかをテストす るフレームワーク ● ChefやPuppet等自動構築ツールに依存せず手軽に扱える ● SSHログインしてテスト実行することが可能なので複数サーバ のテストを統合管理可能 ● カスタマイズも容易にできるのでいろんな場面に適用も可 まとめ