こんにちは。斎藤です。
Chefで構築の自動化ができる事はわかっていても、Cookbookをどう記述すればいいのかピンとこない場合があります。そんなときに使えそうなコツをピックアップしてみました。
「Chefを使ってみたいけどいまいちとっかかりがわかりづらい」「あれ、これはどうやるんだ?」、そんなときにご覧頂けたら幸いです。
※Chef 10.16.2で確認しました。また、RHEL, CentOSで利用する事を前提に説明しています。
Cookbookに同梱したRPMファイルから直接インストールする
cookbook_fileとpackageリソースを組み合わせて実行します。
下記の例は、MySQLサーバをRPMファイルを用いてインストールします。
- "MySQL-server-5.5.29-1.el6.x86_64.rpm"ファイルをあらかじめ "files/default" 内に保存します。
- recipeを次の通り記述します。
ファイルは/tmpに展開されたあと、サーバにインストールされます。
checksumはsha256です。"shasum -a 256 [FILENAME]"で取得できます。無くても良いのですが、ファイルの破損や改ざんをチェックできるよう入れると良いかと思います。
filename = "MySQL-server-5.5.29-1.el6.x86_64.rpm"
file_checksum = "bce0132e86a23b19e1ba229e0411de39cdbde538f922c244d056ecaf3f054cb1"
cookbook_file "/tmp/#{filename}" do
source "#{filename}"
checksum "#{file_checksum}"
end
package "MySQL-server" do
action :install
provider Chef::Provider::Package::Rpm
source "/tmp/#{filename}"
end
リモートサーバにあるtarファイルを展開する
remotefileとscriptリソースを組み合わせて実行します。remote_fileは、リモートサーバにあるファイルをhttp経由で取得し、指定した場所に保存します。scriptリソースを使うと、ChefのDSLだけでは実行できない処理を実現できます。なお、scriptにはPerl, Python, Ruby, cshも利用できます。
下記の例は、Wordpressのソースコードを展開しています。
filename = "wordpress-3.5.tar.gz"
install_dir = "/var/www/html"
remote_uri = "http://wordpress.org/wordpress-3.5.tar.gz"
file_checksum = "def1d094dbd3fcc52208d4e63ae4c31901dfd97e9b4cd619b7d017fd342972ab"
remote_file "/tmp/#{filename}" do
source "#{remote_uri}"
checksum "#{file_checksum}"
end
script "install_wordpress" do
interpreter "bash"
user "root"
code <<-EOL
install -d #{install_dir}
tar zxvf /tmp/#{filename} -C #{install_dir}
EOL
end
条件に合致したときのみ実行する
not_ifとonly_ifがあります。only_ifは評価結果がtrue(return値が0)の時に実行、not_ifはonly_ifの逆です。
下記の例は、"db-"とつくホスト名のサーバのみにmysql-serverパッケージをインストールします。
package "mysql-server"
action :install
only_if "echo $(hostname) | grep -q 'db-'"
end
あるリソースが実行されたときのみに実行する
例えば、パッケージのインストールが実行されたときのみ、合わせて実行したいリソースを紐づけるときに用います。
1点、注意があります。合わせて実行したいリソースのアクションは、nothingとします。入れ忘れてしまうと毎回動いてしまいますので、気をつけてください。
下記の例は、MySQLをインストールしたときだけ、my.cnfを作成します。既にインストールされている場合は、my.cnfは作成されません。手元で2回実行して試してみてください。
template "/etc/my.cnf" do
source "my.cnf.erb"
mode 0644
owner "root"
group "root"
action :nothing
end
package "mysql-server" do
action :install
notifies :create, resources( :template => "/etc/my.cnf" )
end
なお、複数のリソースを実行したい場合は、実行したい順にnotifies属性を増やせばOKです。
ファイルをコピーする
ファイルをコピーするとき、executeやscriptリソースを用いてシェルを呼び出す方法がありますと、fileリソースを用いる方法もあります。
fileリソースを用いた方法は、実行直前にファイルの有無を確認して実行でき、ファイルが無い場合のエラーをハンドリングしやすくなります。
file "/var/www/html/index.html" do
content IO.read( "/tmp/hoge.html" )
end
ループする
同じ処理を繰り返すときに便利です。
%w{
bzip2
curl
dmidecode
}.each do |pkgname|
package "#{pkgname}" do
action :install
end
end
構文チェック
Cookbookの構文チェックを行う事ができます。
$ knife cookbook test mysql-server
checking mysql-server
Running syntax check on mysql-server
Validating ruby files
Validating templates
Dry Run (whyrun)
chef-soloでは、Dry Run(空実行)を行えます。Cookbookの実行時エラーが出ないかをある程度調べる事が出来ます。オプションは"-W"または"--why-run"になります。
注意点があります。remote_fileやcookbook_fileなど、Cookbook実行中の状態遷移に依存するリソースは、「ファイルが無い」などの実行時エラーになります。本記事では「Cookbookに同梱したRPMファイルから直接インストールする」と「リモートサーバにあるtarファイルを展開する」が、それにあたります。こればかりは、実際に実行してみないとわかりません。
$ chef-solo -W
絞って実行
chef-soloでは、指定したCookbookのみを実行する事が出来ます。オプションは"-o"です。roleやrun_listにリストアップされているCookbookを絞って再実行したい場合に用います。
$ chef-solo -o mysql-server
最後に
初めてChefに取り組まれる方は、ぜひchef-soloで試してみてください。Chefサーバを立ち上げて利用するとなると、準備にchef-soloを用いるより時間がかかります。また、デバッグもchef-soloのほうが比較的行いやすいかと思います。
使い方は、Web上にある事例やOpscodeにあがっているCookbookを読むことで、手っ取り早く理解できました。最後に、よくよくドキュメントを読むと良いのではないでしょうか。
それでは、ごきげんよう。
参考文献
Chef Documentation - http://docs.opscode.com/