Claude Code × AWS ECS/Fargate 完整指南 | 自动化容器部署
使用Claude Code自动化AWS ECS/Fargate部署。从任务定义、服务配置到Blue/Green部署和CDK基础设施构建——基于Masa的实际工作经验。
“我想在AWS上运行容器,但ECS配置太复杂了”——这是许多工程师最初遇到的障碍。任务定义、服务、集群、负载均衡器、自动扩展……配置项太多,根本不知道从哪里开始。
我在工作中使用ECS/Fargate构建无服务器容器环境,自从开始用Claude Code描述架构配置,就能一键生成从任务定义到CDK代码的全套内容,部署工作变得轻松了许多。本文将详细讲解其实践步骤。
3分钟理解ECS/Fargate基础
集群(Cluster): ECS容器运行的"容器箱"
任务定义(Task Definition):容器配置规格书(镜像、CPU、内存、环境变量)
服务(Service): 设置启动多少个任务(含自动扩展)
Fargate: 无需服务器管理的容器执行引擎
与EC2不同,Fargate无需进行服务器配置和补丁维护,您可以专注于容器配置本身。
第1步:自动生成任务定义
claude -p "
按以下条件生成ECS任务定义JSON:
- 应用:Node.js API(端口3000)
- CPU:512(0.5 vCPU)
- 内存:1024 MB
- 环境变量:DATABASE_URL(从Secrets Manager获取)、NODE_ENV=production
- 日志:CloudWatch Logs(日志组 /ecs/myapp)
- 健康检查:/health端点,30秒间隔
- 容器镜像:123456789.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:latest
- 执行角色:ecsTaskExecutionRole
- 任务角色:myapp-task-role(DynamoDB和S3访问权限)
"
生成的任务定义:
{
"family": "myapp-task",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024",
"executionRoleArn": "arn:aws:iam::123456789:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789:role/myapp-task-role",
"containerDefinitions": [
{
"name": "myapp",
"image": "123456789.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:latest",
"portMappings": [{ "containerPort": 3000, "protocol": "tcp" }],
"environment": [{ "name": "NODE_ENV", "value": "production" }],
"secrets": [
{
"name": "DATABASE_URL",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789:secret:prod/database-url"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/myapp",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
}
},
"healthCheck": {
"command": ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"],
"interval": 30,
"timeout": 5,
"retries": 3,
"startPeriod": 60
}
}
]
}
第2步:用CDK构建ECS/Fargate环境
不仅是任务定义,还要用CDK一次性生成集群、服务和ALB。
claude -p "
在lib/ecs-stack.ts中用CDK TypeScript实现以下ECS/Fargate环境:
- VPC:导入现有VPC(从环境变量获取vpcId)
- ECS集群:仅Fargate
- 任务定义:与上面生成的规格相同
- ALB:HTTPS(从环境变量获取ACM证书ARN),HTTP进行301重定向
- 服务:最少2台、最多10台的自动扩展
- CPU使用率70%时扩展
- 目标追踪扩展
- Blue/Green部署支持(CodeDeploy集成)
- 在CloudWatch仪表盘中显示服务运行状态
"
// lib/ecs-stack.ts
import * as cdk from "aws-cdk-lib";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as ecs from "aws-cdk-lib/aws-ecs";
import * as ecsp from "aws-cdk-lib/aws-ecs-patterns";
import * as acm from "aws-cdk-lib/aws-certificatemanager";
export class EcsStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// 导入现有VPC
const vpc = ec2.Vpc.fromLookup(this, "Vpc", {
vpcId: process.env.VPC_ID!,
});
// ECS集群
const cluster = new ecs.Cluster(this, "Cluster", {
vpc,
clusterName: "myapp-cluster",
containerInsights: true, // 启用CloudWatch Container Insights
});
// ACM证书
const certificate = acm.Certificate.fromCertificateArn(
this, "Certificate",
process.env.CERTIFICATE_ARN!
);
// 任务定义
const taskDef = new ecs.FargateTaskDefinition(this, "TaskDef", {
cpu: 512,
memoryLimitMiB: 1024,
});
const container = taskDef.addContainer("app", {
image: ecs.ContainerImage.fromEcrRepository(
ecr.Repository.fromRepositoryName(this, "Repo", "myapp")
),
environment: { NODE_ENV: "production" },
logging: ecs.LogDrivers.awsLogs({ streamPrefix: "ecs" }),
healthCheck: {
command: ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"],
interval: cdk.Duration.seconds(30),
timeout: cdk.Duration.seconds(5),
retries: 3,
startPeriod: cdk.Duration.seconds(60),
},
});
container.addPortMappings({ containerPort: 3000 });
// ALB + Fargate服务(使用模式简洁表达)
const service = new ecsp.ApplicationLoadBalancedFargateService(
this, "Service", {
cluster,
taskDefinition: taskDef,
desiredCount: 2,
certificate,
redirectHTTP: true,
publicLoadBalancer: true,
}
);
// 自动扩展配置
const scaling = service.service.autoScaleTaskCount({
minCapacity: 2,
maxCapacity: 10,
});
scaling.scaleOnCpuUtilization("CpuScaling", {
targetUtilizationPercent: 70,
scaleInCooldown: cdk.Duration.seconds(60),
scaleOutCooldown: cdk.Duration.seconds(60),
});
// 输出
new cdk.CfnOutput(this, "LoadBalancerDns", {
value: service.loadBalancer.loadBalancerDnsName,
});
}
}
第3步:用GitHub Actions构建CI/CD流水线
claude -p "
用GitHub Actions创建以下CI/CD流水线:
1. 以向main分支的push为触发器
2. 构建Docker镜像并推送到ECR
3. 将ECS任务定义中的image标签更新为新的SHA
4. 将新任务定义部署到ECS服务
5. 部署完成后向Slack发送通知
环境:ap-northeast-1,ECR仓库名:myapp
"
name: Deploy to ECS
on:
push:
branches: [main]
env:
AWS_REGION: ap-northeast-1
ECR_REPOSITORY: myapp
ECS_CLUSTER: myapp-cluster
ECS_SERVICE: myapp-service
CONTAINER_NAME: app
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build, tag, and push image to ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
- name: Download task definition
run: |
aws ecs describe-task-definition --task-definition myapp-task \
--query taskDefinition > task-definition.json
- name: Update ECS task definition with new image
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: task-definition.json
container-name: ${{ env.CONTAINER_NAME }}
image: ${{ steps.build-image.outputs.image }}
- name: Deploy to ECS
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: ${{ env.ECS_SERVICE }}
cluster: ${{ env.ECS_CLUSTER }}
wait-for-service-stability: true
- name: Notify Slack on success
if: success()
uses: slackapi/slack-github-action@v1
with:
webhook: ${{ secrets.SLACK_WEBHOOK }}
payload: |
{"text": "✅ Deployed to ECS: ${{ github.sha }}"}
第4步:配置Blue/Green部署
claude -p "
生成用于ECS服务配置Blue/Green部署(CodeDeploy)的
CDK代码和AppSpec文件。
回滚条件:部署后5分钟内CloudWatch告警触发时自动回滚
"
# appspec.yaml(用于CodeDeploy)
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: <TASK_DEFINITION>
LoadBalancerInfo:
ContainerName: app
ContainerPort: 3000
PlatformVersion: LATEST
Hooks:
- BeforeAllowTraffic: "arn:aws:lambda:ap-northeast-1:123456789:function:health-check"
- AfterAllowTraffic: "arn:aws:lambda:ap-northeast-1:123456789:function:smoke-test"
五大常见陷阱
1. 忘记健康检查的 startPeriod
Fargate容器启动后立即进行健康检查,但如果应用启动较慢,则会立即变为UNHEALTHY状态。请设置 startPeriod: 60(秒)为应用的启动留出时间。
2. 混淆任务角色和执行角色
executionRole(ecsTaskExecutionRole):启动容器所需的权限
→ 从ECR拉取镜像,向CloudWatch Logs写入日志
taskRole(myapp-task-role):应用使用的权限
→ 访问DynamoDB、S3、SQS等
很容易把权限添加到错误的角色上。
3. awsvpc网络模式下的安全组配置
Fargate必须使用 awsvpc 网络模式。如果忘记将容器的安全组限制为仅允许来自ALB的流量,容器就会直接暴露在公网上。
4. 从Secrets Manager获取值需要执行角色权限
通过 secrets 获取Secrets Manager的值时,executionRole 需要 secretsmanager:GetSecretValue 权限。缺少这一权限经常导致容器无法启动。
5. 部署时的 desired_count: 0 问题
自动扩展最小值为0的服务可能会在深夜停止所有容器,导致早上启动缓慢。生产环境中请将最小值设置为至少2台。
总结
| 任务 | Claude Code的贡献 |
|---|---|
| 任务定义生成 | 只需描述需求,即可完成JSON |
| CDK实现 | 集群、服务、ALB、自动扩展一次性生成 |
| CI/CD配置 | 生成GitHub Actions工作流 |
| Blue/Green部署 | 自动生成AppSpec和CodeDeploy配置 |
| 故障排查 | 从错误日志中找出原因和修复方法 |
ECS的配置项虽多,但只需告诉Claude Code”我需要这样的配置”,就能一次性获得符合最佳实践的完整配置。推荐从CDK开始,这是最简单的方式。
相关文章
参考资料
免费 PDF:5 分钟看懂 Claude Code 速查表
只需留下邮箱,我们就会立即把这份 A4 一页速查表 PDF 发送给你。
我们会严格保护你的个人信息,绝不发送垃圾邮件。
本文作者
Masa
深度使用 Claude Code 的工程师。运营 claudecode-lab.com——一个涵盖 10 种语言、超过 2,000 页内容的科技媒体。
相关文章
Claude Code × Amazon Bedrock 完整指南 | 在AWS上将Claude投入生产环境
使用Claude Code充分利用Amazon Bedrock的完整指南。从IAM认证、流式传输、Lambda集成、RAG实现到成本优化——基于Masa的实际生产实施经验。
Claude Code × AWS CodePipeline/CodeBuild 完全指南 | 自动构建CI/CD流水线
使用Claude Code通过AWS CodePipeline和CodeBuild自动构建CI/CD。包含流水线设计、buildspec.yml生成、测试自动化、CDK基础设施定义的实战代码解说。
Claude Code × AWS CloudWatch 完整指南 | 日志分析·告警设置·仪表盘自动构建
用 Claude Code 提升 AWS CloudWatch 效率。包含日志模式分析、自动告警配置、指标仪表盘构建及故障排查的实战代码解析。