Terraformの限界を突破せよ:`external`プロバイダで構築する「動的インフラ」の極致
Terraformは宣言的である。ゆえに、静的な定義には最強だが、動的に変化するメタデータや、APIの気まぐれなレスポンスを扱う段になると、途端にその牙を折られる。
「この外部APIのレスポンスを、Terraformの変数として流し込めないか?」
多くのエンジニアがここで諦め、手動のシェルスクリプトに逃げ、冪等性を破壊する。だが、真のSREは諦めない。`external`データソースという「禁断の扉」を開くのだ。これは単なるツール連携ではない。Terraformの実行グラフに、外部世界の流動性を接続するアーキテクチャ設計の話だ。
—
1. `external`プロバイダの正体:JSONという共通言語
`external`プロバイダは、Terraformと外部スクリプトの間に架けられた「JSONによる通信路」だ。
- Input: Terraformからスクリプトへ `stdin` 経由でJSONを送る。
- Output: スクリプトからTerraformへ `stdout` 経由でJSONを返す。
シンプルだが、ここに「状態」を混入させることは、Terraformの設計哲学に対する挑戦でもある。以下の鉄則を忘れるな。
- 冪等性の担保: 外部スクリプトは必ず「副作用ゼロ」でなければならない。
- JSONスキーマの厳守: 出力は必ずフラットなマップ(`string` to `string`)であること。ネストされたJSONはTerraformの型システムで受け取れないため、工夫が必要だ。
2. 実践:動的APIからリソースを動的に生成するハック
例えば、AWSのコストエクスプローラーや、社内のレガシーな資産管理APIから、特定のタグ情報を動的に取得してインフラ構成に反映させるケースを考えよう。
スクリプト側の実装 (`fetch_data.sh`)
!/bin/bash
実行時のエラーを確実にstderrへ流す(重要)
set -e
JSON入力を受け取る(Terraform側のquery変数)
eval “$(jq -r ‘@sh “API_ENDPOINT=\(.api_endpoint)”‘)”
外部APIを叩く(ここではcurlの実行結果を想定)
高速化のためキャッシュ戦略を考慮せよ
RESPONSE=$(curl -s -f “$API_ENDPOINT/resource-meta”)
結果をJSONとして出力(キーはすべてstringにするのが鉄則)
jq -n –arg val “$RESPONSE” ‘{“data”: $val, “timestamp”: “‘$(date +%s)'”}’
Terraform側の定義
data “external” “dynamic_meta” {
program = [“bash”, “${path.module}/fetch_data.sh”]
query = {
api_endpoint = “https://internal-api.example.com”
}
}
取得した値をリソースに適用する
resource “aws_instance” “app” {
# …
tags = {
“ProvisionedBy” = data.external.dynamic_meta.result.data
“GeneratedAt” = data.external.dynamic_meta.result.timestamp
}
}
—
3. なぜ `null_resource` や `local-exec` ではないのか?
ここが重要だ。多くの初学者は `local-exec` で頑張ろうとする。だが、それは「構築後の副作用」に過ぎない。
- `local-exec`: Terraformのグラフに依存関係を組み込めない。構築順序が崩れ、破壊的な変更を招く。
- `external`: データソースとして扱われるため、依存グラフに組み込まれる。つまり、スクリプトの出力が変われば、Terraformはそれを変更として検知し、計画的にリソースを更新する。これこそが「IaCの完全自動化」の鍵だ。
—
4. 現場で震えるための「極限の最適化」テクニック
① パフォーマンスとメモリ管理
`external`はプランニングのたびにプロセスをフォークする。数千のリソースに対して`external`を多用すると、Plan時間が指数関数的に増大する。
- 回避策: データをまとめて取得する「バッチ取得スクリプト」を書き、一つのJSONで返す設計にする。細分化しすぎるな。
② エラーハンドリングの極致
スクリプトが失敗した場合、Terraformは即座に停止すべきだ。
- `stderr` を活用せよ。`external`プロバイダは `stderr` への出力をログとして捉える。デバッグ時には `log` に情報を吐き出し、`stdout` には純粋なJSONだけを流す。これがプロの流儀だ。
③ セキュリティ上の注意点
`query` には決して機密情報(APIキーやパスワード)を直接渡してはならない。Terraformのステートファイルに平文で残るリスクがある。
- 解法: 環境変数 `TF_VAR_` を経由してスクリプト内部で認証を行うか、AWS Secrets Manager等のセキュアなストレージをスクリプト内から直接参照せよ。
—
5. 終わりに:伝説的なアーキテクトからの助言
`external`プロバイダは、Terraformという閉じた箱に「外部の知性」を接続するための、唯一無二のバックドアだ。しかし、多用はコードの可読性とメンテナンス性を殺す。
これを使うのは、「Terraformプロバイダが存在しないニッチな領域」、あるいは「社内特有の動的データ」を扱う、最後の手段としてとっておけ。
道具を掌握するとは、その道具を使わない勇気を持つことでもある。だが、どうしても越えられない壁にぶち当たった時、このJSONの導管を思い出してほしい。その時、君はTerraformの設計思想そのものを拡張する領域に到達しているはずだ。
さあ、コードを書け。インフラを、コードの支配下に置くのだ。