2025年8月9日土曜日

ECS で利用可能なネットワークモード

 AWS ECS では、以下の 4 つのネットワークモードがサポートされています:

  1. awsvpc
  2. bridge
  3. host
  4. none
各モードの特徴、ユースケース、制限について詳しく説明します。
1. awsvpc ネットワークモード
  • 説明:
    • 各 ECS タスクに専用の Elastic Network Interface (ENI) が割り当てられます。
    • タスクは VPC 内の独自の IP アドレスを持ち、VPC のサブネットやセキュリティグループを直接設定できます。
    • このモードは、コンテナが他の AWS リソース(例: RDS、S3 エンドポイント)と VPC 内で直接通信する必要がある場合に適しています。
  • 主な特徴:
    • IP アドレス: タスクごとにプライベート IP が割り当てられる。
    • セキュリティ: セキュリティグループをタスクレベルで設定可能。
    • トランキング対応: awsvpcTrunking を有効にすると、複数のタスクが 1 つの ENI を共有可能(質問のコードに関連)。
    • Fargate 必須: AWS Fargate を使用する場合、awsvpc が必須。
  • ユースケース:
    • マイクロサービスアーキテクチャで、各コンテナが独立したネットワーク設定を必要とする場合。
    • VPC 内の他のリソースと細かいネットワーク制御(例: セキュリティグループや VPC エンドポイント)が必要な場合。
    • Fargate ベースのデプロイ。
  • 制限:
    • ENI の上限(サブネットやインスタンスごとの制限)に注意が必要。ただし、awsvpcTrunking で緩和可能。
    • EC2 インスタンスでも使用可能だが、Fargate との相性が良い。
  • Terraform での例:
    hcl
    resource "aws_ecs_task_definition" "example" {
      family                   = "example-task"
      network_mode             = "awsvpc"
      requires_compatibilities = ["FARGATE"]
      cpu                      = "256"
      memory                   = "512"
      container_definitions    = jsonencode([
        {
          name  = "example-container"
          image = "amazon/amazon-ecs-sample"
          essential = true
        }
      ])
    }

2. bridge ネットワークモード
  • 説明:
    • Docker のデフォルトのブリッジネットワークを使用します。
    • タスク内のコンテナは、ホスト EC2 インスタンスのネットワークインターフェースを共有し、コンテナ間でローカル通信(localhost)が可能。
    • 外部との通信は、ホストの IP アドレスを介して行われ、ポートマッピングで特定のポートを公開。
  • 主な特徴:
    • IP アドレス: コンテナはホストの IP を共有し、プライベート IP は割り当てられない。
    • ポートマッピング: コンテナのポートをホストのポートにマッピングする必要がある。
    • シンプルな設定: VPC の詳細な設定が不要。
  • ユースケース:
    • 単純なアプリケーションで、VPC 内の詳細なネットワーク制御が不要な場合。
    • 複数のコンテナが同一ホスト内で通信する必要がある場合。
    • EC2 インスタンスを使用した従来型の ECS デプロイ。
  • 制限:
    • Fargate 非対応: bridge モードは Fargate では使用不可。
    • セキュリティグループや VPC 設定をタスクレベルで制御できない。
    • コンテナ間の通信が複雑になる場合がある(ポート衝突の可能性)。
  • Terraform での例:
    hcl
    resource "aws_ecs_task_definition" "example" {
      family                   = "example-task"
      network_mode             = "bridge"
      requires_compatibilities = ["EC2"]
      container_definitions    = jsonencode([
        {
          name  = "example-container"
          image = "amazon/amazon-ecs-sample"
          essential = true
          portMappings = [
            {
              containerPort = 80
              hostPort      = 80
            }
          ]
        }
      ])
    }

3. host ネットワークモード
  • 説明:
    • コンテナがホスト EC2 インスタンスのネットワークスタックを直接使用します。
    • コンテナはホストの IP アドレスとネットワーク設定をそのまま利用し、ポートマッピングは不要。
  • 主な特徴:
    • IP アドレス: コンテナはホストの IP アドレスを直接使用。
    • パフォーマンス: ネットワークオーバーヘッドが少ない。
    • 制限された制御: コンテナごとに独立したネットワーク設定ができない。
  • ユースケース:
    • 高パフォーマンスなネットワークが必要な場合(例: 高トラフィックのウェブサーバー)。
    • ホストのネットワーク設定をそのまま利用したい場合。
  • 制限:
    • Fargate 非対応: host モードは Fargate では使用不可。
    • ポート衝突のリスクがある(同一ホスト上で同じポートを複数のコンテナで使用できない)。
    • セキュリティグループをタスクレベルで設定できない。
  • Terraform での例:
    hcl
    resource "aws_ecs_task_definition" "example" {
      family                   = "example-task"
      network_mode             = "host"
      requires_compatibilities = ["EC2"]
      container_definitions    = jsonencode([
        {
          name  = "example-container"
          image = "amazon/amazon-ecs-sample"
          essential = true
        }
      ])
    }

4. none ネットワークモード
  • 説明:
    • コンテナにネットワークインターフェースが割り当てられません。
    • 外部ネットワークとの通信が完全に無効化され、コンテナは完全に孤立した状態になります。
  • 主な特徴:
    • ネットワーク無効: コンテナはネットワークに接続しない。
    • ローカル通信のみ: ファイルシステムやボリュームを介した通信のみ可能。
  • ユースケース:
    • ネットワーク接続が不要なバッチ処理やオフライン処理。
    • セキュリティを最大化したい場合(外部通信を完全に遮断)。
  • 制限:
    • Fargate 非対応: none モードは Fargate では使用不可。
    • 外部リソース(例: S3、RDS)へのアクセスができない。
  • Terraform での例:
    hcl
    resource "aws_ecs_task_definition" "example" {
      family                   = "example-task"
      network_mode             = "none"
      requires_compatibilities = ["EC2"]
      container_definitions    = jsonencode([
        {
          name  = "example-container"
          image = "amazon/amazon-ecs-sample"
          essential = true
        }
      ])
    }

ネットワークモードの比較
モード
Fargate 対応
IP アドレス
セキュリティグループ
ポートマッピング
ユースケース
awsvpc
対応
タスクごとの専用 IP
タスク単位で設定可能
不要
マイクロサービス、Fargate、VPC 統合
bridge
非対応
ホストの IP を共有
ホスト単位で設定
必要
従来型 ECS、シンプルなアプリ
host
非対応
ホストの IP を使用
ホスト単位で設定
不要
高パフォーマンスが必要なアプリ
none
非対応
なし
なし
不要
ネットワーク不要のバッチ処理

awsvpc 以外の選択肢を選ぶ際の考慮点
  1. Fargate か EC2 か:
    • Fargate を使用する場合、awsvpc モードが必須です。他のモードは EC2 インスタンスでのみ使用可能です。
  2. ネットワーク制御の必要性:
    • awsvpc はセキュリティグループやサブネットをタスクレベルで制御できるため、複雑なネットワーク構成に適しています。
    • bridgehost はホストレベルでの制御となり、細かい設定が難しい。
  3. スケーラビリティ:
    • awsvpc は ENI の上限に注意が必要ですが、awsvpcTrunking(質問のコードで有効化)を活用することでスケーラビリティを向上できます。
    • bridgehost はポート衝突のリスクがあり、大規模なデプロイでは管理が複雑になる可能性があります。
  4. パフォーマンス:
    • host モードはオーバーヘッドが少なく、高パフォーマンスですが、柔軟性が低い。
    • awsvpc はパフォーマンスと柔軟性のバランスが良い。
  5. セキュリティ:
    • awsvpc はタスクごとのセキュリティグループ設定が可能で、セキュリティ要件が高い場合に適しています。
    • none は外部通信を完全に遮断するため、最高レベルの分離を提供します。

Terraform での設定例(複数モードの比較)以下は、異なるネットワークモードを同じタスク定義で切り替える例です:
hcl
resource "aws_ecs_task_definition" "awsvpc_task" {
  family                   = "awsvpc-task"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                      = "256"
  memory                   = "512"
  container_definitions    = jsonencode([
    {
      name  = "example-container"
      image = "amazon/amazon-ecs-sample"
      essential = true
    }
  ])
}

resource "aws_ecs_task_definition" "bridge_task" {
  family                   = "bridge-task"
  network_mode             = "bridge"
  requires_compatibilities = ["EC2"]
  container_definitions    = jsonencode([
    {
      name  = "example-container"
      image = "amazon/amazon-ecs-sample"
      essential = true
      portMappings = [
        {
          containerPort = 80
          hostPort      = 80
        }
      ]
    }
  ])
}

resource "aws_ecs_task_definition" "host_task" {
  family                   = "host-task"
  network_mode             = "host"
  requires_compatibilities = ["EC2"]
  container_definitions    = jsonencode([
    {
      name  = "example-container"
      image = "amazon/amazon-ecs-sample"
      essential = true
    }
  ])
}

resource "aws_ecs_task_definition" "none_task" {
  family                   = "none-task"
  network_mode             = "none"
  requires_compatibilities = ["EC2"]
  container_definitions    = jsonencode([
    {
      name  = "example-container"
      image = "amazon/amazon-ecs-sample"
      essential = true
    }
  ])
}