こんにちは!株式会社PeX の高橋です。

自分はサーバアプリエンジニアではありますが、Provisioning Frameworks Casual Talksなどの影響を受けて最近はProvisioning Framework力を強化中です。
Provisioningとはサーバをサービスが開始できるように設定する事で、Provisioning Frameworkはサーバの設定を自動化するためのフレームワーク(chef、puppet)の事となります。
本記事ではvagrantで作成した仮想環境に対して、chefでサーバ設定を行いSymfony2のwelcome画面を表示する事を行います。serverspecでテストが失敗する事を確認した後にサーバ設定を行い、テストが成功する事を確認するというテスト駆動的な手法を試してみました。 (mac推奨です!)

1. vagrantの準備

vagrantは仮想サーバ(virtualbox等)を操作するツールです。virtualboxとvagrantのインストールを行います。

virtualbox は下記からダウンロードしてインストール
https://www.virtualbox.org/

vagrantのインストールと設定
参考: vagrantの設定ファイル
// gemでvagrant 1.0系をインストール
$ sudo gem install vagrant --no-ri --no-rdoc
// 仮想環境のsnapshotを取得するためのプラグイン $ sudo vagrant gem install sahara // 今回のブログ用のコードを取得しvagrant用ディレクトリに移動 $ git clone https://github.com/taka512/techblog20130523.git $ cd techblog20130523/vagrant // OSイメージを追加して起動 $ vagrant box add centos63mini https://dl.dropbox.com/u/7225008/Vagrant/CentOS-6.3-x86_64-minimal.box $ vagrant init $ vagrant up // sandboxをonにします。 $ vagrant sandbox on // vagrantに接続するためのsshの設定を行います。 // ※念のため~/.ssh/configはバックアップを取っておきましょう $ vagrant ssh-config --host dev >> ~/.ssh/config
下記コマンドで仮想環境に接続できるようになっていれば成功です。
$ ssh dev

2. serverspecのインストールと実行

serverspecはサーバテスト用の機能を追加したrspecの拡張です。用意されたMatchersを利用する事でサーバのテストを簡潔に記述する事ができます。

現在のバージョン(0.4.9)に用意されている機能は下記となります。
  1. cronエントリのテスト
  2. コマンド実行結果のテスト
  3. ファイル/ディレクトリのテスト
  4. Linuxカーネルパラメータのテスト
  5. ネットワーク設定のテスト
  6. パッケージのテスト
  7. ポートのテスト
  8. SELinuxのテスト
  9. サービスのテスト
  10. ユーザ/グループのテスト
仮想環境にログインしていなければログインしてください。仮想環境にserverspecをインストールします。
// 仮想環境devで実行
$ sudo gem install serverspec --no-ri --no-rdoc
$ sudo gem install rake --no-ri --no-rdoc
$ sudo yum install -y git 
仮想環境でチェックアウトしたserverspec用ディレクトリに移動し、テストを実行するとテストが失敗する事を確認できます。
参考:serverspecでのテスト内容
// 仮想環境でのチェックアウト
$ git clone https://github.com/taka512/techblog20130523.git
$ cd techblog20130523/serverspec
// テストを実行 $ sudo rake spec ~略~ Failures: 1) Package "nginx" Failure/Error: it { should be_installed } # ./spec/localhost/nginx_spec.rb:4 ~略~

3. 手動でのサーバ設定

手動でサーバ設定を行う事でserverspecのエラーを解消します。手順的な物を下記に用意しました。(めんどくさかったら飛ばしてください!)
https://github.com/taka512/techblog20130523/blob/master/shell/install.txt

エラーが解消すると下記のようになります。
$ sudo rake spec
/usr/bin/ruby -S rspec spec/localhost/nginx_spec.rb spec/localhost/ntp_spec.rb spec/localhost/openssh_spec.rb spec/localhost/selinux_spec.rb spec/localhost/symfony_spec.rb spec/localhost/user_spec.rb
..................................................

Finished in 0.78146 seconds
50 examples, 0 failures
URLにアクセスすると画像のような画面が表示されれば成功です。
http://localhost:8080
2a7f41a8






4. chefからのサーバ設定

chefを利用したサーバ設定を行います。chefは大規模向けのchef-serverと中小規模向けのchef-soloの2種類が存在します。今回はchef-soloの方を利用します。
一旦仮想環境から抜けて下記コマンドを実行し、仮想環境を手動でのサーバ設定前の状態に戻します。
// 無慈悲な仮想環境のロールバック
$ vagrant sandbox rollback
仮想環境にログインして環境がロールバックしてテストがエラーになる事を確認します。
// 仮想環境にログイン
$ ssh dev

// 仮想環境がロールバックされたので再度serverspecをインストール
$ sudo gem install serverspec --no-ri --no-rdoc
$ sudo gem install rake --no-ri --no-rdoc
$ sudo yum install -y git

// 環境が戻ってテストがエラーになる事を確認
$ git clone https://github.com/taka512/techblog20130523.git
$ cd techblog20130523/serverspec
$ sudo rake spec
$ exit
仮想環境を抜けてmacにchef-soloの実行環境を準備します。 knifeはchefの管理コマンドでリモートでchefを実行するために必要なコマンドです。
参考: chefのレシピ
// ホストOSで実行
$ sudo gem install chef --no-ri --no-rdoc

// knife環境を準備
$ sudo gem install bundler --no-ri --no-rdoc
$ git clone http://github.com/matschaffer/knife-solo.git
$ cd knife-solo
$ bundle && bundle exec rake install
$ knife configure
$ vi ~/.chef/knife.rb # 下記1行を追加
cookbook_path [ './cookbooks', './site-cookbooks' ]
// 仮想環境にchef実行環境を準備
$ knife solo prepare dev // chefで環境を構築 $ git clone https://github.com/taka512/techblog20130523.git $ cd techblog20130523/chef $ knife solo cook dev
なんということでしょう。 さらっと環境が構築されてしまいました。
// 仮想環境でテストが通る事を確認
$ ssh dev
$ sudo rake spec

5. まとめ

serverspecを使ってみるとサーバ設定のユニットテスト的な使い方に良さげで扱いやすかったです。
アプリ側も昔(5~10年ぐらい前)はテストを記述するのが当たり前という風潮ではなかったと思いますが、今は小学生でもテストを書くよね!って風潮になってきていると思います。サーバ側もそんな時代が来るのかもしれないと思いました!

また、インフラとアプリエンジニアが分かれている会社の場合、アプリエンジニアにroot権限が無いため DevOpsと言いつつもインフラエンジニア任せになってしまっている現状があるかなと思います。
chefはサーバの状態をコードで表現できるので、コードの共有やpull requestでの修正取込等でDevOpsを進めやすくなると思います。
今後、弊社でも取り組んでみたいなと思いました。

参考
kayacでは新卒研修で取り入れているらしく、今回はその話に感化されて試してみました。
https://github.com/kayac/newbie-training
その他参考下記も参考にしました。
http://d.hatena.ne.jp/toritori0318/20130509/1368107821
http://tatsu-zine.com/books/chef-solo