mcpField
T
terraform

terraform

github.com/iliaalクラウド・DevOps45148 回インストール5 日前に更新
リポジトリ

terraform について

terraform は、Terraform と OpenTofu のインフラコード作業向けスキルです。設定構成、状態の保護、リファクタリング、テストに関する計画と検証の手順を扱います。

主な機能

  1. 01設定ファイルとモジュールの整理
  2. 02状態と認証情報の保護
  3. 03リソースアドレスの安全な変更
  4. 04リソース反復とバージョン制約の計画
  5. 05設定検証とテスト実行

活用シーン

  1. 01インフラモジュールの整理
  2. 02リソース変更計画のレビュー
  3. 03状態ドリフトやロックの調査
  4. 04実インフラを作成せずに設定をテスト

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/iliaal/ai-skills --skill terraform

インストール後、Claude Code で/terraformを入力して読み込まれたか確認します。

同梱ファイルreferences/native-test-patterns.mdSPEC.md

詳細

Terraform と OpenTofu

作業ルール

  • リファクタリング中は状態とリソースアドレスを維持し、意図しない置き換えがないかプランを確認します。
  • ローカルまたはモックによる影響を検証済みのテストと、実サービスにアクセスする、または課金対象のインフラストラクチャを作成するテストを分けます。プランモードでも実際のデータソースを読み取る場合がありますが、モックを使った適用はインフラストラクチャを作成せずに実行できます。

ファイル構成と命名

ファイル用途
terraform.tfTerraform とプロバイダーのバージョン要件
providers.tfプロバイダーの設定
main.tf主要なリソースとデータソース
variables.tf入力変数(アルファベット順)
outputs.tf出力値(アルファベット順)
locals.tfローカル値
  • 小文字とアンダースコアを使用します。webAPI や web-api ではなく web_api のようにします。
  • リソースタイプ名を含めず、内容を表す名詞を使います。aws_instance.web_api_instance ではなく aws_instance.web_api のようにします。
  • 複数形ではなく単数形を使います。
  • モジュール内に同じタイプのリソースが1つだけある場合は、シングルトンリソースに this を使います。
  • 文脈に沿った変数の接頭辞を使います。cidr ではなく vpc_cidr_block のようにします。

ブロックの順序

リソース: count/for_each(後に空行)→ 引数 → ネストされたブロック → tags → depends_on → lifecycle(最後)

変数: description → type → default → validation → nullable

すべての変数に type と description が必要です。すべての出力に description が必要です。シークレットには sensitive = true を指定します。

モジュール構成

種類範囲例
リソースモジュール単一の論理グループVPC とサブネット、SG とルール
インフラストラクチャモジュールリソースモジュールの集合1つのリージョンのネットワーキングとコンピュート
コンポジション完全なインフラストラクチャ複数のリージョン/アカウントにまたがる
module-name/
├── main.tf, variables.tf, outputs.tf, versions.tf
├── examples/
│   ├── minimal/
│   └── complete/
└── tests/
    └── defaults.tftest.hcl

モジュールは小さく保ちます(単一責任)。examples/ はドキュメントと統合テスト用のフィクスチャを兼ねます。公開するすべてのモジュールにセマンティックバージョニングを適用します。

count と for_each

シナリオ使用方法
ブール値の切り替え(作成またはスキップ)count = condition ? 1 : 0
順序が変わる可能性のある名前付き/キー付き項目for_each = toset(list) または map
固定数の同一レプリカcount = N

デフォルトでは for_each を使います。count のリストから途中の項目を削除すると、それ以降のすべてのリソースが再作成されるためです。count はブール値の条件分岐、または本当に同一のレプリカに限って使います。

バージョンの固定

コンポーネント方針例
Terraformマイナーバージョンを固定required_version = "~> 1.9.0"
プロバイダーメジャーバージョンを固定version = "~> 5.0"
モジュール(本番環境)完全一致で固定version = "5.1.2"
モジュール(開発環境)パッチバージョンを許可version = "~> 5.1.0"

主な最新機能:moved ブロック(1.1+)、デフォルト値を指定した optional()(1.3+)、ネイティブテスト(1.6+)、モックプロバイダー(1.7+)、変数間の検証(1.9+)、書き込み専用引数(1.11+)。 Stacks(HCP。現在のリリース状況を確認してください):複数の設定を単一のデプロイ単位としてオーケストレーションします。複数環境のパターンでの利用を検討してください。

状態とセキュリティ

  • ロック機能付きのリモートバックエンドを使用します。S3 の場合は use_lockfile = true(1.10+)、Azure Blob、GCS、または Terraform Cloud を使用します。共有インフラストラクチャでは、ローカル状態を決して使用しないでください。DynamoDB ベースの S3 ロック(dynamodb_table)は非推奨で、削除が予定されています。use_lockfile を優先してください。既存のテーブルから移行する間は、両方を同時に設定できます。
  • OpenTofu 専用:terraform { encryption { key_provider "pbkdf2" "k" {...} method "aes_gcm" "m" { keys = key_provider.pbkdf2.k } state { method = method.aes_gcm.m } plan { method = method.aes_gcm.m } } } を設定すると、状態ファイルとプランファイルがクライアント側で暗号化されます(または TF_ENCRYPTION を使用します)。既存の平文状態を引き続き読み込めるよう、fallback { method = method.unencrypted.x } を設定して段階的に導入してください。また、fallback ブロックなしでキープロバイダーやメソッドの名前を変更しないでください。OpenTofu では backend {} の引数やモジュールの source/version でも var.*/local.* を使用できます(init 時に解決されます。状態やプロバイダー関数への参照は使用できません)。同じ HCL は Terraform ではエラーになります(「A backend block cannot refer to named values」)。
  • 保存時の状態を暗号化してください。.tfstate、.terraform/、*.tfplan は決してコミットしないでください。.terraform.lock.hcl は必ずコミットしてください。
  • リソースのタグ付けを統一するため、プロバイダーに default_tags を設定してください。
  • すべてのストレージで保存時の暗号化を有効にしてください。デフォルトではプライベートネットワークを使用し、パブリックアクセスは明示的に許可した場合のみ有効にしてください。
  • 最小権限のセキュリティグループを使用してください。明確な理由がない限り、0.0.0.0/0 からのインバウンドを許可しないでください。
  • 認証情報をハードコードしないでください。assume_role、OIDC、またはシークレットマネージャーを使用してください。
  • プリコミットでは、まず自動フォーマット(terraform fmt -recursive はファイルを書き換えます)を実行し、その後に検証(terraform validate && tflint && trivy config .)を実行してください。
  • リソース名やモジュール名のリファクタリングで破棄と再作成を行わないよう、from と to のアドレスを指定した moved ブロックを使用してください。下流でのアップグレードに備え、過去の移動定義は保持してください。影響を受けるすべての状態が移行した後、または明示的に破壊的変更を伴うモジュールリリースとしてのみ削除してください。
  • lifecycle { ignore_changes = [attr] } は 更新のみ を抑制し、設定変更後の 最初の プラン時に、以前の状態の値で置き換えます。「最初の適用」の例外はありません。レビュー担当者が誤解しやすい結果が 2 つあります。(1)すでにプロビジョニング済みのリソースでは、設定内のリテラル値は書き込まれません。また、ignore_changes が置換の評価前に差分を消去するため、ForceNew も発動しません。そのため、コミット済みの値をプレースホルダーに置き換える変更はリポジトリから値を消去する一方、リモートの値はそのまま残ります。(2)ignore_changes は作成時には適用されないため、その後の -replace、taint、state rm による削除と再追加、または手動削除の際には、別の手段で設定された値の上にプレースホルダーが再設定されます。設定にはコンテナリソースのみを残し、値はすべて別の手段でプロビジョニングしてください。または、あらゆる置換手順について、復元手順をランブックに明記してください。

トラブルシューティング

  • 状態ロックが解除されない場合:他の操作が実行中でないことを確認してから、terraform force-unlock <ID> を実行します。
  • リソースのドリフト:検出には terraform plan -refresh-only、反映には terraform apply -refresh-only を使用します。
  • tainted リソースを置換する場合:terraform taint(非推奨)ではなく、terraform apply -replace=ADDR を使用します。
  • 既存リソースをインポートする場合:宣言的なインポートには import ブロック(1.5+)、または terraform import ADDR ID を使用します。

依存関係の管理

明示的な depends_on を使わずに削除順序を制御するには、try() と locals を使用します。

locals {
  vpc_id = try(aws_vpc_ipv4_cidr_block_association.this[0].vpc_id, aws_vpc.this.id, "")
}

これにより、Terraform は CIDR 関連付けより先にサブネットを破棄し、削除エラーを防止します。

  • サブネット CIDR の計算には cidrsubnet(var.vpc_cidr, 8, count.index) を使用してください。サブネットをハードコードしないでください。
  • マルチリージョンでは、provider "aws" { alias = "eu_west_1" } と、モジュールブロック内の providers = { aws = aws.eu_west_1 } を使用します。

検証

完了を宣言する前に実行してください。

terraform fmt -check && terraform validate && tflint && trivy config .

すべてのコマンドがエラーなしで成功する必要があります。テストファイルを選ぶ前に、プロバイダー、データソース、プロビジョナー、外部コマンドを確認してください。完了チェックには、安全なプランテストと完全にモック化した適用テストを含めてください。実サービスやインフラストラクチャを使うテストは、タスクの承認範囲とコスト上限の範囲内で実行してください。terraform test -filter=tests/vpc_unit_test.tftest.hcl のように、リポジトリルートからの相対パスでテストファイル名を指定し、対象のファイルが少なくとも1回実行されたことを確認してください。終了コードだけでは、テストが選択されず、未知のフィルターが受け入れられる場合があります。native-test-patterns.md に記載された、検証済みの選択手順を使用してください。

タスク固有のリファレンス

該当する動作を実装またはレビューする前に、関連するリファレンスを読んでください。

  • ネイティブのプラン/適用テスト、フィクスチャの順序、または CI のテスト選択については、native-test-patterns.md を参照してください。

コメント