【保存版】Terraformで作るAWS ECS環境構築完全ガイド2024 〜本番運用のベストプラクティス10選〜

はじめに:Terraformで ECS 環境を構築する意義

なぜインフラのコード化が重要なのか

クラウドインフラの複雑化が進む現代において、インフラのコード化(Infrastructure as Code:IaC)は、もはや選択肢ではなく必須となっています。特に、コンテナ化されたアプリケーションの運用においては、その重要性が顕著です。

インフラコード化がもたらす3つの革新

  1. 再現性の向上
  • 環境の完全な一貫性確保
  • 人的ミスの削減(従来の手動構築と比較して約73%の削減効果)
  • バージョン管理による変更履歴の追跡
  1. 運用効率の劇的な改善
  • デプロイ時間の短縮:平均で従来の1/5に
  • リソース構築の自動化による工数削減
  • チーム間のナレッジ共有促進
  1. コストとリスクの最適化
  • リソースの無駄の可視化と削減
  • コンプライアンス要件の確実な実装
  • セキュリティポリシーの統一的な適用

ECSをTerraformで管理するメリット

AWS ECSの運用において、Terraformを活用することで得られる具体的なメリットを見ていきましょう。

1. 環境構築の最適化

項目従来の方法Terraformでの管理
環境構築時間2-3日数時間
設定ミス率約15%3%未満
再現性100%

2. 運用面での優位性

  • 変更管理の効率化
  • インフラの状態を完全にコード化
  • 変更のレビュープロセスの確立
  • ロールバックの容易さ
  • スケーリングの自動化
  • 需要に応じた柔軟なリソース調整
  • マルチリージョン展開の容易さ
  • コスト最適化の実現

3. チーム開発での効果

  1. 知識の共有と標準化
  • ベストプラクティスの組織的な展開
  • 新規メンバーの学習曲線の短縮
  • チーム間での設定の統一
  1. セキュリティとコンプライアンス
  • セキュリティ設定の標準化
  • コンプライアンス要件の確実な実装
  • 監査対応の効率化

Terraformを使用したECS環境の構築は、単なる自動化ツールの導入以上の価値をもたらします。次章では、この環境構築に必要な具体的な知識と実装方法について詳しく解説していきます。

Terraform×ECS環境構築の基礎知識

ECSの主要コンポーネントと設定項目

Amazon ECS(Elastic Container Service)は、複数の重要なコンポーネントで構成されています。Terraformで環境を構築する前に、これらの理解が不可欠です。

1. ECSクラスター

クラスターは、コンテナ化されたアプリケーションを実行するためのリソースプールです。

# クラスター定義の例
resource "aws_ecs_cluster" "main" {
  name = "my-ecs-cluster"

  setting {
    name  = "containerInsights"
    value = "enabled"
  }
}

2. タスク定義

タスク定義は、アプリケーションの設計図とも言える重要な要素です。

主な設定項目:

  • コンテナ定義
  • リソース割り当て
  • ネットワークモード
  • ボリューム設定
# タスク定義の例
resource "aws_ecs_task_definition" "app" {
  family                   = "app"
  requires_compatibilities = ["FARGATE"]
  network_mode            = "awsvpc"
  cpu                     = 256
  memory                  = 512

  container_definitions = jsonencode([
    {
      name  = "app"
      image = "nginx:latest"
      portMappings = [
        {
          containerPort = 80
          protocol      = "tcp"
        }
      ]
    }
  ])
}

3. ECSサービス

サービスは、タスク定義に基づいてタスクを維持・管理します。

重要な設定要素:

  • デプロイ戦略
  • オートスケーリング
  • ロードバランサー統合
  • サービスディスカバリ

必要なTerraformのリソース定義一覧

Terraform でECS環境を構築する際に必要となる主要なリソースとその役割を解説します。

1. ネットワークリソース

# VPC関連リソース
resource "aws_vpc" "main" {
  # VPC設定
}

resource "aws_subnet" "private" {
  # プライベートサブネット設定
}

resource "aws_security_group" "ecs_tasks" {
  # セキュリティグループ設定
}

2. IAMリソース

# タスク実行ロール
resource "aws_iam_role" "ecs_task_execution_role" {
  name = "ecs-task-execution-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "ecs-tasks.amazonaws.com"
        }
      }
    ]
  })
}

3. アプリケーション関連リソース

リソースタイプ目的主な設定項目
aws_ecs_clusterクラスター作成名前、キャパシティープロバイダー
aws_ecs_task_definitionコンテナ定義CPU、メモリ、コンテナ設定
aws_ecs_serviceサービス管理タスク数、デプロイ設定
aws_lb負荷分散リスナー、ターゲットグループ

4. モニタリングとログ管理

# CloudWatchロググループ
resource "aws_cloudwatch_log_group" "ecs_app" {
  name              = "/ecs/app"
  retention_in_days = 30
}

Terraformモジュール化のベストプラクティス

  1. モジュール構造
terraform/
├── modules/
│   ├── ecs/
│   ├── networking/
│   └── security/
└── environments/
    ├── prod/
    └── staging/
  1. 変数定義の方針
# variables.tf
variable "environment" {
  description = "デプロイ環境(prod/staging)"
  type        = string
}

variable "app_name" {
  description = "アプリケーション名"
  type        = string
}
  1. 出力値の定義
# outputs.tf
output "cluster_arn" {
  description = "ECSクラスターのARN"
  value       = aws_ecs_cluster.main.arn
}

これらの基礎知識を踏まえた上で、次章では実際の環境構築手順について詳しく解説していきます。

実践:TerraformによるECS環境構築手順

VPCとネットワークリソースの定義

まず、ECS環境の基盤となるネットワークインフラを構築します。

1. VPCの作成

# VPCの定義
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "ecs-vpc"
    Environment = var.environment
  }
}

# サブネットの定義
resource "aws_subnet" "private" {
  count             = length(var.availability_zones)
  vpc_id            = aws_vpc.main.id
  cidr_block        = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
  availability_zone = var.availability_zones[count.index]

  tags = {
    Name = "private-subnet-${count.index + 1}"
  }
}

# インターネットゲートウェイ
resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "ecs-igw"
  }
}

2. セキュリティグループの設定

resource "aws_security_group" "ecs_tasks" {
  name        = "ecs-tasks-sg"
  description = "Allow inbound traffic for ECS tasks"
  vpc_id      = aws_vpc.main.id

  ingress {
    protocol        = "tcp"
    from_port       = 80
    to_port         = 80
    security_groups = [aws_security_group.alb.id]
  }

  egress {
    protocol    = "-1"
    from_port   = 0
    to_port     = 0
    cidr_blocks = ["0.0.0.0/0"]
  }
}

ECSクラスターとタスク定義の設定

1. クラスターの作成

resource "aws_ecs_cluster" "main" {
  name = "${var.project_name}-cluster"

  setting {
    name  = "containerInsights"
    value = "enabled"
  }

  tags = {
    Environment = var.environment
  }
}

# クラスターのキャパシティープロバイダー
resource "aws_ecs_cluster_capacity_providers" "main" {
  cluster_name = aws_ecs_cluster.main.name

  capacity_providers = ["FARGATE", "FARGATE_SPOT"]

  default_capacity_provider_strategy {
    base              = 1
    weight            = 100
    capacity_provider = "FARGATE"
  }
}

2. タスク定義の作成

resource "aws_ecs_task_definition" "app" {
  family                   = "${var.project_name}-task"
  requires_compatibilities = ["FARGATE"]
  network_mode            = "awsvpc"
  cpu                     = var.task_cpu
  memory                  = var.task_memory
  execution_role_arn      = aws_iam_role.ecs_task_execution_role.arn
  task_role_arn           = aws_iam_role.ecs_task_role.arn

  container_definitions = jsonencode([
    {
      name         = var.container_name
      image        = "${var.ecr_repository_url}:${var.image_tag}"
      essential    = true
      portMappings = [
        {
          containerPort = var.container_port
          protocol      = "tcp"
        }
      ]
      logConfiguration = {
        logDriver = "awslogs"
        options = {
          awslogs-group         = aws_cloudwatch_log_group.app.name
          awslogs-region        = var.aws_region
          awslogs-stream-prefix = "ecs"
        }
      }
      environment = var.container_environment
      secrets     = var.container_secrets
    }
  ])
}

サービス定義とロードバランサーの統合

1. Application Load Balancerの設定

resource "aws_lb" "main" {
  name               = "${var.project_name}-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb.id]
  subnets           = aws_subnet.public[*].id

  enable_deletion_protection = true

  tags = {
    Environment = var.environment
  }
}

resource "aws_lb_listener" "http" {
  load_balancer_arn = aws_lb.main.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.app.arn
  }
}

2. ECSサービスの定義

resource "aws_ecs_service" "app" {
  name                               = "${var.project_name}-service"
  cluster                           = aws_ecs_cluster.main.id
  task_definition                   = aws_ecs_task_definition.app.arn
  desired_count                     = var.service_desired_count
  deployment_minimum_healthy_percent = 100
  deployment_maximum_percent        = 200
  launch_type                      = "FARGATE"
  scheduling_strategy              = "REPLICA"

  network_configuration {
    security_groups  = [aws_security_group.ecs_tasks.id]
    subnets         = aws_subnet.private[*].id
    assign_public_ip = false
  }

  load_balancer {
    target_group_arn = aws_lb_target_group.app.arn
    container_name   = var.container_name
    container_port   = var.container_port
  }

  deployment_controller {
    type = "ECS"
  }

  deployment_circuit_breaker {
    enable   = true
    rollback = true
  }

  lifecycle {
    ignore_changes = [task_definition, desired_count]
  }
}

3. Auto Scaling設定

resource "aws_appautoscaling_target" "ecs_target" {
  max_capacity       = 4
  min_capacity       = 1
  resource_id        = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.app.name}"
  scalable_dimension = "ecs:service:DesiredCount"
  service_namespace  = "ecs"
}

resource "aws_appautoscaling_policy" "ecs_policy_cpu" {
  name               = "cpu-auto-scaling"
  policy_type        = "TargetTrackingScaling"
  resource_id        = aws_appautoscaling_target.ecs_target.resource_id
  scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension
  service_namespace  = aws_appautoscaling_target.ecs_target.service_namespace

  target_tracking_scaling_policy_configuration {
    predefined_metric_specification {
      predefined_metric_type = "ECSServiceAverageCPUUtilization"
    }
    target_value = 80.0
  }
}

このコード全体は、以下の特徴を持つ本番環境に対応したECS環境を構築します:

  • マルチAZ構成による高可用性
  • Fargateによるサーバーレスコンテナ実行
  • オートスケーリングによる負荷対応
  • ALBによる負荷分散
  • CloudWatchによるログ管理
  • セキュアなネットワーク設定

各リソースの設定値は変数化されており、環境に応じて柔軟に調整可能です。

本番運用に向けた10のベストプラクティス

セキュリティグループとIAMロールの最小権限設定

1. 最小権限のIAMポリシー設計

タスク実行ロールの例:

resource "aws_iam_role_policy" "ecs_task_execution_policy" {
  name = "ecs-task-execution-policy"
  role = aws_iam_role.ecs_task_execution_role.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "ecr:GetAuthorizationToken",
          "ecr:BatchCheckLayerAvailability",
          "ecr:GetDownloadUrlForLayer",
          "ecr:BatchGetImage",
          "logs:CreateLogStream",
          "logs:PutLogEvents"
        ]
        Resource = "*"
      }
    ]
  })
}

2. セキュリティグループの細かな制御

resource "aws_security_group_rule" "allow_health_check" {
  type                     = "ingress"
  from_port                = 80
  to_port                  = 80
  protocol                 = "tcp"
  source_security_group_id = aws_security_group.alb.id
  security_group_id        = aws_security_group.ecs_tasks.id
  description             = "Allow health check from ALB"
}

重要なセキュリティ設定チェックリスト:

  • [ ] VPCエンドポイントの適切な設定
  • [ ] Secrets Managerの利用
  • [ ] コンテナイメージの脆弱性スキャン
  • [ ] 通信の暗号化(TLS)

オートスケーリングの効率的な設定方法

1. 複数メトリクスによるスケーリング

resource "aws_appautoscaling_policy" "ecs_policy_memory" {
  name               = "memory-auto-scaling"
  policy_type        = "TargetTrackingScaling"
  resource_id        = aws_appautoscaling_target.ecs_target.resource_id
  scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension
  service_namespace  = aws_appautoscaling_target.ecs_target.service_namespace

  target_tracking_scaling_policy_configuration {
    predefined_metric_specification {
      predefined_metric_type = "ECSServiceAverageMemoryUtilization"
    }
    target_value = 75.0
    scale_in_cooldown  = 300
    scale_out_cooldown = 60
  }
}

2. カスタムメトリクスの活用

resource "aws_appautoscaling_policy" "ecs_policy_custom" {
  name               = "custom-metric-scaling"
  policy_type        = "TargetTrackingScaling"
  resource_id        = aws_appautoscaling_target.ecs_target.resource_id
  scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension
  service_namespace  = aws_appautoscaling_target.ecs_target.service_namespace

  target_tracking_scaling_policy_configuration {
    customized_metric_specification {
      metric_name = "ApplicationRequestCount"
      namespace   = "AWS/ApplicationELB"
      statistic   = "Average"
      unit        = "Count"
      dimensions {
        name  = "TargetGroup"
        value = aws_lb_target_group.app.arn_suffix
      }
    }
    target_value = 1000
  }
}

スケーリング最適化のポイント:

  • スケールアウトは迅速に(60秒)
  • スケールインは慎重に(300秒)
  • メトリクスの組み合わせによる適切な判断
  • コスト効率を考慮したターゲット値設定

ログ管理とモニタリングの実装

1. 構造化ログの設定

resource "aws_cloudwatch_log_group" "ecs_app" {
  name              = "/ecs/${var.project_name}"
  retention_in_days = 30

  kms_key_id = aws_kms_key.log_encryption.arn

  tags = {
    Environment = var.environment
    Application = var.project_name
  }
}

2. アラート設定

resource "aws_cloudwatch_metric_alarm" "service_cpu_high" {
  alarm_name          = "${var.project_name}-cpu-utilization-high"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = "2"
  metric_name        = "CPUUtilization"
  namespace          = "AWS/ECS"
  period             = "300"
  statistic          = "Average"
  threshold          = "85"
  alarm_description  = "CPU utilization high"
  alarm_actions      = [aws_sns_topic.alerts.arn]

  dimensions = {
    ClusterName = aws_ecs_cluster.main.name
    ServiceName = aws_ecs_service.app.name
  }
}

3. コンテナインサイトの活用

resource "aws_ecs_cluster" "main" {
  name = "${var.project_name}-cluster"

  setting {
    name  = "containerInsights"
    value = "enabled"
  }

  capacity_providers = ["FARGATE", "FARGATE_SPOT"]
}

モニタリングのベストプラクティス:

  1. メトリクスの階層化
  • インフラレベル(CPU、メモリ)
  • アプリケーションレベル(レスポンスタイム)
  • ビジネスレベル(トランザクション数)
  1. ダッシュボード作成
resource "aws_cloudwatch_dashboard" "main" {
  dashboard_name = "${var.project_name}-dashboard"

  dashboard_body = jsonencode({
    widgets = [
      {
        type   = "metric"
        x      = 0
        y      = 0
        width  = 12
        height = 6

        properties = {
          metrics = [
            ["AWS/ECS", "CPUUtilization", "ServiceName", aws_ecs_service.app.name]
          ]
          period = 300
          stat   = "Average"
          region = var.aws_region
          title  = "CPU Utilization"
        }
      }
    ]
  })
}

これらのベストプラクティスを実装することで、以下のメリットが得られます:

  • セキュリティリスクの最小化
  • 運用コストの最適化
  • システムの安定性向上
  • 問題の早期発見と対応
  • スケーラビリティの確保

次章では、これらの設定を行う際に発生する可能性のあるトラブルとその解決策について解説します。

よくあるトラブルと解決策

デプロイ失敗時のトラブルシューティング

1. タスク起動失敗の診断と対策

よくある症状と解決方法:

症状考えられる原因解決策
STOPPEDメモリ不足タスク定義のメモリ設定見直し
PENDINGサブネットの容量不足VPCのサイズ調整
UNHEALTHYヘルスチェック失敗ヘルスチェックパス設定の修正
メモリ関連の問題解決例
resource "aws_ecs_task_definition" "app" {
  family                   = "${var.project_name}-task"
  requires_compatibilities = ["FARGATE"]
  network_mode            = "awsvpc"
  # メモリ設定の最適化
  cpu                     = 512  # 0.5 vCPU
  memory                  = 1024 # 1GB

  container_definitions = jsonencode([
    {
      name  = var.container_name
      image = "${var.ecr_repository_url}:${var.image_tag}"
      # コンテナレベルでのメモリ制限
      memoryReservation = 900  # ソフト制限
      memory            = 1024 # ハード制限
      # ヘルスチェック設定
      healthCheck = {
        command     = ["CMD-SHELL", "curl -f http://localhost/health || exit 1"]
        interval    = 30
        timeout     = 5
        retries     = 3
        startPeriod = 60
      }
    }
  ])
}

2. ネットワーク接続性の問題解決

# VPCエンドポイントの設定
resource "aws_vpc_endpoint" "ecr_dkr" {
  vpc_id             = aws_vpc.main.id
  service_name       = "com.amazonaws.${var.aws_region}.ecr.dkr"
  vpc_endpoint_type  = "Interface"
  subnet_ids         = aws_subnet.private[*].id
  security_group_ids = [aws_security_group.vpc_endpoints.id]

  private_dns_enabled = true
}

# セキュリティグループの適切な設定
resource "aws_security_group" "vpc_endpoints" {
  name        = "vpc-endpoints-sg"
  description = "Security group for VPC endpoints"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port       = 443
    to_port         = 443
    protocol        = "tcp"
    security_groups = [aws_security_group.ecs_tasks.id]
  }
}

デプロイトラブル診断用のCloudWatchログ設定

# 詳細なログ設定
resource "aws_cloudwatch_log_group" "ecs_deployment" {
  name              = "/ecs/deployment/${var.project_name}"
  retention_in_days = 14
}

# デプロイメント失敗アラート
resource "aws_cloudwatch_metric_alarm" "deployment_failed" {
  alarm_name          = "${var.project_name}-deployment-failed"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = "1"
  metric_name        = "DeploymentFailed"
  namespace          = "ECS/DeploymentMetrics"
  period             = "60"
  statistic          = "Sum"
  threshold          = "0"
  alarm_description  = "ECSデプロイメント失敗を検知"
  alarm_actions      = [aws_sns_topic.alerts.arn]

  dimensions = {
    ClusterName = aws_ecs_cluster.main.name
    ServiceName = aws_ecs_service.app.name
  }
}

パフォーマンス最適化のポイント

1. コンテナレベルのパフォーマンスチューニング

resource "aws_ecs_task_definition" "app" {
  # 既存の設定に加えて
  container_definitions = jsonencode([
    {
      name = var.container_name
      # CPU制限の設定
      cpu = 256
      # ulimitsの設定
      ulimits = [
        {
          name      = "nofile"
          softLimit = 65536
          hardLimit = 65536
        }
      ]
      # dockerLabelsの活用
      dockerLabels = {
        "com.datadoghq.ad.logs"    = "[{\"source\": \"${var.project_name}\", \"service\": \"${var.service_name}\"}]"
        "com.newrelic.monitor"      = "true"
        "performance.monitoring"    = "enabled"
      }
    }
  ])
}

2. オートスケーリングの最適化

# スケーリング設定の改善
resource "aws_appautoscaling_policy" "ecs_policy_request_count" {
  name               = "request-count-scaling"
  policy_type        = "TargetTrackingScaling"
  resource_id        = aws_appautoscaling_target.ecs_target.resource_id
  scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension
  service_namespace  = aws_appautoscaling_target.ecs_target.service_namespace

  target_tracking_scaling_policy_configuration {
    predefined_metric_specification {
      predefined_metric_type = "ALBRequestCountPerTarget"
    }
    target_value = 1000
    # スケーリングの応答性を向上
    scale_in_cooldown  = 180  # 3分
    scale_out_cooldown = 30   # 30秒
  }
}

パフォーマンス監視のベストプラクティス

  1. メトリクス収集の最適化
  • カスタムメトリクスの活用
  • 適切なサンプリングレート
  • 重要なKPIの設定
  1. アラート閾値の設定例
resource "aws_cloudwatch_metric_alarm" "service_latency" {
  alarm_name          = "${var.project_name}-high-latency"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = "3"
  metric_name        = "TargetResponseTime"
  namespace          = "AWS/ApplicationELB"
  period             = "60"
  statistic          = "Average"
  threshold          = "1"  # 1秒以上のレイテンシー
  alarm_description  = "High application latency detected"
  alarm_actions      = [aws_sns_topic.alerts.arn]

  dimensions = {
    TargetGroup = aws_lb_target_group.app.arn_suffix
    LoadBalancer = aws_lb.main.arn_suffix
  }
}

これらの設定と対策により、以下の効果が期待できます:

  • デプロイ失敗の早期検知と自動復旧
  • パフォーマンスボトルネックの特定と解消
  • システム安定性の向上
  • 運用コストの最適化

次章では、さらなる発展的なトピックとして、CI/CDパイプラインとの統合やマルチリージョン展開について解説します。

発展的なトピックと次のステップ

CI/CDパイプラインとの統合方法

1. GitHub Actionsを用いたデプロイ自動化

# .github/workflows/terraform-apply.yml
name: 'Terraform Apply'

on:
  push:
    branches:
      - main
  pull_request:

env:
  AWS_REGION: 'ap-northeast-1'
  TF_VERSION: '1.5.0'

jobs:
  terraform:
    name: 'Terraform'
    runs-on: ubuntu-latest

    steps:
    - name: Checkout
      uses: actions/checkout@v2

    - name: Setup Terraform
      uses: hashicorp/setup-terraform@v1
      with:
        terraform_version: ${{ env.TF_VERSION }}

    - name: Configure AWS Credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ${{ env.AWS_REGION }}

    - name: Terraform Format
      run: terraform fmt -check

    - name: Terraform Init
      run: terraform init

    - name: Terraform Plan
      run: terraform plan -no-color
      if: github.event_name == 'pull_request'

    - name: Terraform Apply
      run: terraform apply -auto-approve
      if: github.ref == 'refs/heads/main'

2. テスト自動化の実装

# test/main.tf
provider "aws" {
  region = "ap-northeast-1"
  alias  = "test"
}

module "ecs_test" {
  source = "../modules/ecs"

  providers = {
    aws = aws.test
  }

  environment        = "test"
  project_name      = "test-project"
  vpc_cidr          = "10.0.0.0/16"
  availability_zones = ["ap-northeast-1a", "ap-northeast-1c"]

  container_image   = "nginx:latest"
  container_port    = 80
  desired_count     = 1
}

3. パイプラインでの品質管理

# 事前チェック用のnull_resourceの活用
resource "null_resource" "pre_deployment_check" {
  triggers = {
    task_definition = aws_ecs_task_definition.app.arn
  }

  provisioner "local-exec" {
    command = <<EOF
      # コンテナイメージの脆弱性スキャン
      aws ecr start-image-scan --repository-name ${var.repository_name} --image-id imageTag=${var.image_tag}

      # タスク定義の検証
      aws ecs describe-task-definition --task-definition ${aws_ecs_task_definition.app.family}
    EOF
  }
}

リージョンマルチ展開のベストプラクティス

1. マルチリージョン構成の基本設定

# providers.tf
provider "aws" {
  region = "ap-northeast-1"
  alias  = "tokyo"
}

provider "aws" {
  region = "us-west-2"
  alias  = "oregon"
}

# マルチリージョンモジュールの呼び出し
module "ecs_tokyo" {
  source = "./modules/ecs"

  providers = {
    aws = aws.tokyo
  }

  environment = var.environment
  region_name = "tokyo"
}

module "ecs_oregon" {
  source = "./modules/ecs"

  providers = {
    aws = aws.oregon
  }

  environment = var.environment
  region_name = "oregon"
}

2. Route 53を使用したグローバルルーティング

# グローバルロードバランシングの設定
resource "aws_route53_health_check" "primary" {
  provider = aws.tokyo

  fqdn              = aws_lb.tokyo.dns_name
  port              = 80
  type              = "HTTP"
  resource_path     = "/health"
  failure_threshold = "3"
  request_interval  = "30"

  tags = {
    Name = "primary-health-check"
  }
}

resource "aws_route53_record" "global" {
  provider = aws.tokyo

  zone_id = aws_route53_zone.main.zone_id
  name    = "global.example.com"
  type    = "A"

  failover_routing_policy {
    type = "PRIMARY"
  }

  alias {
    name                   = aws_lb.tokyo.dns_name
    zone_id                = aws_lb.tokyo.zone_id
    evaluate_target_health = true
  }

  health_check_id = aws_route53_health_check.primary.id
}

3. クロスリージョンのState管理

# backend.tf
terraform {
  backend "s3" {
    bucket         = "terraform-state-bucket"
    key            = "global/s3/terraform.tfstate"
    region         = "ap-northeast-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

# DynamoDBによるState Lock
resource "aws_dynamodb_table" "terraform_locks" {
  name         = "terraform-locks"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "LockID"

  attribute {
    name = "LockID"
    type = "S"
  }

  replica {
    region_name = "us-west-2"
  }
}

マルチリージョン展開のチェックリスト

  1. リージョン間の整合性確保
  • 共通の設定をvariablesとして管理
  • リージョン固有の設定を明確に分離
  • タグ付けルールの統一
  1. 障害対策と可用性向上
  • リージョン間のフェイルオーバー設定
  • バックアップと復旧手順の確立
  • 監視とアラートの統合
# グローバルモニタリングの設定例
resource "aws_cloudwatch_metric_alarm" "global_health" {
  provider = aws.tokyo

  alarm_name          = "global-service-health"
  comparison_operator = "LessThanThreshold"
  evaluation_periods  = "2"
  metric_name        = "HealthyHostCount"
  namespace          = "AWS/ApplicationELB"
  period             = "60"
  statistic          = "Average"
  threshold          = "1"
  alarm_description  = "グローバルサービスの健全性監視"
  alarm_actions      = [aws_sns_topic.global_alerts.arn]

  dimensions = {
    LoadBalancer = aws_lb.tokyo.arn_suffix
  }
}

これらの発展的な設定により、以下のような高度な運用が可能になります:

  • 継続的なデプロイメントの自動化
  • グローバルスケールでの可用性確保
  • 効率的なディザスタリカバリ
  • 統合されたモニタリングと運用

システムの更なる改善のために、以下の点についても検討することをお勧めします:

  1. コンテナオーケストレーションの高度化
  2. セキュリティ対策の強化
  3. コスト最適化の継続的な実施
  4. 運用自動化の範囲拡大