Article

Amazon ECS FargateとEKSの使い分け戦略

高田晃太郎
Amazon ECS FargateとEKSの使い分け戦略

CNCFの年次調査(2023)ではKubernetesの本番利用が約8割、開発・検証まで含めると9割超がコンテナを活用していると報告されています¹。Datadogの観測でもワークロードの多数がオーケストレーター配下で稼働しており²、AWSにおける主要な選択肢はAmazon ECS FargateとAmazon EKSの2つです³。公開されている価格表やドキュメントを整理すると、意思決定を複雑にしているのは技術差そのものよりも、運用責務の分岐とコストの支払い先にあります⁴⁵。言い換えると、ECS Fargateは“運用をAWSに強く寄せる選択”、EKSは“自由度と移植性(クラウド中立性)に投資する選択”です³。この記事では、アーキテクチャ、コスト、運用の3軸で両者を解剖し、最後に現場でそのまま使える実装レシピを提示します。ECSとEKSの比較・使い分けを実務の判断材料に落とし込むのが目的です。

ECS FargateとEKSの設計思想を正しく掴む

ECS Fargateはコントロールプレーン(制御層)とデータプレーン(実行層)の多くをAWSがフルマネージドで引き受け、利用者はタスク定義とサービス、ALB/NLB、セキュリティグループ、IAMに集中します³。ネットワークはawsvpcモードで各タスクにENI(Elastic Network Interface)が割り当てられ、カーネルやノードのライフサイクル管理から解放される一方、DaemonSet(全ノード常駐の仕組み)やカスタムCNI(Container Network Interface、Kubernetesのネットワーク拡張)のような“ノード前提の拡張”は使えません(EKS on FargateでもDaemonSetはサポート外と明記)⁶。瞬間的なスパイク対応は得意ですが、細やかなスケジューリングやPod/タスク間通信の高度な制御は、設計上の工夫で補うことになります。キーワードで言えば「フルマネージド」「サーバーレス実行」「最小運用責務」が軸です。

EKSはKubernetes APIを提供し、スケジューラやCNI、Ingress、サービスメッシュ(サービス間通信の制御・暗号化)、ジョブ実行、CRD(Custom Resource Definition)による拡張などのクラウド中立なエコシステムをフルに享受できます³。マネージドノードグループによりOSパッチの多くは自動化できますが、Kubernetesのバージョンアップ、アドオン選定、ネットワーク設計はチームの責務です。EKS on Fargateという折衷案もありますが⁶、一般的なWeb/バックエンドではマネージドノードグループの方が運用と費用のバランスを取りやすい場面が多い、という見方が一般的です。こちらのキーワードは「拡張性」「移植性」「ポリシー統治」です。

Fargateのタスク定義は数十行で完結します。以下は最小限のWebアプリの定義例です。ヘルスチェックとログを押さえるとデプロイの再現性が安定します。

{
  "family": "webapp",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "512",
  "memory": "1024",
  "executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
  "taskRoleArn": "arn:aws:iam::123456789012:role/ecsAppRole",
  "containerDefinitions": [
    {
      "name": "app",
      "image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/webapp:latest",
      "portMappings": [{ "containerPort": 3000, "protocol": "tcp" }],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/webapp",
          "awslogs-region": "ap-northeast-1",
          "awslogs-stream-prefix": "app"
        }
      },
      "environment": [{"name": "NODE_ENV", "value": "production"}],
      "healthCheck": {
        "retries": 3,
        "command": ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"],
        "timeout": 5,
        "interval": 30,
        "startPeriod": 10
      }
    }
  ]
}

EKSではDeployment/Serviceで同等の構成を表現します。プローブとリソース制限を必ず入れ、HPA(Horizontal Pod Autoscaler)の前提を整えます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
spec:
  replicas: 3
  selector:
    matchLabels: { app: webapp }
  template:
    metadata:
      labels: { app: webapp }
    spec:
      serviceAccountName: webapp-sa
      containers:
        - name: app
          image: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/webapp:latest
          ports:
            - containerPort: 3000
          resources:
            requests: { cpu: "250m", memory: "256Mi" }
            limits:   { cpu: "500m", memory: "512Mi" }
          readinessProbe:
            httpGet: { path: /health, port: 3000 }
            periodSeconds: 10
          livenessProbe:
            httpGet: { path: /health, port: 3000 }
            initialDelaySeconds: 20
---
apiVersion: v1
kind: Service
metadata:
  name: webapp
spec:
  type: ClusterIP
  selector: { app: webapp }
  ports:
    - port: 80
      targetPort: 3000

コストとスケール:何にいくら払うのか

価格はリージョンと時期で変動しますが、EKSはコントロールプレーンに時間課金(多くのリージョンで0.10 USD/時間)があり⁴、古いKubernetesバージョンの延長サポート(Extended Support)を選ぶ場合は追加で0.60 USD/時間が発生します⁹。ワーカーノードはEC2の料金で、ストレージやデータ転送料も別途です。対してFargateはvCPU時間とメモリGB時間の従量課金で、秒単位(最低1分)で切り上げられます⁵。例えばap-northeast-1の参考価格帯では、vCPU時間とメモリGB時間の合計がそのまま月額に連動します。バーストが少ない常時稼働ワークロードでは、適切にサイズされたスポット混在のEKSが有利になるケースは珍しくありません³。逆に、突発スケールや短命タスクが多いシステム、または小規模でクラスタ固定費を正当化しにくい場合はFargateが合理的です³。検索観点の要点をまとめると、「ECS Fargate 料金モデル」「EKS 料金 比較」「スポットインスタンス 活用」が判断キーワードになります。

スケールの目安も判断材料です。ノードが温まっているEKSでは新規Podの起動は数秒〜十数秒程度で、ノードスケールアウトが絡むと分オーダーに伸びることがあります。Fargateはタスクの初期配置に数十秒程度を要することが多く、スパイク時の先行ウォームアップを設計に入れると安定します。どちらも起動時間のボトルネックはコンテナイメージのサイズとレジストリ到達性に依存するため、イメージのスリム化とリージョン内ECRの利用は明確に効きます。

インフラをコードで管理(IaC)する場合の初期コストも確認しておきます。EKSはクラスタ作成、ノードグループ、CNI/Ingress/監視の選定までがスキャフォールドで、その分のセットアップ時間がかかります。eksctlを使うと最初の山は越えやすく、次のような設定ファイルでマネージドノードグループを用意できます。

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: team-a-eks
  region: ap-northeast-1
managedNodeGroups:
  - name: ng-app
    instanceType: m6i.large
    desiredCapacity: 3
    minSize: 2
    maxSize: 6
    volumeSize: 50
    ssh:
      allow: false
cloudWatch:
  clusterLogging:
    enableTypes: ["api", "audit", "authenticator"]

ECS Fargate側はTerraformでクラスター、サービス、ALBまで一気に定義できます。以下は最小構成の例です。実環境ではターゲットグループのヘルスチェック、タスクの容量プロバイダ、Auto Scalingポリシーを合わせて定義します。

resource "aws_ecs_cluster" "this" {
  name = "team-a-ecs"
}

resource "aws_ecs_task_definition" "web" {
  family                   = "webapp"
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"
  cpu                      = "512"
  memory                   = "1024"
  execution_role_arn       = aws_iam_role.exec.arn
  task_role_arn            = aws_iam_role.app.arn
  container_definitions    = file("taskdef.json")
}

resource "aws_ecs_service" "web" {
  name            = "webapp"
  cluster         = aws_ecs_cluster.this.id
  task_definition = aws_ecs_task_definition.web.arn
  desired_count   = 3
  launch_type     = "FARGATE"
  network_configuration {
    subnets         = var.private_subnets
    assign_public_ip = false
    security_groups = [aws_security_group.web.id]
  }
  load_balancer {
    target_group_arn = aws_lb_target_group.web.arn
    container_name   = "app"
    container_port   = 3000
  }
}

TCOを数式で直感化すると分かりやすくなります。例えば平均500m vCPUと512MiBで24時間×3タスクを1か月運用するケースでは、FargateはvCPU 0.5×時間単価×720時間×3とメモリ0.5GB×時間単価×720時間×3の和になります⁵。EKSはEC2台数×時間単価×720時間に対してクラスタ費用が上乗せされ⁴、ノードのリソース利用率をどこまで高められるかが勝負所です。スポットを50%程度混在できるならEKSの優位は一気に広がる可能性がありますが、運用の複雑さとSLOを天秤にかける必要があります³。

運用とセキュリティ:責務とガバナンスの分岐点

運用の“主語”がどちらにあるかを明確にすると判断が速まります。FargateはOS/カーネル、コンテナランタイム、ノードセキュリティパッチをAWSが担い、利用者はアプリ層のCI/CD、ログ/メトリクス設計、ネットワーク境界の定義に集中できます³。EKSはクラスタとアドオンのライフサイクル、ネットワークプラグイン、Ingress/Service Mesh、マルチテナンシーの設計が責務に入ります³。代わりにPod SecurityやOPA/Gatekeeper、Kyvernoなどのポリシーで強固に縛る自由度を得られます(OPA/KyvernoはいずれもKubernetesのポリシーエンジン)。

IAMの扱いは両者で大きくは変わりません。ECSはIAM Roles for Tasksでタスク単位に権限を付与し⁷、EKSはIRSA(IAM Roles for Service Accounts)でServiceAccountに権限を結びます⁸。以下はIRSAの最小例です。OIDCプロバイダ連携を済ませた上で、アプリのPodだけがS3へアクセスできるように絞り込みます。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: webapp-sa
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/eks-webapp-s3
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: webapp-role
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: webapp-rb
subjects:
  - kind: ServiceAccount
    name: webapp-sa
roleRef:
  kind: Role
  name: webapp-role
  apiGroup: rbac.authorization.k8s.io

可観測性(Observability)はアーキテクチャに合わせて最短距離を選びます。FargateはCloudWatch LogsとEmbedded Metric Formatでメトリクスを直接吐く構成がシンプルです。EKSはOpenTelemetry CollectorやFluent BitのDaemonSetでログ・メトリクス・トレースを集約し、外部SaaSに転送するのが定石です。ALB Ingress Controller(現: AWS Load Balancer Controller)とPrometheus/Grafanaの組み合わせはデファクトで、ServiceとIngressのラベル設計を最初に揃えておくとダッシュボード自動生成が効きます。ネットワークの最小権限化も重要です。Fargateはセキュリティグループをタスクに直付けでき、EKSはNetworkPolicyとSecurity Groups for Podsの併用で同等の粒度を実現します。

同じWebアプリを両者で動かす実装レシピ

ここではNode.jsベースのWebアプリを想定し、両者で再現性のある配備を行うための最低限の実装を並べます。CI/CDはGitHub Actionsを例にし、OIDCでの一時クレデンシャル付与を前提にします。まずEKS側ではIngressを置き、ALB経由で外部公開します。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: webapp
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: webapp
                port:
                  number: 80

GitHub ActionsでECRへプッシュし、ECSサービスをローリング更新するワークフローの例です。EKSへの適用はkubectl/helmジョブに置き換えれば同様の流れになります。

name: deploy-webapp
on:
  push:
    branches: ["main"]
permissions:
  id-token: write
  contents: read
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/gha-deploy
          aws-region: ap-northeast-1
      - uses: aws-actions/amazon-ecr-login@v2
      - run: |
          IMAGE_TAG=${GITHUB_SHA::7}
          aws ecr create-repository --repository-name webapp || true
          docker build -t ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.ap-northeast-1.amazonaws.com/webapp:$IMAGE_TAG .
          docker push ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.ap-northeast-1.amazonaws.com/webapp:$IMAGE_TAG
      - run: |
          TASK_DEF=$(jq '.containerDefinitions[0].image = "'${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.ap-northeast-1.amazonaws.com/webapp:'${GITHUB_SHA::7}'"' taskdef.json)
          echo "$TASK_DEF" > taskdef.out.json
          aws ecs register-task-definition \
            --cli-input-json file://taskdef.out.json
          REV=$(aws ecs describe-task-definition --task-definition webapp --query 'taskDefinition.revision' --output text)
          aws ecs update-service --cluster team-a-ecs --service webapp --task-definition webapp:$REV

レイテンシの安定化は小さな工夫の積み重ねです。EKSではPodDisruptionBudgetとReadinessゲートでローリング時の容量確保を明示し、Fargateでは最小健全タスク数をDesiredの60〜80%に設定しつつヘルスチェックの猶予を十分に取ります。どちらでも共通して、p95/p99を監視しながらHPA/タスク数を調整するのが効果的です。以下はPodDisruptionBudgetの一例です。

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: webapp-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: webapp

最後に、よく問われる“いつFargateをやめてEKSへ移るべきか”を実装観点で整理します。まず、クラスタ固定費が相対的に重くなくなり、スポット混在やノード最適化で月間インフラ費を2〜3割程度削減できる可能性がシミュレーションで見えてきたときが一つのシグナルです。次に、サイドカーやDaemonSet前提の可観測性・セキュリティ基盤に踏み込みたい、もしくは複数言語・複数チームのマルチテナント運用でプラットフォーム機能を内製したいとき。これらが重なると、EKSに投資する価値が蓄積しやすくなります。逆に、プロダクトマーケットフィット探索フェーズやチームが小規模でSRE体制が薄い間は、Fargateで“運用を買う”という戦略が適合します。検索軸でいえば「ECS vs EKS 選び方」「マルチテナンシー」「観測性/セキュリティ要件」が判断の分岐点です。

まとめ:意思決定の軸を3つに揃える

最短で結論にたどり着くには、運用責務、コスト構造、拡張性の3軸を同じ粒度で比べることが有効です。運用責務の面では、Amazon ECS Fargateは“ハードニングされた標準”をそのまま使えるためリソースをプロダクトに集中できます。Amazon EKSはガバナンスと拡張性をプラットフォームとして自社に取り込み、長期の移植性と最適化余地を手にします。コストでは、短命・変動ワークロードと小規模構成はFargateに分がありますが、稼働率とスポットの工夫が効く中〜大規模ではEKSが優位になりやすい構造です。拡張性は、CRDやサービスメッシュ、ポリシーによる制御が必要ならEKS、機能が足りているならFargateと割り切るのが現実的です。

今日の要件に最も合うほうを選び、半年後の要件を軽く見積もる。それがコンテナ基盤の意思決定で外さないコツです。今まさに迷っているなら、プロダクションの1系統を両者で小さく並走させ、p95レイテンシと運用時間、月次コストの3指標だけを比較してみてください。数字がチームにとっての正解を教えてくれます。次のアクションとして、コンテナイメージを最小化し、ここで示したデプロイ定義をコピーしてプローブとログを整備するところから始めてみましょう。検索の観点では「ECS Fargate 使い分け」「EKS コスト 比較」「Kubernetes 運用 ベストプラクティス」を手掛かりに、要件に近い事例を追加で集めるのがおすすめです。

参考文献

  1. CNCF. CNCF Annual Survey 2023. https://www.cncf.io/reports/cncf-annual-survey-2023/
  2. Datadog. The state of container usage 2021. https://www.datadoghq.com/container-report-2021/
  3. AWS Containers Blog. Amazon ECS vs. Amazon EKS: Making sense of AWS container services. https://aws.amazon.com/blogs/containers/amazon-ecs-vs-amazon-eks-making-sense-of-aws-container-services/
  4. AWS. Amazon EKS pricing. https://aws.amazon.com/eks/pricing/
  5. AWS. AWS Fargate pricing. https://aws.amazon.com/fargate/pricing/
  6. AWS. AWS Fargate on Amazon EKS(EKS Fargate)ドキュメント. https://docs.aws.amazon.com/eks/latest/userguide/fargate.html
  7. AWS. IAM roles for Amazon ECS tasks. https://docs.aws.amazon.com/AmazonECS/latest/developerguide/security-ecs-iam-role-overview.html
  8. AWS. IAM roles for service accounts (IRSA). https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html
  9. AWS. Amazon EKS pricing – Kubernetes Version Extended Support. https://aws.amazon.com/ar/eks/pricing/#:~:text=Kubernetes%20Version%20Support%20Tier%20,60%20per%20cluster%20per%20hour