takt/builtins/ja/facets/knowledge/terraform-aws.md
nrslib 1cd063680c feat: Terraform/AWS ピースとファセット一式を追加
hoicil-spot-tf の規約を分析し、専用のピース・ファセットを作成。
plan → implement → 3並列レビュー → fix → COMPLETE のワークフロー。
カテゴリに「インフラストラクチャ」を追加。
2026-02-25 23:50:52 +09:00

7.7 KiB
Raw Blame History

Terraform AWS 知識

モジュール設計

モジュールはドメイン(ネットワーク、データベース、アプリケーション層)単位で分割する。汎用ユーティリティモジュールは作らない。

基準 判定
ドメイン単位のモジュール分割 OK
汎用 "utils" モジュール REJECT
1モジュールに無関係なリソースが混在 REJECT
モジュール間の暗黙的依存 REJECT出力→入力で明示的に接続

モジュール間の依存

モジュール間の依存は出力→入力で明示的に渡す。暗黙的な参照(data ソースで他モジュールのリソースを引く)は避ける。

# OK - 明示的な依存
module "database" {
  source     = "../../modules/database"
  vpc_id     = module.network.vpc_id
  subnet_ids = module.network.private_subnet_ids
}

# NG - 暗黙的な依存
module "database" {
  source = "../../modules/database"
  # vpc_id を渡さず、module 内で data "aws_vpc" で引いている
}

識別変数のパススルー

環境名・サービス名などの識別変数は、ルートモジュールから子モジュールへ明示的に渡す。グローバル変数やハードコードに頼らない。

# OK - 明示的なパススルー
module "database" {
  environment      = var.environment
  service          = var.service
  application_name = var.application_name
}

リソース命名規約

localsname_prefix を計算し、全リソースに一貫して適用する。リソース固有のサフィックスを付加する。

基準 判定
name_prefix パターンで統一命名 OK
各リソースでバラバラに命名 REJECT
AWS 文字数制限を超える名前 REJECT
タグ名が PascalCase でない 警告
# OK - name_prefix で統一
locals {
  name_prefix = "${var.environment}-${var.service}-${var.application_name}"
}

resource "aws_ecs_cluster" "main" {
  name = "${local.name_prefix}-cluster"
}

# NG - 各リソースでバラバラに命名
resource "aws_ecs_cluster" "main" {
  name = "${var.environment}-app-cluster"
}

文字数制限への対応

AWS サービスには名前の文字数制限がある。制限に近い場合は短縮形を使う。

サービス 制限
Target Group 32文字 ${var.environment}-${var.service}-backend-tg
Lambda 関数 64文字 フルプレフィックス可
S3 バケット 63文字 フルプレフィックス可

タグ戦略

provider の default_tags で共通タグを一括設定する。個別リソースでの重複タグ付けは不要。

基準 判定
provider default_tags で一括設定 OK
個別リソースで default_tags と同じタグを重複設定 警告
個別リソースで Name タグのみ追加 OK
# OK - provider で一括、個別は Name のみ
provider "aws" {
  default_tags {
    tags = {
      Environment = var.environment
      ManagedBy   = "Terraform"
    }
  }
}

resource "aws_instance" "main" {
  tags = {
    Name = "${local.name_prefix}-instance"
  }
}

# NG - default_tags と重複
resource "aws_instance" "main" {
  tags = {
    Environment = var.environment
    ManagedBy   = "Terraform"
    Name        = "${local.name_prefix}-instance"
  }
}

ファイル構成パターン

環境ディレクトリ構造

環境ごとにディレクトリを分離し、各環境が独立した状態管理を持つ。

environments/
├── production/
│   ├── terraform.tf       # バージョン制約
│   ├── providers.tf       # プロバイダ設定default_tags
│   ├── backend.tf         # S3 バックエンド
│   ├── variables.tf       # 環境変数
│   ├── main.tf            # モジュール呼び出し
│   └── outputs.tf         # 出力
└── staging/
    └── ...

モジュール内ファイル構成

ファイル 内容
main.tf localsdata ソースのみ
variables.tf 入力変数定義のみ(リソースなし)
outputs.tf 出力定義のみ(リソースなし)
{resource_type}.tf リソースカテゴリごとに1ファイル
templates/ user_data スクリプト等のテンプレート

セキュリティベストプラクティス

EC2 インスタンスセキュリティ

設定 推奨値 理由
http_tokens "required" IMDSv2 強制SSRF 防止)
http_put_response_hop_limit 1 コンテナエスケープ防止
root_block_device.encrypted true 保存データ暗号化

S3 バケットセキュリティ

パブリックアクセスは4項目すべてブロックする。CloudFront 経由の場合は OACOrigin Access Controlを使用する。

# OK - 完全ブロック
resource "aws_s3_bucket_public_access_block" "this" {
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

IAM 設計

パターン 推奨
用途別ロール分離 実行ロールECS Agent 用)とタスクロール(アプリ用)を分ける
CI/CD 認証 OIDC フェデレーション(長期認証情報を使わない)
ポリシースコープ リソース ARN を明示的に指定("*" を避ける)

機密情報管理

方法 推奨度
SSM Parameter StoreSecureString 推奨
Secrets Manager 推奨(ローテーション必要時)
.tfvars に直接記載 条件付きOKgitignore 必須)
.tf ファイルにハードコード REJECT

SSM Parameter の初期値はプレースホルダーにし、lifecycle { ignore_changes = [value] } で Terraform 管理外にする。

コスト最適化パターン

コスト影響のある選択にはインラインコメントでトレードオフを文書化する。

選択 コスト効果 トレードオフ
NAT Instance vs NAT Gateway NAT Instance は月額 ~$3-4 vs Gateway ~$32 可用性・スループットが劣る
パブリックサブネット配置 VPC Endpoint 不要 ネットワーク分離が弱まる
EC2 + EBS vs RDS EC2 は月額 ~$15-20 vs RDS ~$50+ 運用負荷が増える
# OK - トレードオフを文書化
# NAT Gateway の代わりに t3.nano を使用(約 $3-4/月 vs $32/月)
# トレードオフ: 可用性は単一AZ、スループット上限あり
resource "aws_instance" "nat" {
  instance_type = "t3.nano"
}

Lifecycle ルールの使い分け

ルール 用途 適用対象
prevent_destroy 誤削除防止 データベース、EBS ボリューム
ignore_changes 外部変更を許容 desired_countAuto Scaling、SSM の value
create_before_destroy ダウンタイム防止 ロードバランサー、セキュリティグループ
# OK - データベースの誤削除防止
resource "aws_instance" "database" {
  lifecycle {
    prevent_destroy = true
  }
}

# OK - Auto Scaling の desired_count を Terraform 管理外にする
resource "aws_ecs_service" "main" {
  lifecycle {
    ignore_changes = [desired_count]
  }
}

バージョン管理

設定 推奨
required_version ">= 1.5.0" 以上(default_tags サポート)
プロバイダバージョン ~> でマイナーバージョン固定(例: ~> 5.80
状態ロック use_lockfile = true 必須