Chefは「動かす」な、「焼き込め」:Packer + Chef Infraで実現する不変インフラの極致
「Chef Clientが定期実行されている間に設定が書き換わってしまう」「環境ごとに微妙に挙動が違う」。これらはChefを伝統的な構成管理ツールとして運用しているチームが必ず直面する『構成ドリフトの地獄』です。
SREとして断言しよう。Chefの真の力は、実行時に環境を治すことではなく、デプロイ前に環境を完成させることにある。
本稿では、PackerとChef Infraを組み合わせ、AMIビルドパイプラインの中で「不変(Immutable)なサーバー」を焼き上げる、モダンで堅牢なインフラ構築術を伝授する。
—
1. パラダイムシフト:なぜ「Immutable」なのか
従来の「サーバーにChef Clientを入れ、定期的にPullさせる」手法は、以下のリスクを内包している。
- 非決定的な実行: 外部依存(リポジトリの更新、APIの応答遅延)による失敗。
- ドリフトの放置: Chefが走るまでの数分間、あるいはエラー発生時に環境が不整合に陥る。
- 検証の遅れ: 実際にデプロイするまで、その設定で動くかどうかが分からない。
これらを解決するのが、「ビルド時のみChefを使い、本番機ではChefを捨て去る」というアプローチだ。
—
2. 実践:Packer + Chef Infra ビルドパイプライン
Packerの `chef-client` プロビジョナーを使えば、Chefの強力なCookbook資産をそのまま活用し、AMIを生成できる。
ベストプラクティスな `packer.pkr.hcl` 構成
以下は、セキュアかつ高速にAMIを焼き上げるための構成例だ。
source “amazon-ebs” “hardened-web” {
ami_name = “web-server-${formatdate(“YYYYMMDD-hhmm”, timestamp())}”
instance_type = “t3.medium”
region = “ap-northeast-1”
source_ami_filter {
filters = {
virtualization-type = “hvm”
name = “al2023-ami-2023-x86_64”
}
owners = [“137112412989”] # AWS公式
most_recent = true
}
ssh_username = “ec2-user”
}
build {
sources = [“source.amazon-ebs.hardened-web”]
# Chefで構成を焼き込む
provisioner “chef-client” {
config_template = “./chef/client.rb”
run_list = [“recipe[web_server::default]”]
# ライフサイクルが終わったらChefを削除して「不変」を確定させる
cleanup_chef = true
}
}
—
3. チームの生産性を加速させる「隠れた技術」
チーム開発の神プラグイン:`Cookstyle`
ChefのLintツールであるCookstyleは、ただの規約チェックではない。最新のRubyベストプラクティスを強制し、レガシーなコードの混入を防ぐ。
- VS Code拡張: `Chef-Workstation` 拡張を入れ、`cookstyle` を保存時に自動実行させる設定を `.vscode/settings.json` に記述せよ。
{
“editor.codeActionsOnSave”: {
“source.fixAll.cookstyle”: true
}
}
爆速開発のためのキーボードショートカット(VS Code)
- `Cmd + Shift + P` -> `Chef: Generate Cookbook`: テンプレートを一瞬で生成。
- `Cmd + P` でファイル遷移を極める(`berks`や`metadata.rb`への移動を高速化)。
共有化ルール:`Policyfile` 一択
古い `Berkshelf` はもう捨てるべきだ。Policyfileを使えば、Cookbookのバージョンと実行順序を1つのロックファイル(`Policyfile.lock.json`)に閉じ込めることができる。これにより「手元の環境では動くが本番では動かない」という現象を完全に排除できる。
—
4. 実用的な設定ファイル構成(ディレクトリレイアウト)
チーム開発では、設定を隠蔽せず、かつ共通化できる構造が必須だ。
.
├── Policyfile.rb # 依存関係とRunListの定義(唯一の正解)
├── chef/
│ ├── client.rb # ローカル開発/ビルド用設定
│ └── knife.rb # チーム共通のインフラ接続定義
├── cookbooks/ # チーム内製Cookbook
├── data_bags/ # 暗号化された機密データ(Git管理不可)
└── scripts/
└── validate.sh # Packer実行前に構文チェックを行うCIスクリプト
—
5. テックリードからの提言:ドリフト防止の真髄
不変インフラにおいて、「ドリフトが発生した時」は「修正する時」ではない。「作り直す時」である。
1. Chef Clientはインストールしない: PackerでAMIを作る際、最終的に `yum remove chef` または削除スクリプトを走らせる。
2. 実行環境を切り離す: 設定変更が必要な場合は、Gitのコミットからパイプラインを回し、新しいAMIをデプロイして古いインスタンスを破棄する(Blue/Green Deployment)。
3. 検証の自動化: Packerのビルドの最後に `inspec` を実行せよ。AMIが焼き上がった瞬間に、期待通りのポートが空いているか、不要なサービスが停止しているかをテストし、失敗すればAMIの公開をブロックする。
「ツールを使う」のは当たり前だ。ツールを飼い慣らし、インフラを「ソースコードの結実」として定義すること。それが、我々エンジニアが目指すべき高みである。
さあ、古いChefの運用の名残を捨て、コードで定義された完璧なサーバーを焼き上げよう。