Serverspec 最初の一歩 @ AWS EC2


Serverspecとは

O'REILLY『Serverspec』P.5 によると以下の目的に使うサーバテストツールです。

  1. テスト駆動によるインフラコード開発
  2. サーバ構築後の確認作業の自動化
  3. 稼働しているサーバの監視
  4. サーバの再起動後の状態確認
  5. サーバのあるべき状態の抽象化

Chef, Puppet, Ansibleと合わせて使うと、TDD(テスト駆動)なインフラコード開発が可能になります。

対象読者

AWS EC2上でServerspecを体感してみたい初心者を対象としています。

  • 『Serverspec』を読んで、本に書いてある通りにコマンドを打っても動作しなかった人。
  • あらゆること(SSHでサーバー間の通信をする、Linuxのsudoはこう使うべき論、Rubyのgemはこう管理すべき論)を横に置いておいて、とにかくAWS EC2上でServerspecを走らせてみたい人。
  • サーバの管理を任されてしまった新人(Rubyの知識、RSpecの知識はあまりなし)。

が対象です。

今回は、ローカルサーバの状態をテストします。
利用するコマンドは、以下の3つです。
  ・ gem install
  ・ serverspec-init
  ・ rake spec

環境の準備

  • EC2のインスタンスを作成
    選択したインスタンスは以下です。
    「Amazon Linux AMI 2016.03.2 (HVM), SSD Volume Type - ami-6154bb00」
     
  • Serverspecインストール
    以下の流れでServerspecをインストールします。
    (1) ec2-userでEC2インスタンスにログイン
    (2) Amazon Linuxにrubyとgemがインストールされていることを確認
    (3) rootでRakeとServerspecをインストール
      インストールは、 gem install コマンドで行います。

    login as: ec2-user
    Authenticating with public key "imported-openssh-key"
    
           __|  __|_  )
           _|  (     /   Amazon Linux AMI
          ___|\___|___|
    
    https://aws.amazon.com/amazon-linux-ami/2016.03-release-notes/
    No packages needed for security; 2 packages available
    Run "sudo yum update" to apply all updates.
    [ec2-user@ip-172-31-24-21 ~]$ ruby -v
    ruby 2.0.0p648 (2015-12-16) [x86_64-linux]
    [ec2-user@ip-172-31-24-21 ~]$ gem -v
    2.0.14.1
    [ec2-user@ip-172-31-24-21 ~]$ sudo su -
    [root@ip-172-31-24-21 ~]# gem install rake
    Fetching: rake-11.2.2.gem (100%)
    Successfully installed rake-11.2.2
    Parsing documentation for rake-11.2.2
    Installing ri documentation for rake-11.2.2
    Done installing documentation for rake after 1 seconds
    1 gem installed
    [root@ip-172-31-24-21 ~]# gem install serverspec
    Fetching: rspec-support-3.4.1.gem (100%)
    Successfully installed rspec-support-3.4.1
    Fetching: rspec-core-3.4.4.gem (100%)
    Successfully installed rspec-core-3.4.4
    Fetching: diff-lcs-1.2.5.gem (100%)
    Successfully installed diff-lcs-1.2.5
    Fetching: rspec-expectations-3.4.0.gem (100%)
    Successfully installed rspec-expectations-3.4.0
    Fetching: rspec-mocks-3.4.1.gem (100%)
    Successfully installed rspec-mocks-3.4.1
    Fetching: rspec-3.4.0.gem (100%)
    Successfully installed rspec-3.4.0
    Fetching: rspec-its-1.2.0.gem (100%)
    Successfully installed rspec-its-1.2.0
    Fetching: multi_json-1.12.1.gem (100%)
    Successfully installed multi_json-1.12.1
    Fetching: net-ssh-3.1.1.gem (100%)
    Successfully installed net-ssh-3.1.1
    Fetching: net-scp-1.2.1.gem (100%)
    Successfully installed net-scp-1.2.1
    Fetching: net-telnet-0.1.1.gem (100%)
    Successfully installed net-telnet-0.1.1
    Fetching: sfl-2.2.gem (100%)
    Successfully installed sfl-2.2
    Fetching: specinfra-2.59.0.gem (100%)
    Successfully installed specinfra-2.59.0
    Fetching: serverspec-2.36.0.gem (100%)
    Successfully installed serverspec-2.36.0
    Parsing documentation for rspec-support-3.4.1
    Installing ri documentation for rspec-support-3.4.1
    Parsing documentation for rspec-core-3.4.4
    Installing ri documentation for rspec-core-3.4.4
    Parsing documentation for diff-lcs-1.2.5
    Installing ri documentation for diff-lcs-1.2.5
    Parsing documentation for rspec-expectations-3.4.0
    Installing ri documentation for rspec-expectations-3.4.0
    Parsing documentation for rspec-mocks-3.4.1
    Installing ri documentation for rspec-mocks-3.4.1
    Parsing documentation for rspec-3.4.0
    Installing ri documentation for rspec-3.4.0
    Parsing documentation for rspec-its-1.2.0
    Installing ri documentation for rspec-its-1.2.0
    Parsing documentation for multi_json-1.12.1
    Installing ri documentation for multi_json-1.12.1
    Parsing documentation for net-ssh-3.1.1
    Installing ri documentation for net-ssh-3.1.1
    Parsing documentation for net-scp-1.2.1
    Installing ri documentation for net-scp-1.2.1
    Parsing documentation for net-telnet-0.1.1
    Installing ri documentation for net-telnet-0.1.1
    Parsing documentation for sfl-2.2
    Installing ri documentation for sfl-2.2
    Parsing documentation for specinfra-2.59.0
    Installing ri documentation for specinfra-2.59.0
    Parsing documentation for serverspec-2.36.0
    Installing ri documentation for serverspec-2.36.0
    Done installing documentation for rspec-support, rspec-core, diff-lcs, rspec-expectations, rspec-mocks, rspec, rspec-its, multi_json, net-ssh, net-scp, net-telnet, sfl, specinfra, serverspec after 15 seconds
    14 gems installed
    

テストの作成

  • テスト作成コマンドを実行

    • serverspec-init コマンドでServerspecの実行に最低限必要なファイルを作成します。
    • このコマンドを実行すると対話的に選択肢がでてきます。
    • 「1) UN*X」「2) Exec (local)」を選択します。
    [root@ip-172-31-24-21 ~]# mkdir /etc/severspec
    [root@ip-172-31-24-21 ~]# cd /etc/severspec
    [root@ip-172-31-24-21 severspec]# serverspec-init
    Select OS type:
    
      1) UN*X
      2) Windows
    
    Select number: 1
    
    Select a backend type:
    
      1) SSH
      2) Exec (local)
    
    Select number: 2
    
     + spec/
     + spec/localhost/
     + spec/localhost/sample_spec.rb
     + spec/spec_helper.rb
     + Rakefile
     + .rspec
    
    
  • スペック ファイル
    「spec/localhost/sample_spec.rb」にサーバのテストが記載されています。
    内容は以下のようになっています。

    sample_spec.rb
    require 'spec_helper'
    
    describe package('httpd'), :if => os[:family] == 'redhat' do
      it { should be_installed }
    end
    
    describe package('apache2'), :if => os[:family] == 'ubuntu' do
      it { should be_installed }
    end
    
    describe service('httpd'), :if => os[:family] == 'redhat' do
      it { should be_enabled }
      it { should be_running }
    end
    
    describe service('apache2'), :if => os[:family] == 'ubuntu' do
      it { should be_enabled }
      it { should be_running }
    end
    
    describe service('org.apache.httpd'), :if => os[:family] == 'darwin' do
      it { should be_enabled }
      it { should be_running }
    end
    
    describe port(80) do
      it { should be_listening }
    end
    
    

     serverspec-init コマンドで作成したスペック ファイル(spec/localhost/sample_spec.rb)には様々なテストが記載されています。
     ただ、Amazon Linuxのos familyは、

    os[:family] == 'amazon'
    

    です。
     AWS EC2でServerspecのテストを実行すると、最後の3行だけが実行されます。

テストの実行

  • テストの実行
     /etc/severspec ディレクトリでテストを実行します。テストを実行するコマンドは、 rake spec です。

  • 失敗テスト

  • sample_spec.rb
    describe port(80) do
      it { should be_listening }
    end
    

     特に設定を変更していなければ、EC2のインスタンスは、22番ポートのみ開いてる状態です。80番ポートは開いていません。
     この状態でテストを実行(rake spec)させてみましょう。テストが失敗します。

    [root@ip-172-31-24-21 severspec]# rake spec
    /usr/bin/ruby2.0 -I/usr/local/share/ruby/gems/2.0/gems/rspec-support-3.4.1/lib:/usr/local/share/ruby/gems/2.0/gems/rspec-core-3.4.4/lib /usr/local/share/ruby/gems/2.0/gems/rspec-core-3.4.4/exe/rspec --pattern spec/localhost/\*_spec.rb
    
    Port "80"
      should be listening (FAILED - 1)
    
    Failures:
    
      1) Port "80" should be listening
         On host `localhost'
         Failure/Error: it { should be_listening }
           expected Port "80" to be listening
           /bin/sh -c netstat\ -tunl\ \|\ grep\ --\ :80\\\
    
         # ./spec/localhost/sample_spec.rb:27:in `block (2 levels) in <top (required)>'
    
    Finished in 0.022 seconds (files took 0.34902 seconds to load)
    1 example, 1 failure
    
    Failed examples:
    
    rspec ./spec/localhost/sample_spec.rb:27 # Port "80" should be listening
    
    /usr/bin/ruby2.0 -I/usr/local/share/ruby/gems/2.0/gems/rspec-support-3.4.1/lib:/usr/local/share/ruby/gems/2.0/gems/rspec-core-3.4.4/lib /usr/local/share/ruby/gems/2.0/gems/rspec-core-3.4.4/exe/rspec --pattern spec/localhost/\*_spec.rb failed
    
  • 成功テスト
     それでは、テスト スペック ファイルを編集して、今度は成功するテストに変更してみましょう。
     「spec/localhost/sample_spec.rb」の最後の3行を次のように変更します。

    sample_spec.rb
    describe port(22) do
      it { should be_listening }
    end
    
    describe service('ntpd') do
      it { should be_enabled }
      it { should be_running }
    end
    

    EC2のAmazon Linuxは、インスタンス生成直後は、以下の状態にあります。

    • 22番ポートが開いている
    • 「ntpd」サービスが利用可能
    • 「ntpd」サービスが稼働している

    この状態でテストを実行(rake spec)すると、3つのテストが成功します。

    [root@ip-172-31-24-21 localhost]# rake spec
    (in /etc/severspec)
    /usr/bin/ruby2.0 -I/usr/local/share/ruby/gems/2.0/gems/rspec-support-3.4.1/lib:/usr/local/share/ruby/gems/2.0/gems/rspec-core-3.4.4/lib /usr/local/share/ruby/gems/2.0/gems/rspec-core-3.4.4/exe/rspec --pattern spec/localhost/\*_spec.rb
    
    Port "22"
      should be listening
    
    Service "ntpd"
      should be enabled
      should be running
    
    Finished in 0.03241 seconds (files took 0.33734 seconds to load)
    3 examples, 0 failures
    

Nextステップ

次は、リモートマシンのテストをSSH経由で行います。
 ・Serverspec で AWS EC2 のリモートテスト