EC2 / ECS / EKS:你的容器該跑在哪?

你有一個容器化的 App,想丟到 AWS 上跑。打開 Console 發現 EC2、ECS、EKS 三個選項——它們到底差在哪?

先講結論

EC2 是你自己管機器,什麼都能控制,但 OS patch、scaling 都要自己來。ECS 是 AWS 自家的容器編排,學習成本低、跟 AWS 生態整合最好。EKS 是 AWS 託管的 K8s,適合已經有 K8s 經驗或需要多雲的團隊。如果你只是要跑幾個容器、團隊不超過 10 人,ECS + Fargate 是 2026 年的最佳起點。


三種選擇一覽

EC2ECS (Fargate)EKS
你管什麼OS、Runtime、AppAppK8s manifests、App
學習曲線低(就是 VM)中(Task Definition)高(K8s 全家桶)
Scaling自己設 ASG自動(Fargate)HPA + Cluster Autoscaler
成本最低(可用 Spot)中(Fargate 溢價)最高(Control Plane $73/月)
適合誰非容器化 App、特殊 OS 需求大多數容器化 App已有 K8s 團隊、多雲

EC2:老朋友,但要自己扛

EC2 就是虛擬機。幾個重點:

Instance Type 怎麼選?

# 查看可用的 Instance Type(東京 Region)
aws ec2 describe-instance-types \
  --filters "Name=current-generation,Values=true" \
  --query "InstanceTypes[?starts_with(InstanceType,'t3')].[InstanceType,VCpuInfo.DefaultVCpus,MemoryInfo.SizeInMiB]" \
  --output table
場景Instance Type說明
測試/開發t3.micro免費方案,2 vCPU / 1 GB
Web Appt3.medium2 vCPU / 4 GB,夠跑大多數服務
計算密集c6i.xlarge4 vCPU / 8 GB,CPU 優化
記憶體密集r6i.xlarge4 vCPU / 32 GB,DB/Cache 用

PEM 檔案管理

# 建立 Key Pair
aws ec2 create-key-pair --key-name prod-key \
  --query 'KeyMaterial' --output text > prod-key.pem
chmod 400 prod-key.pem
 
# SSH 進去
ssh -i prod-key.pem ec2-user@<PUBLIC_IP>

PEM 弄丟了就只能重建 instance,沒有第二次機會。建議存到密碼管理器(1Password / Bitwarden),別放在桌面。

User Data:開機自動設定

# 啟動 EC2 時自動安裝 Docker
aws ec2 run-instances --image-id ami-xxxxx \
  --instance-type t3.medium \
  --key-name prod-key \
  --subnet-id subnet-private-1a \
  --security-group-ids sg-app \
  --user-data file://init.sh
 
# init.sh 內容
#!/bin/bash
yum update -y
yum install docker -y
systemctl start docker
systemctl enable docker
usermod -aG docker ec2-user

ECS + Fargate:容器化 App 的最佳起點

ECS 是 AWS 自家的容器編排服務。搭配 Fargate,你連 EC2 都不用管——丟 container image 進去就跑。

核心概念

  • Cluster:邏輯群組,裡面跑 Service 和 Task
  • Task Definition:描述你的容器怎麼跑(image、CPU、Memory、port、env)
  • Service:保持 N 個 Task 一直在跑(類似 K8s Deployment)
  • Task:一次性任務(類似 K8s Job)

建立 ECS 服務

# 1. 建立 Cluster
aws ecs create-cluster --cluster-name prod-cluster
 
# 2. 建立 Task Definition
cat > task-def.json << 'EOF'
{
  "family": "web-app",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512",
  "executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
  "containerDefinitions": [
    {
      "name": "app",
      "image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/web-app:1.0.0",
      "portMappings": [
        { "containerPort": 8080, "protocol": "tcp" }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/web-app",
          "awslogs-region": "ap-northeast-1",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "environment": [
        { "name": "NODE_ENV", "value": "production" }
      ]
    }
  ]
}
EOF
 
aws ecs register-task-definition --cli-input-json file://task-def.json
 
# 3. 建立 Service
aws ecs create-service --cluster prod-cluster \
  --service-name web-app \
  --task-definition web-app:1 \
  --desired-count 2 \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=[subnet-private-1a,subnet-private-1c],securityGroups=[sg-app],assignPublicIp=DISABLED}" \
  --load-balancers "targetGroupArn=arn:aws:elasticloadbalancing:...,containerName=app,containerPort=8080"

ECS Auto Scaling

# 註冊 Scalable Target
aws application-autoscaling register-scalable-target \
  --service-namespace ecs \
  --resource-id service/prod-cluster/web-app \
  --scalable-dimension ecs:service:DesiredCount \
  --min-capacity 2 --max-capacity 10
 
# Target Tracking:CPU 70% 就擴
aws application-autoscaling put-scaling-policy \
  --service-namespace ecs \
  --resource-id service/prod-cluster/web-app \
  --scalable-dimension ecs:service:DesiredCount \
  --policy-name cpu-tracking \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration \
    "TargetValue=70.0,PredefinedMetricSpecification={PredefinedMetricType=ECSServiceAverageCPUUtilization}"

EKS:如果你真的需要 K8s

EKS 適合兩種人:已經有 K8s 經驗的團隊,和需要多雲可攜性的架構

EKS 的成本

別忽略 Control Plane 費用:73/月**,這還沒算 Worker Node。

# 建立 EKS Cluster(用 eksctl 比較不痛苦)
eksctl create cluster \
  --name prod-cluster \
  --region ap-northeast-1 \
  --version 1.31 \
  --vpc-private-subnets subnet-private-1a,subnet-private-1c \
  --vpc-public-subnets subnet-public-1a,subnet-public-1c \
  --nodegroup-name workers \
  --node-type t3.medium \
  --nodes 3 \
  --nodes-min 2 \
  --nodes-max 5 \
  --managed

EKS vs 自架 K8s

面向自架 K8sEKS
Control Plane自己維護 etcd/API ServerAWS 託管
升版手動、怕爆eksctl upgrade cluster
IAM 整合沒有IRSA(Pod 層級 IAM)
NetworkingCNI 自己選VPC CNI(Pod 拿 VPC IP)
成本機器費用機器 + $73/月 Control Plane

決策框架

你的 App 容器化了嗎?
├─ 否 → EC2(先容器化再說)
├─ 是 → 團隊有 K8s 經驗嗎?
│  ├─ 否 → ECS + Fargate
│  └─ 是 → 需要多雲嗎?
│     ├─ 否 → ECS(省錢省事)
│     └─ 是 → EKS

我的真心建議:除非你有很強的理由選 EKS(多雲、團隊已熟 K8s),否則 ECS + Fargate 是最省心的選擇。EKS 的 overhead 不只是 $73/月,還有學習成本和維運複雜度。


自架 vs AWS

面向自架(Docker Compose)ECS FargateEKS
部署方式docker-compose upTask Definitionkubectl apply
Scaling手動 / 腳本Application Auto ScalingHPA
服務發現Docker networkCloudMap / ALBK8s Service
LogDocker log driverCloudWatch LogsFluentd/Loki
成本機器費用按 vCPU/Memory 秒計機器 + CP 費

如果你在 Infra 系列讀過 Container Runtime,ECS Task Definition 就是 Docker Compose 的 AWS 版。而 Compose vs K8s 的決策,在 AWS 上變成了 ECS vs EKS。


K8s 映射

ECS 概念K8s 對應
ClusterCluster
Task DefinitionPod spec / Deployment
ServiceDeployment + Service
TaskJob
FargateVirtual Kubelet / Fargate on EKS
Application Auto ScalingHPA (Horizontal Pod Autoscaler)

如果你選了 EKS,那就是完整的 K8s——直接看 K8s Workloads 吧。


系列導覽

上一篇下一篇
NAT Route 53

選 Compute 方案就像選車——不是最貴的最好,是最適合你的路況的最好。