⚔️
概念 #Kubernetes #ECS #AWS #コンテナ #オーケストレーション 📚 TCPIPネットワーク

K8s vs ECS:設計思想とアナロジーで理解する

ホテル・マンション・自分の家のアナロジーでK8sとECSの違いを直感的に解説。選択基準・ネットワーク・エコシステムの比較。

一言アナロジー

ECS Fargate    ホテルに泊まる
               → チェックインして荷物を置くだけ。清掃・設備管理はホテルが全部やる

ECS on EC2     サービスアパートメント
               → 部屋は借りているが、家具配置や一部の設備は自分で管理

EKS / GKE      管理会社付きマンション
               → 共用部分(エレベーター・外壁)は管理会社が担当。
                 部屋の中(アプリ・設定)は自分の責任

K8s 自前運用   土地を買って自分で家を建てる
               → 設計の自由度は最大。でも配管工事から固定資産税まで全部自分

Control Plane:誰がオーケストレーターを管理するか

コンテナを「どのホストで動かすか」「何台に増減するか」を決める頭脳部分。

【ECS】
  Control Plane = AWSが完全管理・無料
  ユーザーが気にすることはゼロ

  [AWS] ─── ECS Control Plane(無料)
               │ スケジューリング・ヘルスチェック・再起動

  [ユーザー] ─ TaskDefinition + Service の定義だけ書く

【K8s(EKS)】
  Control Plane = AWSが管理するが料金が発生
  EKS: $0.10/hr = 約$72/月(クラスター1つあたり)

  [AWS] ─── EKS Control Plane(有料)
               │ kube-apiserver / etcd / scheduler / controller-manager

  [ユーザー] ─ Node(EC2/Fargate)の管理 + マニフェストの管理

【K8s 自前】
  全部自分で構築・管理
  kubeadm / k3s / kops 等でクラスター構築
  etcdのバックアップ、証明書ローテーション、アップグレードも全部自分

デプロイ単位の比較

ECS の概念

Cluster(インフラのグループ)
└── Service(何台動かすか・どう更新するか)
    └── Task(1回の実行単位)
        └── TaskDefinition(コンテナの設定テンプレート)
            ├── Container A(アプリ)
            └── Container B(ログ収集サイドカー)

K8s の概念

Cluster
└── Namespace(論理的な分離単位)
    └── Deployment(ロールアウト戦略・レプリカ数を管理)
        └── ReplicaSet(実際のPod数を維持)
            └── Pod(1回のデプロイ単位)
                ├── Container A(アプリ)
                └── Container B(サイドカー)

対応関係

ECSK8s説明
ClusterClusterインフラのグループ
ServiceDeployment + Service「何台動かすか」と「どうアクセスするか」が分離
TaskPod1つ以上のコンテナのグループ
TaskDefinitionPodSpec(Deployment内)コンテナの設定テンプレート
Service DiscoveryService + CoreDNSサービス間通信のエンドポイント
ALB Target GroupIngressL7ルーティング
CloudWatch LogsFluentd/Lokiログ収集
IAM Task RoleServiceAccount + IRSA/Workload IdentityPodのクレデンシャル

ネットワークモデルの違い

ECS の VPC Native ネットワーク(awsvpc モード)

【Fargate awsvpc モード】

VPC (10.0.0.0/16)
└── Private Subnet (10.0.2.0/24)
    ├── Task A: ENI → 10.0.2.10  ← タスクが直接VPC IPを持つ
    ├── Task B: ENI → 10.0.2.11
    └── Task C: ENI → 10.0.2.12

特徴:
  ・Taskが直接VPCのIPアドレスを持つ(追加の抽象層なし)
  ・Security GroupをTaskレベルで設定可能
  ・VPC Flow Logsでそのまま追跡可能
  ・シンプルで理解しやすい

K8s のネットワーク(CNI + Service)

【K8s(EKS)のネットワーク】

VPC (10.0.0.0/16)
└── Node (EC2: 10.0.2.10)
    ├── Pod A: 10.244.0.2  ← Podは別のIPアドレス空間
    ├── Pod B: 10.244.0.3
    └── Pod C: 10.244.0.4

外部からPodへのアクセス:
  Internet → ALB → NodePort → kube-proxy → Pod
  ※ PodのIPは直接公開されない(Serviceを経由)

特徴:
  ・IPアドレス空間がNodeとPodで2層になる
  ・抽象度が高い分、理解とデバッグが難しい
  ・NetworkPolicyでPod間通信を細かく制御可能
  ・AWSのVPC CNIを使うとPodが直接VPC IPを持てる(EKS特有)

エコシステムと移植性

【ECS】
  ・完全にAWSエコシステム
  ・ALB / RDS / ElastiCache / IAM との統合がネイティブ
  ・移植性はない(AWSから出られない)
  ・学習コストが低い

【K8s】
  ・CNCF(Cloud Native Computing Foundation)の標準
  ・GKE → EKS → AKS → オンプレ の移植が原則可能
    (実際はクラウド固有の機能を使うと移植コストがかかる)
  ・Helm / ArgoCD / Istio / Prometheus など豊富なエコシステム
  ・学習コストが高い

移植性の実態:
  「K8sにしたから移植できる」は半分正しい。
  StorageClass / Ingress Controller / LoadBalancer の実装は
  クラウドごとに異なる。完全な移植には追加コストがかかる。

選択基準マトリクス

┌─────────────────────────────┬──────────────────┬───────────────┐
│  状況                        │  推奨             │  理由          │
├─────────────────────────────┼──────────────────┼───────────────┤
│ AWSに閉じた小〜中規模サービス │  ECS Fargate     │ 管理コスト最小 │
│ チームがK8s未経験            │  ECS Fargate     │ 学習コスト低   │
│ シンプルなマイクロサービス    │  ECS             │ 過剰設計を避ける│
│ 複雑なデプロイ戦略が必要     │  K8s             │ 豊富な制御機能 │
│ マルチクラウド・オンプレ混在  │  K8s             │ 移植性        │
│ Service Meshが必要          │  K8s             │ Istio/Linkerd │
│ チームにK8s経験者がいる      │  K8s             │ 経験を活かせる │
│ コスト最優先(小規模)       │  ECS Fargate     │ Control Plane代なし│
└─────────────────────────────┴──────────────────┴───────────────┘

規模別の目安

〜10サービス:ECS Fargate で十分なことが多い
10〜50サービス:チームの経験次第。K8sの恩恵が出始める
50サービス〜:K8sのエコシステム(NetworkPolicy, ServiceMesh等)が効く

共通の落とし穴

どちらを選んでも起きるコンテナ運用のハマりポイント。

①  コンテナのリソース制限を設定しない
   → OOM Killer でアプリが突然死ぬ
   → CPU スロットリングで予期せぬ遅延
   → K8s: requests/limits / ECS: cpu/memory を必ず設定

②  ヘルスチェックを甘く設定する
   → 起動が遅いアプリが「不健全」と判定されて無限再起動
   → initialDelaySeconds(K8s)/ startPeriod(ECS)を適切に設定

③  環境変数にシークレットを直書き
   → K8s: Secret リソース + IRSA
   → ECS: Secrets Manager / Parameter Store の参照

④  ログをファイルに書き出す
   → コンテナが消えるとログも消える
   → stdout/stderr に書いてログドライバーで収集

⑤  1コンテナに複数プロセスを詰め込む
   → PID 1 問題(シグナルハンドリング・ゾンビプロセス)
   → tini / dumb-init を使うか、プロセスを分離

コスト比較(目安)

構成例:2 vCPU / 4GB メモリ × 3タスク/Pod を東京リージョンで24時間運用

ECS Fargate:
  2 vCPU × $0.04048/vCPU時間 × 24時間 × 3 = 約$5.8/日
  4 GB  × $0.004445/GB時間   × 24時間 × 3 = 約$1.3/日
  合計:約$7.1/日 ≒ 約¥1,065/日(Control Plane代なし)

EKS + EC2(m5.large × 3ノード):
  EC2 m5.large: $0.107/hr × 3 × 24 = $7.7/日
  EKS Control Plane: $0.10/hr × 24 = $2.4/日
  合計:約$10.1/日 ≒ 約¥1,515/日

K8s(EKS)の追加コスト:Control Plane代($72/月)が必ずかかる
小規模では ECS の方がコスト効率が良いことが多い