Chef Infra Clientの「多重実行」を物理的に封殺せよ:現場で信頼される排他制御の極意
こんにちは。インフラの現場で「なぜかChefが二重に走ってファイルが壊れた」「CIと定期実行が衝突して状態が不整合になった」という悪夢を見たことはありませんか?
Chefは非常に強力ですが、「何も考えずにcronで回す」のは実は非常に危険な運用です。特に大規模な環境やCI/CDパイプラインを統合している現場では、Chefクライアントの多重実行を防ぐことは「インフラの品格」そのものと言えます。
今日は、初心者の方でも今日から実践できる、Chefの多重実行を完全に防ぐ「堅牢な防壁」の作り方を伝授します。
—
1. なぜChefの「多重実行」が地獄を生むのか
Chefは状態を定義するツールですが、裏側ではRubyのプロセスが走り、`/var/chef/cache` などのディレクトリを激しく読み書きします。もし、手動で走らせた `chef-client` と、cronによる定期実行が同時に動いたらどうなるでしょうか?
- ロックファイルの破損: 複数のプロセスが同時にメタデータを書き換え、整合性が崩壊します。
- リソースの競合: 同じサービスを同時に再起動しようとして、OSが不安定になります。
- Chef Serverとの通信エラー: 同一ノードから短時間に連続してクエリが飛び、レートリミットに引っかかることもあります。
これらを防ぐには、「OSの機能を使って、Chefを実行する権利を一つに絞る」というアプローチが必要です。
—
2. 実践:flockによる「スマート排他制御」
最もシンプルかつ強力なのが、Linuxの `flock` コマンドを使う方法です。`flock` は、指定したファイルにロックをかけ、他のプロセスがそのロックを保持している間は実行を待機(または即座に終了)させます。
推奨コマンド構成
cronに記述する際、以下のようにラップしてください。
-n: ロックが取れない場合は即終了(待機させない)
-x: 排他ロックを取得
/var/run/chef-client.lock: ロックファイルとして使用
/usr/bin/flock -n /var/run/chef-client.lock /usr/bin/chef-client -c /etc/chef/client.rb
この設計のポイント:
- `-n` をつけることで、実行中に別のChefが走ろうとしたら即座に終了させます。これにより、CI/CDで手動実行した際に「今は定期実行中だから待機する」といった無駄なリソース消費を防げます。
—
3. systemdのRuntimeDirectoryでモダンに管理する
最新のLinux環境なら、`systemd` の機能を使うのが最も「クラウドネイティブ」で美しい解決策です。
`/etc/systemd/system/chef-client.service` を以下のように設定してみましょう。
[Service]
ExecStart=/usr/bin/chef-client
RuntimeDirectoryを作成し、そこにPIDを置くことで自動的に排他制御の基盤にする
RuntimeDirectory=chef
RuntimeDirectoryPreserve=no
実行中のプロセスが一つだけであることを保証する設定
Type=simple
`systemd` を使うメリットは、万が一Chefがクラッシュした際も、再起動ポリシー(`Restart=on-failure`)を組み合わせることで、「排他制御された安全な状態で自動復旧」が可能になる点です。
—
4. 競合時の「自動リトライ」と「アラート通知」
排他制御をした際、「実行できなかった」ことを知る仕組みがないと、インフラは「沈黙の失敗」を続けます。これを防ぐための、現場で使えるスクリプトの断片を紹介します。
!/bin/bash
LOCKFILE=”/var/run/chef-client.lock”
排他制御付きで実行
if flock -n $LOCKFILE /usr/bin/chef-client; then
echo “Chef run completed successfully.”
else
# ロックが取得できなかった場合のみアラートを飛ばす
echo “Alert: Chef client is already running. Skipping this execution.” | mail -s “Chef Conflict Alert” admin@example.com
exit 1
fi
現場の知見:
- アラートの重要性: 単に失敗を無視するのではなく、`exit 1` で終了コードを返し、監視ツール(MackerelやDatadogなど)に「実行に失敗した(衝突した)」というメトリクスを飛ばすのがプロの仕事です。
—
最後に:IaCを「当たり前」にするために
Chefの実行を「おまじない」で終わらせず、排他制御という「防御的プログラミング」の視点を取り入れるだけで、インフラの安定性は劇的に向上します。
最初は難しく感じるかもしれませんが、一度この「ロックを意識した運用」を身につければ、どんな複雑な構成管理ツールを使っても迷うことはありません。
まずは、今動いているcronのコマンドに `flock` を追加することから始めてみてください。あなたのインフラが、より一層「壊れない場所」に変わるはずですよ。
それでは、素晴らしい自動化ライフを!