serverspec大規模システムでの設計のポイント


# 概要
serverspecがインフラ担当者に与えたメリットの一つは、
試験項目を設定ファイルとして作ることができるようになり、
試験項目の作成から設定ミスの発覚までの時間が非常に短時間で検知できるようになったことである。

serverspecはデフォルトの設定だと、サーバ単位で試験項目が作られることになる。
数台の運用であればそれでも問題ないが、大規模になるにつれて冗長が目立つようになり、メンテナンスも複雑になる。

そこで、serverspecの導入初期から考えたい、設計のポイントをまとめた。
インストール方法などについては割愛する。

#課題
server1のディレクトリに様々なserverspecの設定ファイルを起き、さまざまな試験を行うことが可能だが、
単純にサーバを追加していくとディレクトリを丸ごとコピーして必要なものを編集していく。という一昔前のありがちな運用になりかねない。

デフォルトのディレクトリ構成
serverspec
|--.rspec
|--Rakefile.group
|--spec
|  |--server1
|  |  |--cron_spec.rb
|  |  |--characterCode_spec.rb
|  |  |--interfaces_spec.rb
|  |  |--kernel_spec.rb
|  |  |--mail_spec.rb
|  |  |--port_spec.rb
|  |  |--resolv_spec.rb
|  |  |--selinux_spec.rb
|  |  |--user-group_spec.rb

#設計のポイント
冗長を無くし、あくまでもサーバを属性ごとにグループに分ける。
たとえば、server1というサーバは、
・linuxサーバであり、 
・mailサーバであり、
・サーバ固有の設定もある。
という場合。

新しく3つのディレクトリを作成し、
そこにそれぞれ入れていく。
今回はlinux、mail、server1というディレクトリを作成した。
それぞれ
linux... Linuxサーバ全体のチェック(カーネル、selinux、文字コードなど)
mail... メールサーバ特有の設定など(postfixの確認など)
server1(ホスト名)...IPアドレスやホスト名などサーバ単位で異なる設定を格納

上記はLinuxのメールサーバのチェックなので、上のように定義したが、
Webサーバだったら新たにwebサーバ用のディレクトリを作成し、そこにWebサーバ共通の設定を入れても良いと思う。


新ディレクトリ構成
/usr/local/src/serverspec
|--.rspec
|--Rakefile.group
|--spec
|  |--linux★新設
|  |  |--cron_spec.rb
|  |  |--characterCode_spec.rb
|  |  |--kernel_spec.rb
|  |  |--port_spec.rb
|  |  |--resolv_spec.rb
|  |  |--selinux_spec.rb
|  |  |--user-group_spec.rb
|  |--mail★新設
|  |  |--mail_spec.rb
|  |--server1★新設
|  |  |--interfaces_spec.rb


#Rakeファイルを修正
```Rakefile
require 'rake'
require 'rspec/core/rake_task'

hosts = [
  {
    :name   => 'server1',
    :roles  => %w(linux mail server1)
  },
]

hosts = hosts.map do |host|
  {
    :name       => host[:name],
    :short_name => host[:name].split('.')[0],
    :roles      => host[:roles]
  }
end

desc "Run specgroup to all hosts"
task :specgroup => 'specgroup:all'

namespace :specgroup do
  task :all => hosts.map { |h| 'specgroup:' + h[:short_name] }
  hosts.each do |host|
    desc "Run specgroup to #{host[:name]}"
    RSpec::Core::RakeTask.new(host[:short_name].to_sym) do |t|
      ENV['TARGET_HOST'] = host[:name]
      t.pattern = 'spec/{' + host[:roles].join(',') + '}/*_spec.rb'
    end
  end
end
```

http://mizzy.org/blog/2013/05/12/1/
serverspecの生みの親、mizzyさんのページを参考にRakefileを作り変えた。
実行する上で、spec_helper.rb は変更せずに実行できた。

サーバの追加やグループの追加をするたびに

```Rakefile
  {
    :name   => 'server1',
    :roles  => %w(linux mail server1)
  },
```
の項目を試験対象のホスト、所属するグループを追加するとよい。


#動作確認
```command
[root@serverspec serverspec]# rake -T
rake specgroup       # Run specgroup to all hosts
rake specgroup:server1  # Run specgroup to server1
[root@serverspec serverspec]#
```

#試験
```command
[root@serverspec serverspec]# rake specgroup:server1
File "/etc/sysconfig/i18n"
  should contain "LANG=\"ja_JP.eucjp\""
  should contain "SYSFONT=\"latarcyrheb-sun16\""

Cron
  should have entry "0 6 * * *  /usr/sbin/ntpdate -s timeserver"

Default Gateway
  ipaddress
    should eq "10.0.0.1"
  interface
    should eq "eth0"

Linux kernel parameters
  Linux kernel parameter "net.bridge.bridge-nf-call-ip6tables"
    value
      should eq 0
  Linux kernel parameter "net.bridge.bridge-nf-call-iptables"
    value
      should eq 0

Port "22"
  should be listening

File "/etc/resolv.conf"
  should contain "nameserver 10.0.0.2"

SELinux
  should be disabled

User "guest"
  should have uid 7777
  should have home directory "/home/guest"
  should have login shell "/bin/bash"

Package "postfix"
  should be installed

Port "25"
  should be listening

Default Gateway
  ipaddress
    should eq "10.0.0.1"
  interface
    should eq "eth0"

Interface "eth0"
  should have ipv4 address "10.0.1.1/22"
  speed
    should eq 100
```


#tips
試験項目については本家参照
http://serverspec.org/resource_types.html