Serverspecの概要からインストールまで

2014年8月1日(金)
池田 大輔

Serverspecのインストール

ServerspecはRubyのgemパッケージとして配布されています。そのため、RubyおよびRubygemsがインストールされている環境であれば、以下のコマンドだけでインストール完了です。

    $ sudo gem install serverspec

このコマンドを実行すると、Specinfraなどの依存するパッケージもすべてインストールされます。

Serverspecの初期化処理

Serverspecの実行元サーバ上で初期化処理(serverspec-init)を行います。

    $ serverspec-init
    Select OS type:

      1) UN*X
      2) Windows

    Select number: 1  ←テスト対象サーバのOS種別を選択

    Select a backend type:

      1) SSH
      2) Exec (local)

    Select number: 1  ←テスト実行のタイプを選択

    Vagrant instance y/n: n ←Vagrantの管理下のインスタンスかどうかを選択
    Input target host name: server-01 ←テスト対象サーバのホスト名を入力
     + spec/
     + spec/server-01/
     + spec/server-01/httpd_spec.rb
     + spec/spec_helper.rb
     + Rakefile

上記はLinuxマシン(server-01)に対してSSH接続でテストする場合の実行例です。Windowsマシンに対してWinRM接続でテストする場合には、OS typeを「2) Windows」、backend typeを「1) WinRM」に設定して初期化します。

この初期化処理により、テスト実行に最低限必要なファイル群が生成されます。そのうちの1つであるspec_helper.rbの中には、対象サーバに接続するための設定が含まれます。そのため、初期化実行時の選択内容に応じてspec_helper.rbの中身が変わります。実際のテストコードは生成された「spec//」ディレクトリの中のxxx_spec.rbです。serverspec-initを実行するとデフォルトでApache HTTP Serverのテストコードであるhttpd_spec.rbがサンプルとして作成されます。

接続設定

先述した通り、Serverspecをリモートにあるサーバに対して実行する場合には接続設定が必要となります。

SSH接続の場合

SSH接続の場合には、セキュリティ面を考慮して、公開鍵認証での接続を利用することをお勧めします。

テスト対象のサーバに公開鍵認証での接続設定をした上で、Serverspec実行元サーバに対して以下の設定を実施します。まずServerspecを実行するユーザが、対象サーバにSSH接続する際に秘密鍵を読み込んで接続できるようにするため、SSH接続を設定します。Serverspecでは、初期化処理時に設定したホスト名をもとに対象サーバに接続します。そのため、そのホスト名でのSSH接続時に作成した秘密鍵を読み込んで接続を実行できるようSSHクライアントを設定します。たとえば、ホームディレクトリ以下の.ssh/configに以下のように記述します。

    Host server-01
      HostName 10.0.0.10
      Port 22
      User user1
      IdentityFile ~/.ssh/serverspec-key

こうすることで、Serverspecがspec/server-01ディレクトリ以下のテストコードを実行する際、server-01にuser1というユーザ名で~/.ssh/serverspec-keyという鍵ファイルを使って接続を試みることになります。また接続時にインタラクティブにパスワード入力を求められないよう、事前にパスフレーズなしで公開鍵認証できるように設定しておきます。

WinRM接続の場合

WinRMの場合、テスト実行対象のWindowsマシンにてwinrm qcコマンド等を利用してWindows Remote Managementサービスを起動し、WinRMの接続設定を実施します。

Serverspec実行元サーバには、WinRM接続用に追加でwinrmというgemパッケージをインストールします。

    $ sudo gem install winrm

serverspec-init実行時にWinRMで実行するように進めると以下のようなspec_helper.rbが作成されます。

    require 'serverspec'
    require 'winrm'

    include SpecInfra::Helper::WinRM
    include SpecInfra::Helper::Windows

    RSpec.configure do |c|
      user = <user name>
      pass = <password>
      endpoint = "http://<hostname>:5985/wsman"

      c.winrm = ::WinRM::WinRMWebService.new(endpoint, :ssl, :user => user, :pass => pass, :basic_auth_only => true)
      c.winrm.set_timeout 300 # 5 minutes max timeout for any operation
    end

ここにWinRM接続情報を記述することで、Windowsマシンに対して接続してテストを実行できます。

sudo実行設定

テスト実行対象サーバがLinuxマシンの場合、稼働状況の確認用のコマンドを実行する際に「sudo」をつけて実行する仕様となっています。そのため、先述の接続設定の時に指定したユーザに対してsudoの実行権限を付与する必要があります。テスト実行対象サーバ内で、以下の設定を実施します。

    # visudo

    user1   ALL=(ALL)       ALL

上記のように設定すると、sudo実行時にユーザのパスワードを聞かれます。パスワードについてはSUDO_PASSWORD環境変数に設定するか、環境変数にパスワードを設定したくない場合には、ASK_SUDO_PASSWORD環境変数を1に設定することでServerspec実行時にインタラクティブにパスワード入力を求められるようになります。

テストコードの作成

実行したいテストコードはserverspec-init実行時に作成されたフォルダの中に作成します。フォルダ構成としては以下のような形となります。

    Rakefile
    spec/
        - spec_helper.rb
        - server-01/
            - httpd_spec.rb
            - xxx_spec.rb
            ・・・・
        - server-02/
        ・・・・

Serverspecのテスト実行時の読み込みファイルの設定等は、Rakefileにて定義されています。標準のRakefileの記述では、specディレクトリ以下の各ディレクトリ内のxxx_spec.rbという名前のファイルが読み込まれて、順次テストが実行されるようになっています。

標準のRakefileの内容

    require 'rake'
    require 'rspec/core/rake_task'

    RSpec::Core::RakeTask.new(:spec) do |t|
      t.pattern = 'spec/*/*_spec.rb'
    end

    task :default => :spec

そのためテストコードを追加作成する場合は、xxx_spec.rbのような名前でファイルを作成して「spec/接続先サーバ名ディレクトリ/」以下に配置します。テストコードのファイルは、Webサーバやデータベースサーバ、セキュリティ設定関連のテストというように、テストの種類毎に分類して作成するなど、環境にあわせて管理しやすい形で分割することをお勧めします。またRakefileの内容を修正すれば、特定のディレクトリ以下のテストコードのみ実行するなどの応用も可能です。

テスト実行

Serverspecのテストを実行するためには、rakeコマンドを利用します。先述したRakefileにタスクが定義されています。rakeコマンドを利用することで、この記述に従ってテストコードの内容が実行されます。標準のRakefileには「spec」という名前のRakeタスクが定義されていて、これを実行することで先述した通りに各テストコードが実行される仕組みになっています。

    $ rake spec

また特定のテストファイルのみ実行したければ、rspecコマンドを利用して以下のようにテストファイルを指定します。

    $ rspec spec/server-01/httpd_spec.rb

Serverspecの出力は、デフォルトではテスト結果が正常なら「.」のみ、失敗した場合には「F」とその状況が表示される形式となっています。より詳細に実行結果を表示したい場合には、Serverspecの実行元サーバにてテストを実行するユーザのホームディレクトリ直下に以下のようなファイルを作成します。

    $ vim ~/.rspec
    --format documentation

これにより、テスト結果の出力は以下のようになります。

    $ rake spec

    Package "python"
      should be installed

    Finished in 0.24518 seconds
    1 examples, 0 failures

テストコードの記述方法

テストコードは「ResourceType」と「Matcher」の2つの要素から成り立っています。

ResourceType

ResourceTypeはテストの対象となるリソースを定義します。標準でサポートしているResourceTypeはこちらにまとめられています。サーバ内のファイルやプロセス、パッケージなどがResourceTypeに相当します。

Matcher

MatcherとはResourceTypeの状態を定義するもので、ResourceTypeの種類毎にサポートされるMatcherは異なります。ResourceType一覧のページに、各Matcher毎の例がまとめられています。

テストコードの書式

テストコードの書式は以下のようになります。

例1:「◯◯◯が△△△であるべきである」という形のテスト

具体例として、「pythonというパッケージ」が「インストールされているべきである」というテストコードは以下のようになります。

    require 'spec_helper'

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

例2:「◯◯◯の□□□が△△△であるべきである」という形のテスト

具体例として、「server-01というホスト」の「IPアドレス」が「10.1.1.2であるべきである」というテストコードは以下のようになります。

    require 'spec_helper'

    describe host('server-01.example.com') do
      its(:ipaddress) { should eq '10.1.1.2' }
    end

このようにServerspecのテストコードはRSpec形式の記法となっており、テストしたい内容を非常に読みやすい形で記述できます。

まとめ

ServerspecはChefやAnsibleによる自動処理とセットで活用することで、非常に効果を発揮するテストフレームワークです。迅速で正確な環境セットアップに欠かせないものではないでしょうか。内部の仕組みや利用方法についても、本記事で紹介したように非常にシンプルになっています。「構築したつもりだったが設定漏れがあり、障害の原因となった」といった苦い経験をされたことがある方は、ぜひお試しいただくことをお勧めします。今回は、仕組みや基本的な利用の流れについて触れました。次回は、より具体的なケースをもとにテストコードの書き方を解説します。

TIS株式会社

Twitter : @ike_dai
TIS株式会社OSS推進室所属。社内向けシステムの保守運用業務を経験後、クラウド時代の効率的な統合運用管理をテーマに活動中。特に、OSSを駆使した運用のエコシステム実現を目指し、Zabbix,fluentd,Serverspec,Ansibleなどの導入や検証に取り組む。技術検証成果などを技術ブログ『Tech-Sketch』にて発信中。著書:『Zabbix統合監視徹底活用 - 複雑化・大規模化するインフラの一元管理』

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています