===========================================
前回はサンプルクックブックのレシピを作りました。今回はその続きです。
とりあえず、新しいクックブックで始めましょう。
$ knife cookbook create resource-sample -o site-cookbooks
リソース(Resource)とは
レシピ(recipes/以下のRubyスクリプト)はリソースを記述することで構成されます。
前回の実行結果にあるように、default.rb では3つのリソースを定義しており、種類としては directory
と file
の2つです。
directory "/tmp/hoge" do
# 状態・アクション・属性の定義
end
file "/tmp/hoge/ipaddress.txt" do
# 状態・アクション・属性の定義
end
これ以外にも様々なリソースが予め定義されています。
以下のサイトをリファレンスとして参照してください。
http://docs.getchef.com/chef/resources.html
リソースはクックブックの中で定義することができますが、まずは既存のリソースを使ってみましょう。
代表的なリソースとサンプル
代表的なリソースをサンプルとして書いてみます。
site-cookbooks/resource-sample/recipes/default.rb
に追記しながら試してみてください。
user, group : Unixシステムのユーザ管理
サーバ内のユーザとグループを定義します。
#
# someone グループを id=1234 で作成
#
group "someone" do
action :create
gid 1234
end
#
# someone ユーザを id=1234 で someone グループに所属させて作成
# ホームディレクトリ /home/someone に作成する
# シェルは /bin/bash
#
user "someone" do
action :create
password "$1$y0mNscmC$LDkzLErL355w0T5mhVJ3C1" # openssl passwd -1 hogehoge
uid 1234
gid "someone"
home "/home/someone"
shell "/bin/bash"
supports { :manage_home => true }
end
#
# app ユーザをシステムユーザとして作成
#
user "app" do
uid 2345
system true
shell "/bin/false"
end
ユーザに関する属性値を記述できます。
ユーザのパスワードはハッシュ化された値で登録します。openssl
コマンドがあれば openssl passwd -1
で生成できます。
既に存在するユーザであっても、パスワードの変更や起動シェルなど属性の違いがあれば修正されます。
file, remote_file, cookbook_file
ファイルを管理するリソースです。
-
file
: サーバ内の指定されたパスのファイルの内容、パーミッション、ユーザ等を管理する -
remote_file
: URLから指定されたパスにファイルをダウンロードする -
cookbook_file
: cookbookのfiles/
ディレクトリ以下に予め用意されたファイルを指定されたパスに置く
共通することは、ファイルのチェックサムを比較して差分がなければ何もしないという点です。自動的に冪等性が担保されます。
#
# file: サーバ内のファイルを定義する
#
file "/tmp/platform.txt" do
content "platform: #{node[:platform]}"
mode 0644 # 注: 0644は8進数表記。644だと違う意味になってしまう。文字列で"644"の方がミスしにくい。
owner "root"
end
# 不必要なファイルが存在しない状態を定義する。削除するというタスクではないことに注意。
file "/tmp/unused.txt" do
action :delete
end
#
# remote_file: インターネット上のファイルをダウンロードして保存する
#
remote_file "/tmp/resource.html" do
source "http://docs.getchef.com/chef/resources.html"
mode "644"
owner "someone"
end
#
# cookbook_file: クックブック内のfiles/からファイルをコピーする
#
cookbook_file "/tmp/cookbook_file_sample.sh" do
mode "0755"
end
cookbook_file
で配置するファイルはfiles/default/
以下に同名(ここでは cookbook_file_sample.sh
)で配置します。
# !/bin/sh
echo "Copied by cookbook_file."
別名でも良いですが、その場合は属性で指定が必要です。詳しくはリファレンスを見てください。
template
cookbook_file
リソースと似ているが、テンプレートファイルを差し替えてから配置できます。
template "/tmp/template-sample.txt" do
mode "644"
owner "someone"
end
テンプレートファイルはtemplates/default/
以下に配置します。ファイル名は差し替えるファイル名に.erb
をつけたもの(ここではtemplate-sample.txt.erb
)です。
差し替えはerbで行われます。詳細についてはこちらを参照してください。
platform: <%= node[:platform] %>
<% if 1 == 0 %>
!?
<% else %>
OK
<% end %>
directory
読んで字のごとくディレクトリの管理です。
階層の深いディレクトリを作る場合などは、recursive
をつけます。ただし、中間のディレクトリ(以下の例では/tmp/too
, /tmp/too/deep
)にはownerやmodeが適用されないので注意してください。
directory "/tmp/too/deep/dir" do
action :create
recursive true
owner "someone"
mode 0755
end
link
シンボリックリンクを管理します。
#
# シンボリックリンク(/tmp/ip.txt)を作成
#
link "/tmp/ip.txt" do
to "/tmp/hoge/ipaddress.txt"
end
#
# シンボリックリンクを削除
#
link "/tmp/unknown_link" do
action :delete
end
toでリンク先を指定します。同じ位置に別ファイルへのリンクが合った場合は、定義したリンク先に書き換えます。
不要なリンクを削除することも出来ます。存在しなければ何もしません。
package
OSの持つパッケージ管理システムを利用してパッケージを管理します。
package "vim" do
action :install
end
package "exim4" do
action :purge
end
パッケージ管理ツール別に、apt_package
, yum_package
などもありますが、chefの実行時に自動的に判定するので、基本的には package
で充分でしょう。
プラットフォームによりパッケージ名が異なる場合がありますが、その場合はcase
文で分岐しましょう。
http://docs.getchef.com/essentials_cookbook_recipes.html#use-case-statement
service
/etc/init.d/*
のサービスの起動状態を管理します。
#
# ntpサービスを起動時有効化(enable)して、開始(start)する
#
service "ntp" do
action [:enable, :start]
end
注意すべき点として、 この記述の場合、サービスが(起動していない場合に)起動するタイミングはChefの処理の最後 になります。
リソースに対する変更タイミングについては後ほど記述します。
execute
汎用コマンドの実行を可能にするリソースです。
このリソースを利用すると任意のコマンドを実行可能ですが、特に条件を指定しない場合、何度も処理を実行していしまいます。
不用意に実行しないため、 変更の必要がないと判断する基準を必ず定義してください。
#
# /path/to/source に移動し、 ./configure を someone ユーザで実行
# Makefile が既に生成されていれば実行しない.
#
ex = execute "configure hoge" do
action :nothing
command "./configure --prefix=/usr/local/hoge"
user "someone"
cwd "/path/to/source"
not_if "test -e /path/to/source/Makefile"
end
resouces("execute[configure hoge]")
script(bashなど)
汎用コマンドの中でも、特にスクリプトファイルで複雑な処理を実行したい場合に使用します。
複数行のスクリプトが書きたい場合は、ヒアドキュメントを使うと便利です。
execute
の場合と同じく、条件がなければ何度も実行してしまいます。
#
# スクリプト実行
#
bash "test script" do
code <<-EOS
# script here
touch evidence
EOS
user "someone"
cwd "/path/to/execute"
environment { "PATH" => "/usr/local/pgsql/bin" }
not_if "test -e /path/to/execute/evidence"
end
実行タイミングについて
Chefレシピの実行順序は大まかには以下のとおりです。
- クックブックの評価(レシピの定義、属性値を読み込んで一覧化する)
- クックブックの実行(リソースを評価して実行する)
- ディレイリソースの実行(service startなど)
Rubyスクリプトの評価とリソースの評価
Rubyスクリプトの実行自体はクックブックの評価に当たるため、以下の様なコードではnkfのインストールがスクリプト評価時に行われず、まだインストールされていない場合は思ったような挙動になりません。
package "nkf" do
action :install
end
#
# package[nkf] が実行される前に if が評価される
#
if `nkf -g /test/hogehoge | grep -v UTF-8` # <- ここだけRubyとして先に実行される
execute "Change encoding" do
command "nkf -w --overwrite /test/hogehoge"
end
end
#
# リソース実行時に条件を確認する
#
execute "Change encoding" do
command "nkf -w --overwrite /test/hogehoge"
only_if "nkf -g /test/hogehoge | grep -v UTF-8"
end
リソース実行タイミングのコントロール
service
リソースなどはデフォルトでは遅延実行となっており、chef実行の最後に行われます。
実行するactionとタイミングは notifies
, subscribes
でコントロールできます。
http://docs.getchef.com/chef/resources.html#notifications
-
notifies
: 自身のリソースの更新があったら、他のリソースのアクションを実行する -
subscribes
: 監視しているリソースの更新があったら、自身のリソースを実行する。
#
# リソース定義のみ。何もしない。
#
service "ntp" do
action :nothing
end
#
# ntpd.confに変更があったら、即時
#
template "/etc/ntpd.conf" do
mode 0644
notifies :restart, "service[ntp]", :immediately
end
同じことをsubscribes
で書くとこうなります。
#
# ntpd.confの変更を監視する
#
service "ntp" do
action :nothing
subscribes :restart, "template[/etc/ntpd.conf]", :immediately
end
#
# ntpd.confテンプレート
#
template "/etc/ntpd.conf" do
mode 0644
end
まとめ
この他にも cron
や git
などのリソースもあります。
また、サードパーティのクックブックを利用することで、新たに定義されるリソースもあります。(postgresql_database_user
など。)