目的
Test KitchenをつかってChefへ入門します。
Chefを使うとサーバの設定を自動化することができます。
Test KitchenはChefで利用するクックブックの統合テストを行うことができます。
Chefに入門する環境として初めからTest Kitchenを使うのが良いと感じたのでこの文書を作成しました。
関連: LT駆動開発10でTest KitchenではじめるChef入門という話をした。 - そんなこと覚えてない
環境構築
Chef DKのインストール
Chef DKはChefのクックブック開発する上で便利なものがまとめられています。
DKはDevelopment Kitの略です。
今回利用するTest KitchenはChef DKに含まれています。
Chef DKは https://downloads.chef.io/chef-dk/ よりダウンロードできます。
brewcaskを使用しているのであれば
$ brew cask install chefdk
でインストールすることが可能です。
$ chef -v
Chef Development Kit Version: 0.3.5
$ which chef
/usr/bin/chef
$ kitchen -v
Test Kitchen version 1.2.1
$ which kitchen
/usr/bin/kitchen
補足ですが、/usr
にインストールされて気持ち悪いかもしれませんが、実体は/opt/chefdk
にインストールされます。
$ ls -ll /usr/bin/chef
lrwxr-xr-x 1 root wheel 20 1 3 14:22 /usr/bin/chef -> /opt/chefdk/bin/chef
vagrantのインストール
Test KitchenのdriverはデフォルトでVagrantを利用します。
つまり、普通に使うとVagrantも使うことになります。
Vagrantのダウンロード
https://www.vagrantup.com/downloads.html
brewcaskを使用しているのであれば
$ brew cask install vagrant
でもインストールすることが可能です。
$ vagrant -v
Vagrant 1.7.2
プロジェクトの作成
Chefではクックブックという単位で開発していきます。
Chef DKに添付されているchef
コマンドのgenerate
サブコマンドを使用すると雛形が作成できます。
hello-chefというクックブックを作成してそこで作業してみましょう。
$ chef generate cookbook hello-chef
$ cd hello-chef
hello-chefというクックブックができたので、このディレクトリで作業を進めていきます。
Test Kitichenの設定
Testk Kitchnの設定は.kitchen.yml
に書きます。
generateコマンドで自動的に生成されています。
少し変更して、今回は下記のようにしました。
---
driver:
name: vagrant
provisioner:
name: chef_zero
platforms:
- name: ubuntu-14.10
suites:
- name: default
run_list: recipe[hello-chef::default]
attributes:
platformのcentosを削って、ubuntuの14.10を指定しました。
インスタンスの作成
Test Kitchenのインスタンスを作成してみましょう。
chef-clientを実行するための仮想マシンが生成されます。
Chef DKに開発を支援するchefコマンドがあるため、紛らわしくならないように、Chefを実行することを実際にサーバの設定をしてくれるコマンドのchef-clientと呼んでいきます。
インスタンスの作成にkitchen verify
コマンドを使用してみます。
このコマンドの実行は長いので、じっくり待つことになります。通信環境によりますが、15分かかりました。
$ kitchen verify
このコマンドを実行すると
- インスタンスを作成(setup)
- chef-clientを実行(converge)
- テストコードの実行(verify)
をしてくれます。
もしインスタンスを作成済みでchef-clientを実行であれば、テストコードの実行のみが実行されます。
また、作成したインスタンスはlistサブコマンドで確認できます。
$ kitchen list
Instance Driver Provisioner Last Action
default-ubuntu-1410 Vagrant ChefZero Verified
Last Actionでどこまで実行されているのか確認することができます。
作成するだけであればkitchen setup
コマンドがあります。
今回はなるべく全体像が把握できるようにverify
コマンドを利用しました。
作成したインスタンスにログインする
loginサブコマンドで作成したインスタンスにログインできます。
ログインしてchef-clientがインストールされているのかどうか確認してみます。
$ kitchen login default-ubuntu-1410
default-ubuntu-1410 $ /opt/chef/bin/chef-client -v
Chef: 12.0.3
Chefは/opt/chef
にインストールされています。
kitchen loginして実行するコマンドの戦闘にはdefault-ubuntu-1410 $
と記述しておきます。
chef-applyで遊んでみる
chef-clientは引数などが複雑なので、はじめはchef-applyを使ってChefを体験していきます。
まずはファイルを作成してみましょう。
chef-applyをつかってhello.txtを作成するには以下のコマンドを実行します。
default-ubuntu-1410 $ /opt/chef/bin/chef-apply -e 'file "hello.txt" do content "Hello, World\n" end'
chefは/opt/chef
にインストールされていて、環境変数PATHが設定されていないので、フルパスでコマンドを実行しています。
Recipe: (chef-apply cookbook)::(chef-apply recipe)
* file[hello.txt] action create
- create new file hello.txt
- update content in file hello.txt from none to 77df26
--- hello.txt 2015-01-03 02:34:39.707849381 +0000
+++ ./.hello.txt20150103-2182-1a8z2qa 2015-01-03 02:34:39.707849381 +0000
@@ -1 +1,2 @@
+Hello, World
Hello.txtが作成できています。中身を確認してみます。
$ cat hello.txt
hello,world
レシピファイルの作成
ワンライナーでファイルを作成しましたが、見通しが悪いのでファイルに書いてみます。
ローカルマシンのrecipe/hello.rb
に書いてみましょう。
このhello.rbをレシピファイルと呼びます。
file 'hello.txt' do
content "Hello, World\n"
end
recipe/hello.rb
を仮想マシンにアップロードするにはkitchen convege
コマンドを利用します。
$ kitchen converge
本来はchef-clientを実行するコマンドですが、クックブックの同期が行なわれるのを利用しています。
このコマンドを実行すると/tmp/kitchen/cookbooks/hello-chef/recipes
にファイルが転送されています。実行してみましょう。
default-ubuntu-1410 $ /opt/chef/bin/chef-apply /tmp/kitchen/cookbooks/hello-chef/recipes/hello.rb
Recipe: (chef-apply cookbook)::(chef-apply recipe)
* file[hello.txt] action create (up to date)
長いですが、パスを省略してかけばchef-apply hello.rb
をしているだけです。
変更がないと、面白みがないのでファイルの中身を変更してみましょう。
file 'hello.txt' do
content "Hello, Chef\n"
end
contentに指定した文字列がファイルの中身になります。
さて、レシピファイルを転送しましょう。
$ kitchen converge
レシピファイルを実行します。
default-ubuntu-1410 $ /opt/chef/bin/chef-apply /tmp/kitchen/cookbooks/hello-chef/recipes/hello.rb
Recipe: (chef-apply cookbook)::(chef-apply recipe)
* file[hello.txt] action create
- update content in file hello.txt from 8663ba to c634c3
--- hello.txt 2015-01-03 06:59:34.007560036 +0000
+++ ./.hello.txt20150103-5116-1bfkldm 2015-01-03 07:07:02.527169431 +0000
@@ -1,2 +1,2 @@
-Hello, World
+Hello, Chef
実行できました。中身がHello, Chef
に変更されています。
ところで、hello.rbはhello-chefクックブックのレシピなります。
このレシピを指すのにrecipe[hello-chef::hello]
と表現することができます。
省略してhello-chef::hello
レシピと呼ぶことがあります。
ランリストの設定
converge
サブコマンドを実行した際に実行するレシピを設定することができます。
この設定は.kitche.yml
に設定します。
「実行するレシピの一覧」をランリストと呼びます。
.kitchen.yml
にrun_list
という項目があります。
run_list:
- recipe[hello-chef::default]
hello-chef::default
が設定されています。
hello-chef::hello
も加えてみます。
run_list:
- recipe[hello-chef::default]
- recipe[hello-chef::hello]
変化がわかるようにhello.rb
も書き換えておきましょう。
file 'hello.txt' do
content "Hello, Cookbook\n"
end
変更したらconverge
サブコマンドを実行してみます。
$ kitchen converge
hello.txtを確認してみます。
default-ubuntu-1410 $ cat hello.txt
Hello, Chef
変化していません。
ktichen convergeコマンドを使用した際には/
ディレクトリが基準になるので作成したファイルは/hello.txt
になります。
default-ubuntu-1410 $ cat /hello.txt
Hello, Cookbook
仮想マシン上でレシピを実行したい場合は、下記コマンドを実行します。
$ sudo chef-client -z -j /tmp/kitchen/dna.json -c /tmp/kitchen/client.rb
何が起きているのか詳細を知りたい場合は、各ファイルの中身やオプションの意味を調べてみてください。
蛇足ですが、Chefの入門が難しく感じるのは、初めて挑戦する時に指定するオプションが多いのが原因な気がします。
テストコードを書いてみる
Test Kitchenは統合テストを行うツールなので、テストコードを記述するとテストを実行することができます。
折角なので書いてみましょう。
今回はServerspecを使います。
test/integration/default/serverspec
ディレクトリにhello_spec.rbを作成してみます。
ファイルを作成する位置に意味があるので、同じファイル名にすることをおすすめします。
$ mkdir -p test/integration/default/serverspec
require 'serverspec'
set :backend, :exec
describe 'Hello Chef' do
describe file('/hello.txt') do
it { should contain('Cookbook') }
end
end
/hello.txt
の中に「Cookbook」という文字列が含まれているか確認するテストを書きました。
Serverspecをここまで利用していなかったので、仮想マシンがServerspecを使えるように設定されていません。
setup
サブコマンドを実行すると必要なものがインストールできます。
$ kitchen setup
verify
サブコマンドを実行した際に一度setup
サブコマンドは自動で実行されていますが、その際はServerspecが不要だったためインストールされていませんでした。明示的にkitchen setup
コマンドを呼ぶことで再度セットアップすることができます。
テストを実行するにはverify
サブコマンドを実行します。
$ kitchen verify
Hello Chef
File "/hello.txt"
should be file
Finished in 0.09 seconds (files took 0.27225 seconds to load)
1 example, 0 failures
Finished verifying <default-ubuntu-1410> (0m1.99s).
Attributesを使う
レシピファイルの中で変数を使いたいことがあります。
変数のように値を差し替えるような機能があるとレシピを変更せずに作成するファイルの内容を調整することができるようになります。
この機能がAttributesです。
Test Kittchenでは.kitchen.yml
ファイルでattributeを設定しておくことができます。message
という値を設定してみます。
attributes:
message: "World!!"
レシピファイルの中でmessageの値を利用するにはnode.message
になります。
実際に使ってみます。
file 'hello.txt' do
content "Hello, #{node.message}\n"
end
レシピを実行します。
$ kitchen converge
テストを実行してみます。
$ kitchen verify
Hello Chef
File "/hello.txt"
should contain "Cookbook" (FAILED - 1)
Failures:
1) Hello Chef File "/hello.txt" should contain "Cookbook"
Failure/Error: it { should contain('Cookbook') }
expected File "/hello.txt" to contain "Cookbook"
/bin/sh -c grep\ -qs\ --\ Cookbook\ /hello.txt\ \|\|\ grep\ -qFs\ --\ Coo
kbook\ /hello.txt
# /tmp/busser/suites/serverspec/hello_spec.rb:7:in `block (3 levels) in <to
p (required)>'
Finished in 0.10098 seconds (files took 0.28348 seconds to load)
1 example, 1 failure
/hello.txt
の中身が変更されてテストが失敗します。
ファイルに「Cookbook」という文字がなくなったためです。
hello_spec.rb`を修正しておきます。
require 'serverspec'
set :backend, :exec
describe 'Hello Chef' do
describe file('/hello.txt') do
it { should contain('World') }
end
end
$ kitchen verify
なれてきたらテストファーストでやってみると良いと思います。
通しでテストする
仮想マシンをいろいろ操作した上でテストを実行しています。
仮想マシンを起動してレシピを実行するだけで本当にテストが成功するのでしょうか?
test
サブコマンドを利用すると一旦すべて破棄して仮想マシンをつくるとこらか確認してくれます。
$ kitchen test
終了したら仮想マシンが削除されてしまいます。
残したい場合は--destroy=never
オブションを使います。
より詳細は、test-kitchenのつかいかた - Qiitaを参照してください。
補足
インスタンスが停止しているとき
「マシンを再起動しちゃってインスタンスが止まちゃってるよ!」なんてことがあると思います。
.kitchen/kitchen-vagrant/default-ubuntu-1410/
にVagrantfileがあるので、
$ cd .kitchen/kitchen-vagrant/default-ubuntu-1410/
$ vagrant up
とすれば大丈夫です。
すっきりさせたい場合はkitchen destroy
してしまう荒技もあります。もちろんsetupからやりなおすことになります。
まとめ
Chefに挑戦する際にTest Kitchenを使うと仮想マシンのセットアップをしてくれるのでChef入門しやすくなるのではないかと思って書いてみました。
しかも、Test Kitchenを使ってChefを始めるとテストコードを書く環境も整っています。
レシピに書いたfile
などのサーバに変化を与える命令はResoucesと言います。
その他の命令を確認したい場合はResources and Providers Reference — Chef Single-page Topicsを見てください。
Chefを使っていく上で知っておいたほうが良いことは他にもありますが、まずは最初の敷居を下げることができたら良いと思います。
作成したクックブックを実際のサーバにknife zeroで適用するところも書きたいですが長くなりそうなので持ち越します。