Chefの深淵:Custom Resourcesで「宣言的インフラ」を極めろ
Chefを単なる「スクリプト実行ツール」だと思っているなら、今すぐその認識を捨ててほしい。Chefの真骨頂は、冪等性を担保した「状態定義(State Definition)」の抽象化にある。
実務において、`package`や`file`といったプリミティブなリソースをそのままレシピに書き連ねるのは、スパゲッティコードへの第一歩だ。我々SREが目指すべきは、「ChefのDSL(ドメイン固有言語)を拡張し、インフラの仕様を宣言的に記述できるカスタムリソース(Custom Resources)の構築」である。
今日は、現場で生き残るための「Custom Resources」設計術を伝授する。
—
1. なぜ既存リソースでは限界が来るのか?
複雑なミドルウェアや社内標準のデプロイフローを構築する際、レシピの中に`execute`や`bash`が乱立していないか? それは「抽象化の失敗」だ。
- 冪等性の崩壊: `bash`ブロックは、毎回実行される可能性がある。ガード句(`not_if`, `only_if`)を書くコストは高く、見通しが悪い。
- コードの重複: 似たような設定を複数サーバーで適用する際、コピー&ペーストが発生し、修正漏れが頻発する。
- テスタビリティの欠如: レシピ単位のテストは困難だが、カスタムリソースなら単体テスト(ChefSpec)が容易になる。
—
2. Custom Resourcesの設計とディレクトリ構成
Custom Resourcesは `resources/` ディレクトリに配置する。これにより、レシピから見れば「ただの組み込みリソース」のように扱える。
ディレクトリ構成例:
cookbooks/my_app/
├── resources/
│ └── app_service.rb # カスタムリソース定義
├── recipes/
│ └── default.rb # 呼び出し側
└── metadata.rb
—
3. 現場で効く!再利用可能なコードの書き方
以下は、ある特定のサービス設定を抽象化したカスタムリソースの実例だ。
resources/app_service.rb
resource_name :app_service
provides :app_service
プロパティの定義(型定義で安全性を担保)
property :name, String, name_property: true
property :port, Integer, default: 8080
property :config_path, String, required: true
アクションの定義
action :create do
# 既存リソースを組み合わせて抽象化する
directory ::File.dirname(new_resource.config_path) do
recursive true
end
template new_resource.config_path do
source ‘service.conf.erb’
variables(port: new_resource.port)
notifies :restart, “service[#{new_resource.name}]”, :delayed
end
service new_resource.name do
action [:enable, :start]
end
end
チーム開発のためのベストプラクティス
1. プロパティのバリデーション: `validation`を使い、予期せぬ値の混入を初期段階で防げ。
2. `new_resource`の活用: アクション内では、定義したプロパティへアクセスするために必ず`new_resource`オブジェクトを経由すること。
3. 冪等性の保証: 常に`notifies`や`subscribes`を使い、変更があった場合のみアクションをトリガーする設計を徹底する。
—
4. 開発速度を爆速にする「テックリードの隠し味」
推奨プラグイン & エディタ設定 (VS Code)
- Chef Extension for VS Code: 文法チェックとスニペット補完に必須。
- Cookstyle: `rubocop`ベースの静的解析ツール。これをCIに組み込まないチームは論外だ。
- YAML/JSON Lint: 構成ファイルは必ずバリデーションを通過させる。
生産性を高めるキーボードショートカット
- `Ctrl + Shift + P` (Command Palette): `Chef: Generate Cookbook` など、生成系タスクをキーボードから叩く癖をつけろ。
- `Alt + Up/Down`: レシピの行移動は思考を止めないために必須。
設定ファイル(YAML/JSON)の構成ルール
構成値はコードにハードコーディングせず、`attributes/` に分離せよ。ただし、複雑な階層を持つ場合は、JSONよりも可読性の高いYAMLを採用し、`Hashie::Mash`でアクセスする設計が最も堅牢だ。
attributes/default.yml
app_settings:
port: 8080
timeout: 30
レシピからの呼び出し
app_service ‘my-web-app’ do
port node[‘app_settings’][‘port’]
config_path ‘/etc/myapp/config.yml’
end
—
最後に:SREとしての心構え
ChefのCustom Resourcesを書くということは、単なるサーバーの設定ではない。「インフラの仕様をコードとして設計し、その仕様をチームの共通言語にする」ということだ。
「とりあえず動く」コードを書くエンジニアは多い。しかし、壊れない設計、変更に強い抽象化、そして何より「誰が読んでも意図が伝わる」コードを書くエンジニアこそが、真のテックリードだ。
さあ、今すぐ既存のベタ書きレシピをリファクタリングし、Chefという強力な武器を真に使いこなしてほしい。現場で震えるような高効率な自動化の世界が、そこには待っている。