【入門編】Chefリソースの条件分岐マスタークラス:only_if・not_ifの高度な評価とシェルスクリプト最適化 – インフラ構成管理(IaC)活用バイブル

インフラの現場で、Chefを「ただの自動化ツール」として使っているうちは、まだ序の口です。本当のプロは、Chefが持つ「収束(Convergence)」という哲学を深く理解し、無駄な処理を徹底的に排除した「極めて美しいコード」を書きます。

今日は、Chefにおける「条件分岐の極意」である `only_if` と `not_if` を深掘りします。これをマスターすれば、あなたの書くレシピは数秒で完了し、サーバーの負荷も最小限に抑えられるようになります。

—

1. そもそも「なぜ条件分岐が必要なのか?」

Chefの最大の強みは「冪等性(べきとうせい)」です。何度実行しても、結果は常に同じ状態になること。しかし、単純な設定変更ならともかく、複雑なスクリプトを実行する場合、毎回実行されると困るケースがありますよね。

そこで使うのが `only_if` と `not_if` です。これらは「リソースが実行される前に、その条件を評価する」というガード節です。

  • `only_if`: この条件が「真(終了コード0)」の時だけ実行する。
  • `not_if`: この条件が「偽(終了コード0以外)」の時だけ実行する。

重要な評価タイミング

Chefがリソースを適用する際、まず `only_if`/`not_if` が評価されます。ここで「実行不要」と判断されれば、メインの処理は一切実行されません。これが「高速な収束」の秘訣です。

—

2. Rubyブロックを使った高度な条件判定

シェルスクリプトだけで条件を書くのは限界があります。ChefのレシピはRubyそのもの。Rubyの力を借りれば、もっと賢い判定が可能です。

例:特定のパッケージがインストール済み、かつ設定ファイルのハッシュ値が一致しない場合のみ処理を行う
execute ‘deploy_application’ do
command ‘/usr/local/bin/deploy.sh’

# Rubyブロックを使って、より複雑なロジックを判定
only_if do
# 1. 前提条件のチェック
package_installed = system(‘rpm -q my-app > /dev/null’)

# 2. ファイルの存在確認
config_exists = File.exist?(‘/etc/my-app/config.json’)

# 全ての条件が揃ったときだけ実行
package_installed && config_exists
end
end

このように、`only_if` にブロックを渡すと、そのブロックの戻り値(真偽値)で実行が制御されます。シェルスクリプトを呼び出すよりも高速で、かつRubyの柔軟な条件式が使えるため、現場では多用します。

—

3. 【極意】収束速度を最大化するアンチパターン回避

初心者が陥りやすいのが「重い処理をガード節に入れてしまう」ことです。

❌ アンチパターン:ガード節の中で重いコマンドを叩く

毎回 grep や find を実行すると、数千リソースある環境では地獄のように遅くなる
execute ‘update_config’ do
command ‘…’
not_if “grep ‘configured’ /var/log/my-app.log” # ログが巨大だとここで毎回待たされる
end

✅ プロの最適化:ファイルの特性を利用する

Chefには `creates` という強力な属性があります。`only_if` を書く前に、まずこれを使えないか検討してください。

execute ‘initialize_db’ do
command ‘/usr/bin/db_init.sh’
# ファイルが存在すれば実行しない。シェルを叩くより圧倒的に高速
creates ‘/var/lib/db/initialized.lock’
end

教訓:
1. シェルを実行するな: 可能な限り Ruby の `File` や `Dir` クラスを使え。
2. ガード節を軽くしろ: ログの検索や巨大なファイルのパースは避け、ステータスファイルやハッシュ値比較で判定せよ。
3. 冪等性を意識せよ: `execute` を使うときは、常に「この処理を二度実行しても安全か?」を自分に問いかけろ。

—

はじめの一歩:HelloWorld的な動作確認

初めてChefを触るなら、まずはこの「ガード節の挙動」を体感してください。

1. 環境: Chef Workstation をインストール。
2. レシピ作成 (`test.rb`):

1. ファイルがない時だけ作成
file ‘/tmp/hello.txt’ do
content ‘Hello, Chef!’
not_if { File.exist?(‘/tmp/hello.txt’) }
end

2. 上記のファイルが存在する時だけメッセージを表示
execute ‘check_file’ do
command ‘echo “File exists!”‘
only_if { File.exist?(‘/tmp/hello.txt’) }
end

3. 実行: `chef-apply test.rb` を2回叩いてみてください。

  • 1回目:両方の処理が実行されます。
  • 2回目:ガード節により、どちらも「Up-to-date(更新不要)」と判断され、即座に終了します。

—

最後に

Chefは単なる「コマンド実行ツール」ではありません。あなたのサーバーの状態を「定義(宣言)」する、インフラの設計図です。

`only_if` や `not_if` を使いこなすことは、サーバーの現状を深く理解し、無駄な処理を削ぎ落とす「職人の仕事」です。これをマスターすれば、あなたのコードは格段に安定し、チームメンバーから「なぜか君のレシピだけ爆速だね」と称賛されるはずです。

さあ、次はあなたの番です。コードの中に隠された「無駄な実行」を、今日から一つずつ消していきましょう。

タイトルとURLをコピーしました