前回はItamaeをインストールし、簡単なレシピを実行してみました。今回はさらに実践的なレシピの書き方について解説します。前回述べたようにItamaeはChefに強く影響を受けているため、概ねChefと同じように書けます。
リソースとは
レシピにはリソースと呼ばれる、サーバ上のコンポーネント(ソフトウェア、ファイル、コマンドなど)を抽象化したものを記述します。リソースにはアクションをはじめとする属性を指定でき、操作の種類を指定することができます。前回も使ったpackageのリソースを例にすると
のようにpackage
リソースをインストールしたり、アンインストールしたりすることができます。
package
リソースの場合、install
アクションがデフォルトになっているため、省略することも可能です。
どのようなアクションや属性が用意されているかはドキュメントを参照してください。
Itamaeには様々なリソースが用意されていますが、以下ではその中でよく使うであろうリソースを紹介します。
executeリソース
execute
リソースは任意のコマンド実行を表します。
runアクション
任意のコマンドをリソースとして定義できるため、Itamaeのリソースとして用意されていない操作を実行することができます。
繰り返し似たようなコマンドを書く場合や抽象化出来る場合は、プラグイン機構を利用して独自のリソースを定義するほうがお勧めですが、手っ取り早く実行するには便利です。プラグイン機構については次回、解説します。
execute
リソースを利用する際は、冪等性が保たれるように記述する必要があります。例えば、2度以上実行する必要がなかったり、2度実行すると失敗するようなコマンドの場合は、実行すべきかどうかを事前に確認するようにします。
上記のようにonly_if
またはnot_if
を使うと、特定のコマンドが成功または失敗した場合のみアクションを実行することができます。
fileリソース
file
リソースはサーバ上のファイルを表すリソースです。
createアクション
デフォルトはcreate
アクションで、ファイルを作成します。なお、既にファイルが存在して、変更がある場合は上書きします。
fileリソースをつかうと実行時にdiffが表示されます。--dry-run
オプションをつけた場合にも表示されるので、実行前に変更される部分がわかります。
editアクション
edit
アクションをつかうと、ファイルの内容変更をRubyのスクリプトで書くことができます。
edit
アクションの場合にもdiffが出力されます。
remote_fileリソース
createアクション
remote_fileはfileリソースの一種で、ローカルにあるファイルをサーバに置きます。
content
をファイルに書けること以外、file
リソースと同じですが、レシピと設定ファイルなどのsource
を分離でき管理しやすくなります。source
は省略すると自動的に決定されます。source
を省略した場合は、上記のmy.cnfの例だと以下のパスを上から順番に探索し、最初に見つかったものが使われます。
- (レシピがあるディレクトリ)/files/etc/my.cnf
- (レシピがあるディレクトリ)/files/my.cnf
templateリソース
createアクション
template
リソースはremote_file
とほぼ同じですが、source
ファイルとしてERBテンプレートを使える点が異なります。テンプレートを使って動的に設定ファイルを生成し、ホストごとに異なる設定を配布するときに有用です。
ホスト固有の値を渡したり、ホストの情報を取得するにはノード属性機能を利用します。ノード属性については次回解説します。
remote_file
と同様に、source
は省略すると自動的に決定されます。source
を省略した場合は、上記のmy.cnfの例だと以下のパスを上から順番に探索し、最初に見つかったものが使われます。
- (レシピがあるディレクトリ)/templates/etc/my.cnf.erb
- (レシピがあるディレクトリ)/templates/etc/my.cnf
- (レシピがあるディレクトリ)/templates/my.cnf.erb
- (レシピがあるディレクトリ)/templates/my.cnf
packageリソース
package
リソースはOS標準のパッケージシステムのパッケージを表します。Ubuntu, Debianの場合dpkg(apt)、CentOS, RHELの場合rpm(yum)、Mac OSの場合Homebrewを操作します。
installアクション
install
アクションはパッケージのインストールを行います。すでにパッケージがインストールされていて、version
が指定されていない場合は何もしません。
removeアクション
remove
アクションはパッケージのアンインストールを行います。
serviceリソース
service
リソースはSysvinitやUpstartなどで管理されているサービスを表します。package
リソースと同様、OS・ディストリビューションに応じて自動的にコマンドが選択されます。
利用可能なアクションはstop
, start
, restart
, reload
です。このリソースはデフォルトのアクションがnothing
で、action
を指定しない限り何も起こりません。
local_ruby_blockリソース
runアクション
local_ruby_block
リソースはローカルでRubyのコード(ブロック)を実行するだけのリソースです。後述しますが、レシピに書かれたRubyのコードはリソースアクションが実行される前に評価されます。特定のリソースアクションのあとに実行したいコードがある場合、local_ruby_block
を利用します。
全リソース共通の属性
既にでてきたonly_if
やnot_if
に加え、いくつかの属性は全リソースで使えるようになっています。
only_if, not_if
only_if, not_ifでリソースアクションを実行すべきかどうかを判定することができます。
only_if
:指定されたコマンドが成功した場合(コマンドの終了コードが0)のみアクションを実行します。
not_if
:指定されたコマンドが失敗した場合(コマンドの終了コードが0以外)のみアクションを実行します
user
user
で指定したユーザとしてコマンドを実行します。
cwd
cwd
で指定したディレクトリ内でコマンドを実行します。
リソースの実行順序
Itamaeのリソースは基本的に上から下に順番に実行されます。しかし、リソースの定義は実行前に行われるため注意が必要です。具体例を以下に示します。
実行結果を見るとわかるように、D
とE
がC
より前に出力されています。これはリソースアクション(C
)の前にリソース定義部分が評価されているためです。レシピを書く際はこの挙動にご注意ください。
リソース間の連携
例えば、特定のファイルが更新された際にサービスをリロードしたいなど、リソース間で連携を取りたい場合があると思います。notifies
とsubscribes
で、リソースに変更があった場合に他のリソースのアクションを実行できます。
notifies
上記の例では、template
に更新があった場合(ファイルの内容に変更があった場合など)service
のreload
アクションを実行するようになります。これにより設定ファイルが変更された時だけ、設定ファイルをリロードすることができます。
service
に指定されてるnothing
アクションはnotifies
やsubscribes
のためのアクションで、すべてのリソースで利用可能です。nothing
を指定すると、実際にはアクションが実行されずリソース定義だけが行われるので、notifies
、subscribes
でのみアクションが実行されます。
subscribes
subscribes
はnotifies
の逆で、あるリソースの変更を監視して、変更があった場合にアクションを実行することができます。
上記の例では先に出てきたnotifies
の例と同様、template
に変更があった場合にservice
のリロードを行います。
なお、notifies
やsubscribes
は1つのリソースに複数指定することも可能です。
複数のリソースをまとめる
define
を使うと、複数のリソースをまとめて1つのリソースのように見せることができます。
このようにリソースを定義すると、定義以降install_and_enable_package
リソースが使えるようになります。
複数回同じようなリソース定義が出てくる場合はこのようにdefine
を使って抽象化をすると見通しが良くなります。
他のレシピを読み込む
レシピを書いていくと、ファイルが大きくなって見通しが悪くなったり、再利用したくなる場合があります。その場合はinclude_recipe
を使って他のレシピを読み込み、ファイルを分割することをお勧めします。
このようにソフトウェアごとにディレクトリを作って、サーバの役割ごとのレシピからinclude_recipe
でレシピを読み込む形を推奨しています。
実際に実行する際は以下のようにroles以下のファイルを指定します。
まとめ
今回は比較的よく使うリソースの解説と、レシピを書きやすくする機能について紹介しました。
次回はホストごとに異なる値の渡し方・取得の仕方や、Itamaeプラグインの作り方について解説します。