Chefの「実行順序」で夜を明かさないために:notifiesとsubscribesの深淵を解き明かす
こんにちは。インフラをコードで支配するSREの世界へようこそ。
Chefを触り始めたエンジニアが必ずぶつかる壁、それは「なぜか設定ファイルが書き換わったのに、サービスが再起動しない」あるいは「サービスが再起動するはずのないタイミングで落ちた」という怪奇現象です。
これ、実はChefの「収束フェーズ(Convergence Phase)」における通知の仕組みを理解できていないことが原因です。今日は、Chefの心臓部である `notifies` と `subscribes`、そして実行タイミングの魔術である `delayed` と `immediate` を完全攻略しましょう。
—
1. Chefの「実行順序」の基本原則を理解する
まず大前提として、Chefは「宣言的」なツールです。しかし、レシピ内のリソースは「上から順に実行」されます。
ここで重要なのは、Chefには「Compileフェーズ(コードを解析する)」と「Convergeフェーズ(実際にリソースを適用する)」の2段階があることです。`notifies` は、この「Convergeフェーズ」でリソースの状態が変化(updated)した瞬間に発火するトリガーです。
なぜ `notifies` が必要なのか?
設定ファイル(例: `nginx.conf`)を書き換えるだけでは、サービスは新設定を読み込みません。Chefに「変更があったら、あわせてこれも実行してくれ」と伝えるための糊(のり)、それが通知機能なのです。
—
2. 実践!通知の魔術:notifiesとsubscribes
A. `notifies`(能動的な通知)
「私が変わったら、お前も動け」というプッシュ型のアプローチです。
/etc/nginx/nginx.conf が変更されたら、nginxサービスをリロードする
template ‘/etc/nginx/nginx.conf’ do
source ‘nginx.conf.erb’
# :restart ではなく :reload が推奨(ダウンタイムを最小化するため)
notifies :reload, ‘service[nginx]’, :delayed
end
service ‘nginx’ do
action [:enable, :start]
end
B. `subscribes`(受動的な監視)
「私はあいつを監視する。あいつが変わったら、私は動く」というプル型のアプローチです。
逆の書き方:サービス側から設定ファイルを監視する
service ‘nginx’ do
action [:enable, :start]
subscribes :reload, ‘template[/etc/nginx/nginx.conf]’, :delayed
end
どちらを使うべきか?現場のベストプラクティスとしては、「変更の発生源(templateやpackage)に `notifies` を書く」方が、コードの依存関係が直感的になり、可読性が高まります。
—
3. 「即時」か「遅延」か:ここがバグの温床だ
ここが今回のハイライトです。通知には2つのタイミングが選べます。
- :delayed (デフォルト)
- 挙動: Chefの全リソース処理が終わった「最後」に実行される。
- メリット: 複数箇所で同じ通知が発生しても、実行は「1回」にまとめられる。効率的で安全。
- :immediate
- 挙動: リソースが変化した「その瞬間」に実行される。
- メリット: 設定反映を即座に行いたい場合。ただし、依存関係が複雑な場合に予期せぬ挙動を生む。
現場で震えるほど役立つTIPS:なぜ :delayed を使うべきか
例えば、`template` を3箇所で更新したとします。もし通知が `:immediate` だと、サービスは3回再起動します。これではダウンタイムの嵐です。`:delayed` なら、Chefは賢く「最後の一回だけ」再起動してくれます。
—
4. 精度高い「HelloWorld」的セットアップ
実際に手を動かしてみましょう。まずはChef Workstationをインストールし、ローカルで実行を確認します。
1. インストール (macOSの場合)
brew install –cask chef-workstation
2. 動作確認用ディレクトリ作成
mkdir chef-test && cd chef-test
# 最小構成のレシピファイルを作成
vi recipe.rb
3. レシピ(recipe.rb)の記述
# ファイル作成
file ‘/tmp/hello.txt’ do
content ‘Hello, Chef World!’
notifies :run, ‘execute[log_message]’, :immediate
end
# 実行ログ出力
execute ‘log_message’ do
command ‘echo “Change detected!”‘
action :nothing # 明示的に指示されるまで実行しない
end
4. 実行!
chef-apply recipe.rb
初回実行時はファイルが作られ、即座にログが出ます。2回目に実行すると、ファイルに変化がないため、`execute` は実行されません。これが「冪等性(べきとうせい)」の真髄です。
—
最後に:先輩からのアドバイス
「なぜか動かない」と感じた時は、`chef-apply` に `-l debug` オプションをつけて実行してみてください。Chefがどのリソースで何を感じ取り、どの通知をキューに入れたのかが、詳細に表示されます。
Chefは決して難しい魔法ではありません。リソースの状態を記述し、その連鎖を `notifies` で繋ぐ。この設計思想さえ掴めば、あなたはインフラの混沌をコントロールするマスターになれます。
さあ、次はどんなインフラをコードで自動化しましょうか?応援していますよ。