

รู้จักกับ AWS Fargate และการ Deploy Docker Container อย่างมืออาชีพ
ในยุคที่การพัฒนาแอปพลิเคชันแบบ Microservices และ Containerization กลายเป็นมาตรฐานใหม่ของวงการ DevOps นักพัฒนาต่างมองหาโซลูชันที่ช่วยลดภาระการจัดการ Infrastructure โดยเฉพาะอย่างยิ่งการจัดการ Kubernetes Cluster ที่มีความซับซ้อน AWS Fargate คือคำตอบที่ AWS สร้างขึ้นมาเพื่อให้เราสามารถ Run Container ได้โดยไม่ต้องจัดการ Server หรือ Cluster เลย
AWS Fargate เป็น Compute Engine สำหรับ Container ที่ทำงานบน Amazon ECS (Elastic Container Service) และ Amazon EKS (Elastic Kubernetes Service) โดยในบทความนี้เราจะเจาะลึกถึงวิธีการ Deploy Docker Container ด้วย AWS Fargate อย่างละเอียด พร้อมเทคนิคและ Best Practices ที่ใช้จริงในโปรดักชั่น
ทำไมต้องเลือก AWS Fargate แทน EC2 หรือ EKS?
ก่อนที่เราจะลงมือ Deploy เราควรเข้าใจก่อนว่า Fargate แตกต่างจากตัวเลือกอื่นๆ อย่างไร ตารางเปรียบเทียบด้านล่างจะช่วยให้คุณตัดสินใจได้ง่ายขึ้น
เปรียบเทียบ AWS Fargate กับ Amazon ECS on EC2 และ EKS
| คุณสมบัติ | AWS Fargate (ECS) | ECS on EC2 | Amazon EKS (Kubernetes) |
|---|---|---|---|
| การจัดการ Infrastructure | AWS จัดการให้ทั้งหมด | ต้องจัดการ EC2 Cluster เอง | ต้องจัดการ Control Plane และ Worker Node |
| ความยืดหยุ่นในการปรับขนาด | ปรับอัตโนมัติ (Serverless) | ต้องตั้ง Auto Scaling Group | ต้องตั้ง Cluster Autoscaler |
| ต้นทุน | จ่ายตาม vCPU/GB RAM ที่ใช้จริง | จ่ายตาม EC2 Instance (อาจถูกกว่าถ้าใช้เต็ม) | จ่ายค่า Control Plane + Worker Node |
| การปรับแต่ง OS/Network | จำกัด (ไม่สามารถ SSH เข้าไปได้) | ควบคุมได้เต็มที่ | ควบคุมได้เต็มที่ |
| ความเร็วในการ Deploy | เร็ว (ไม่ต้อง Provision Server) | ปานกลาง (ต้องรอ Instance พร้อม) | ช้ากว่า (ต้องรอ Pod Scheduling) |
จากตารางจะเห็นว่า Fargate เหมาะสำหรับทีมที่ต้องการลดภาระการจัดการ Infrastructure ลงให้มากที่สุด โดยเฉพาะทีมขนาดเล็กถึงกลางที่ไม่มีทีม DevOps เฉพาะทาง
การเตรียมความพร้อมก่อน Deploy Docker Container ด้วย AWS Fargate
ก่อนที่เราจะเริ่ม Deploy จริง มีสิ่งที่ต้องเตรียมหลายอย่าง ตั้งแต่ Docker Image, AWS CLI, ไปจนถึง IAM Role และ Network Configuration
1. สร้าง Docker Image และ Push ไปยัง Amazon ECR
Amazon Elastic Container Registry (ECR) คือ Private Registry สำหรับเก็บ Docker Image ของคุณ ขั้นตอนแรกคือการสร้าง Dockerfile และ Build Image
# Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
จากนั้นเราจะ Build และ Push Image ไปยัง ECR ด้วยคำสั่งดังนี้
# Login to AWS ECR
aws ecr get-login-password --region ap-southeast-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.ap-southeast-1.amazonaws.com
# Build Docker Image
docker build -t my-api-app .
# Tag Image
docker tag my-api-app:latest 123456789012.dkr.ecr.ap-southeast-1.amazonaws.com/my-api-app:latest
# Push Image
docker push 123456789012.dkr.ecr.ap-southeast-1.amazonaws.com/my-api-app:latest
2. สร้าง ECS Cluster แบบ Fargate
ECS Cluster คือ Logical Group ของ Container Instance ในที่นี้เราจะใช้ Fargate Launch Type
# สร้าง ECS Cluster ด้วย AWS CLI
aws ecs create-cluster \
--cluster-name my-fargate-cluster \
--capacity-providers FARGATE FARGATE_SPOT \
--default-capacity-provider-strategy capacityProvider=FARGATE,weight=1
3. สร้าง Task Definition
Task Definition เป็นเหมือน Blueprint ที่กำหนดว่า Container จะทำงานอย่างไร ต้องใช้ CPU เท่าไหร่, RAM เท่าไหร่, และใช้ Image ไหน
ด้านล่างเป็นตัวอย่าง Task Definition JSON สำหรับ Fargate
{
"family": "my-api-task",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789012:role/my-api-task-role",
"containerDefinitions": [
{
"name": "my-api-container",
"image": "123456789012.dkr.ecr.ap-southeast-1.amazonaws.com/my-api-app:latest",
"portMappings": [
{
"containerPort": 3000,
"protocol": "tcp"
}
],
"environment": [
{ "name": "NODE_ENV", "value": "production" },
{ "name": "DB_HOST", "value": "mydb.cluster-xxxxx.ap-southeast-1.rds.amazonaws.com" }
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/my-api-task",
"awslogs-region": "ap-southeast-1",
"awslogs-stream-prefix": "ecs"
}
}
}
]
}
จากนั้น Register Task Definition ด้วยคำสั่ง
aws ecs register-task-definition --cli-input-json file://task-definition.json
การ Deploy Service บน AWS Fargate
หลังจากที่เรามี Task Definition พร้อมแล้ว ขั้นตอนต่อไปคือการสร้าง Service ที่จะจัดการ Running Task ให้คงที่ตามจำนวนที่เราต้องการ
สร้าง ECS Service
ECS Service จะช่วยให้ Container ของเราทำงานตลอดเวลา หาก Task ใดตายลง Service จะสร้าง Task ใหม่ขึ้นมาแทนที่โดยอัตโนมัติ
aws ecs create-service \
--cluster my-fargate-cluster \
--service-name my-api-service \
--task-definition my-api-task:1 \
--desired-count 2 \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[subnet-xxxxx,subnet-yyyyy],securityGroups=[sg-xxxxx],assignPublicIp=ENABLED}" \
--load-balancers "targetGroupArn=arn:aws:elasticloadbalancing:ap-southeast-1:123456789012:targetgroup/my-api-tg/xxxxx,containerName=my-api-container,containerPort=3000"
การตั้งค่า Load Balancer และ Auto Scaling
เพื่อให้แอปพลิเคชันของเราสามารถรองรับ Traffic ที่เพิ่มขึ้น เราควรตั้งค่า Application Load Balancer (ALB) ร่วมกับ Auto Scaling
| พารามิเตอร์ | ค่าที่แนะนำ | คำอธิบาย |
|---|---|---|
| Minimum Tasks | 2 | เพื่อความ High Availability |
| Maximum Tasks | 10 | จำกัดค่าใช้จ่ายสูงสุด |
| Scaling Metric | CPU Utilization > 70% | ขยายเมื่อ CPU ใกล้เต็ม |
| Cooldown Period | 300 วินาที | ป้องกันการ Scale up-down บ่อยเกินไป |
คำสั่งสำหรับตั้งค่า Auto Scaling
aws application-autoscaling register-scalable-target \
--service-namespace ecs \
--resource-id service/my-fargate-cluster/my-api-service \
--scalable-dimension ecs:service:DesiredCount \
--min-capacity 2 \
--max-capacity 10
aws application-autoscaling put-scaling-policy \
--service-namespace ecs \
--resource-id service/my-fargate-cluster/my-api-service \
--scalable-dimension ecs:service:DesiredCount \
--policy-name cpu-scaling-policy \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration file://scaling-policy.json
Best Practices สำหรับการ Deploy Docker Container บน Fargate
จากการทำงานจริงกับลูกค้าหลายราย เรามีคำแนะนำที่เป็นประโยชน์ดังนี้
1. การจัดการ Environment Variables และ Secrets
- ใช้ AWS Secrets Manager หรือ Parameter Store สำหรับเก็บ Credential ที่ Sensitive เช่น Database Password, API Key
- หลีกเลี่ยงการ Hardcode ค่าใน Dockerfile หรือ Task Definition โดยตรง
- ใช้ ECS Task Role เพื่อให้ Container สามารถดึง Secrets ได้อย่างปลอดภัย
2. การ Optimize Docker Image
- ใช้ Multi-stage Build เพื่อลดขนาด Image
- เลือก Base Image ที่เล็กที่สุด เช่น Alpine Linux (node:18-alpine, python:3.11-slim)
- ลบ Cache และ File ที่ไม่จำเป็นออกจาก Image
- ใช้ .dockerignore เพื่อไม่ให้ไฟล์ที่ไม่จำเป็นถูก Copy เข้า Image
3. การตั้งค่า Monitoring และ Logging
- เปิดใช้งาน CloudWatch Container Insights เพื่อดู Metrics แบบ Real-time
- ตั้งค่า Log Group สำหรับแต่ละ Service เพื่อแยก Log ให้เป็นระเบียบ
- ใช้ Structured Logging (JSON format) เพื่อให้ CloudWatch Logs Insights ค้นหาง่าย
- ตั้ง Alarm สำหรับ CPU > 80%, Memory > 80%, และ Task Count ที่ผิดปกติ
4. การจัดการ Network และ Security
- วาง Fargate Task ใน Private Subnet เท่านั้น ใช้ NAT Gateway หรือ VPC Endpoint สำหรับออก Internet
- ใช้ Security Group แบบ Least Privilege: เปิดเฉพาะ Port ที่จำเป็น
- เปิดใช้งาน VPC Flow Logs เพื่อตรวจสอบ Network Traffic
- ใช้ Service Discovery (AWS Cloud Map) สำหรับการสื่อสารระหว่าง Microservices
กรณีศึกษาจากโลกจริง (Real-World Use Cases)
กรณีที่ 1: SaaS Platform สำหรับจัดการร้านอาหาร
บริษัทสตาร์ทอัพแห่งหนึ่งในกรุงเทพฯ ใช้ Fargate ในการ Deploy Backend API ที่พัฒนาด้วย Node.js และ PostgreSQL โดยมีรายละเอียดดังนี้
- ปัญหาเดิม: ใช้ EC2 แบบ Manual Scaling ทำให้เสียเวลาจัดการ Server และมี Downtime บ่อย
- วิธีแก้: ย้ายมาใช้ Fargate + ALB + Auto Scaling โดยตั้งค่า Minimum 2 Tasks และ Maximum 20 Tasks
- ผลลัพธ์: ลดเวลา Deploy จาก 30 นาทีเหลือ 5 นาที, ลดค่าใช้จ่าย 40% เพราะไม่ต้องจ่ายค่า Server ตอนไม่มี Traffic, และเพิ่ม Uptime เป็น 99.95%
กรณีที่ 2: E-commerce Platform ช่วง Flash Sale
แพลตฟอร์มขายของออนไลน์ขนาดกลางที่ต้องรับมือกับ Traffic ที่พุ่งสูงในช่วง Flash Sale
- ปัญหาเดิม: ใช้ EKS แต่ทีม DevOps มีขนาดเล็ก ทำให้จัดการ Cluster ได้ไม่ทัน
- วิธีแก้: เปลี่ยนมาใช้ Fargate Spot Instance สำหรับงานประมวลผลที่ไม่สำคัญ (Background Jobs) และ Fargate On-Demand สำหรับ API หลัก
- ผลลัพธ์: ประหยัดค่าใช้จ่ายเพิ่มอีก 60% สำหรับงาน Background, Scale ได้ภายใน 2 นาทีเมื่อ Traffic เพิ่มขึ้น 300%
การ Troubleshoot ปัญหาที่พบบ่อยบน AWS Fargate
1. Container Crash Loop (Restart บ่อย)
สาเหตุส่วนใหญ่เกิดจาก Resource Limit ที่ไม่เพียงพอ หรือ Application Error
- ตรวจสอบ CloudWatch Logs ว่ามี Error อะไรใน Container
- เพิ่ม Memory และ CPU ใน Task Definition
- ตรวจสอบ Health Check Path ใน ALB ว่าถูกต้องหรือไม่
2. Network Connectivity Issues
Fargate Task ไม่สามารถเชื่อมต่อกับ Database หรือ Service อื่นได้
- ตรวจสอบ Security Group ของ Fargate Task และ Target Service
- ตรวจสอบว่า Subnet มี Route Table ที่ถูกต้อง (NAT Gateway หรือ VPC Endpoint)
- ใช้ VPC Reachability Analyzer เพื่อทดสอบ Network Path
3. Permission Denied (IAM Role Issue)
Container ไม่สามารถเข้าถึง S3, DynamoDB, หรือ Secrets Manager
- ตรวจสอบ Task Role (ไม่ใช่ Execution Role) ว่ามี Policy ที่ถูกต้อง
- ใช้ IAM Policy Simulator เพื่อทดสอบ Permission
- ตรวจสอบ Trust Relationship ของ Role
การ Deploy แบบ Blue/Green และ Canary Release
เพื่อให้การ Deploy ใหม่ไม่กระทบกับผู้ใช้ เราสามารถใช้ CodeDeploy ร่วมกับ ECS เพื่อทำ Blue/Green Deployment
ขั้นตอนการตั้งค่า Blue/Green Deployment
- สร้าง Application Load Balancer ที่มี 2 Target Group (Blue และ Green)
- สร้าง CodeDeploy Application และ Deployment Group
- สร้าง AppSpec file ที่ระบุ Task Definition และ Container Name
- เมื่อ Deploy ใหม่ CodeDeploy จะสร้าง Task ใหม่ (Green) รอให้ Health Check ผ่านก่อนค่อยสลับ Traffic
ตัวอย่าง AppSpec file สำหรับ CodeDeploy
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: "arn:aws:ecs:ap-southeast-1:123456789012:task-definition/my-api-task:5"
LoadBalancerInfo:
ContainerName: "my-api-container"
ContainerPort: 3000
Hooks:
- BeforeAllowTraffic: "arn:aws:lambda:ap-southeast-1:123456789012:function:pre-traffic-check"
- AfterAllowTraffic: "arn:aws:lambda:ap-southeast-1:123456789012:function:post-traffic-check"
การจัดการ Cost Optimization สำหรับ Fargate
หนึ่งในข้อกังวลหลักของการใช้ Fargate คือค่าใช้จ่ายที่อาจสูงกว่าการใช้ EC2 หากไม่มีการจัดการที่ดี
เทคนิคการประหยัดค่าใช้จ่าย
- ใช้ Fargate Spot: ประหยัดได้ถึง 70% สำหรับงานที่ทนต่อการถูก Terminate ได้ (Background Jobs, Batch Processing)
- เลือกขนาด CPU/Memory ให้เหมาะสม: อย่าใช้ Over-provision เช่น ถ้า Container ใช้ CPU แค่ 0.25 vCPU ก็ไม่จำเป็นต้องจอง 1 vCPU
- ใช้ Scheduled Scaling: ลด Task Count ในช่วงเวลาที่ Traffic น้อย เช่น กลางคืนหรือวันหยุด
- ตั้งค่า Idle Timeout: สำหรับ API ที่ไม่มีการใช้งาน ให้ตั้งค่า Keep-Alive ให้สั้นลง
- ใช้ Savings Plans: หากมีการใช้งานต่อเนื่องมากกว่า 1 ปี ควรซื้อ Compute Savings Plans เพื่อลดค่าใช้จ่าย
การ Integrate Fargate กับ AWS Services อื่นๆ
1. Fargate + Amazon RDS (Aurora Serverless)
สำหรับ Database ที่ต้องการ Scaling อัตโนมัติเช่นกัน การใช้ Aurora Serverless v2 ร่วมกับ Fargate จะช่วยให้ทั้ง Compute และ Database เป็น Serverless อย่างสมบูรณ์
2. Fargate + AWS Step Functions
ใช้สำหรับ Orchestrate Workflow ที่ซับซ้อน เช่น การประมวลผลไฟล์, การส่ง Email, หรือการเรียก API หลายขั้นตอน
3. Fargate + Amazon EventBridge
ใช้สำหรับ Schedule Task เช่น การ Run ETL ทุกเที่ยงคืน หรือการประมวลผลข้อมูลตาม Event
4. Fargate + AWS Lambda
ใช้ Lambda สำหรับงานที่ใช้เวลาสั้น (< 15 นาที) และ Fargate สำหรับงานที่ใช้เวลานานหรือต้องการ Environment ที่กำหนดเอง
เครื่องมือและ CI/CD Pipeline ที่แนะนำ
เพื่อให้การ Deploy เป็นระบบและทำซ้ำได้ เราควรตั้งค่า CI/CD Pipeline ด้วยเครื่องมือเหล่านี้
| เครื่องมือ | การใช้งาน | ข้อดี |
|---|---|---|
| AWS CodePipeline + CodeBuild | Build Docker Image, Push to ECR, Deploy to ECS | Native Integration, ไม่ต้องจัดการ Server |
| GitHub Actions | CI/CD จาก GitHub Repository | ฟรีสำหรับ Public Repo, Community Templates เยอะ |
| GitLab CI/CD | Deploy จาก GitLab | มี Container Registry ในตัว |
| Jenkins | สำหรับองค์กรที่มี Jenkins อยู่แล้ว | Customizable สูง แต่ต้องจัดการเอง |
ตัวอย่าง Pipeline แบบง่ายด้วย AWS CodeBuild
version: 0.2
phases:
pre_build:
commands:
- echo Logging in to Amazon ECR...
- aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
- REPOSITORY_URI=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/my-api-app
- COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
- IMAGE_TAG=${COMMIT_HASH:=latest}
build:
commands:
- echo Build started on `date`
- docker build -t $REPOSITORY_URI:latest .
- docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
post_build:
commands:
- echo Build completed on `date`
- docker push $REPOSITORY_URI:latest
- docker push $REPOSITORY_URI:$IMAGE_TAG
- echo Writing imagedefinitions.json...
- printf '[{"name":"my-api-container","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
files: imagedefinitions.json
สรุปข้อควรระวังและข้อจำกัดของ AWS Fargate
แม้ว่า Fargate จะมีข้อดีมากมาย แต่ก็มีข้อจำกัดที่ควรรู้ก่อนตัดสินใจ
- ไม่สามารถ SSH เข้า Container ทำให้ Debug ยากกว่า EC2
- Network Performance อาจไม่เสถียรเท่า EC2 ในบางกรณี (โดยเฉพาะงานที่ต้องการ Network Throughput สูง)
- Storage จำกัด Fargate รองรับ Ephemeral Storage สูงสุด 200 GB ต่อ Task (เพิ่มได้ถึง 200 GB ด้วย EFS)
- ราคาต่อหน่วยสูงกว่า EC2 หากใช้งานเต็ม 24/7 โดยไม่มีการหยุด
- GPU Support ยังไม่รองรับ (ต้องใช้ EC2 หรือ EKS แทน)
Summary
AWS Fargate เป็นตัวเลือกที่ยอดเยี่ยมสำหรับทีมที่ต้องการลดความซับซ้อนในการจัดการ Container Infrastructure โดยเฉพาะอย่างยิ่งสำหรับองค์กรที่ไม่มีทีม DevOps ขนาดใหญ่ หรือต้องการความรวดเร็วในการ Deploy และ Scale แอปพลิเคชัน
ในบทความนี้เราได้เรียนรู้ตั้งแต่การสร้าง Docker Image, การตั้งค่า ECS Cluster, การสร้าง Task Definition, การ Deploy Service พร้อม Load Balancer, การตั้งค่า Auto Scaling, การทำ Blue/Green Deployment, ไปจนถึง Best Practices และการจัดการ Cost Optimization
สิ่งสำคัญที่สุดคือการเลือกใช้ Fargate ให้เหมาะสมกับลักษณะงานของคุณ หากคุณมี Workload ที่ต้องการ Performance สูงสุดหรือต้องการควบคุม OS ระดับ Kernel การใช้ EC2 หรือ EKS อาจเป็นทางเลือกที่ดีกว่า แต่สำหรับ 80% ของ Use Cases ทั่วไป Fargate คือคำตอบที่ลงตัวระหว่างความสะดวกและประสิทธิภาพ
สำหรับผู้ที่สนใจเริ่มต้นใช้งานจริง แนะนำให้ลองสร้าง Environment แบบ Sandbox ก่อนเพื่อทดสอบการทำงาน และค่อยๆ Migrate Workload ที่ไม่สำคัญมาไว้บน Fargate ก่อน แล้วจึงขยายไปยัง Production Service หลักเมื่อมั่นใจแล้ว