关于 aws-ecs-fargate
用于通过 Fargate 或 EC2 在 Amazon ECS 上部署和运维容器应用的技能,指导 AWS 使用者完成集群配置、发布、扩缩容、日志查看与故障排查。
主要功能
- 01ECS 集群与任务配置
- 02将容器镜像推送到 ECR
- 03配置由 ALB 支持的服务
- 04滚动部署与自动扩缩容
- 05查看 CloudWatch 日志
- 06排查任务与网络问题
适用场景
- 01使用 Fargate 部署容器而无需管理服务器
- 02在负载均衡器后运行微服务
- 03为容器工作负载配置扩缩容
- 04诊断任务失败和健康检查问题
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ bagelhole/ devops-security-agent-skills --skill aws-ecs-fargate安装后在 Claude Code 中输入/aws-ecs-fargate确认已加载。
详细介绍
AWS ECS & Fargate
使用 Amazon ECS 运行容器化应用,可选择 Fargate 无服务器计算或 EC2 启动类型。
适用场景
- 无需管理服务器即可将 Docker 容器部署到 AWS(Fargate)
- 运行具有服务发现和负载均衡功能的微服务
- 为容器化应用设置蓝绿部署或滚动部署
- 配置容器工作负载的自动扩缩
- 从 docker-compose 或 Kubernetes 迁移到 ECS
- 排查任务故障、运行状况检查问题或网络问题
前置条件
- 已安装并配置 AWS CLI v2
- 已安装 Docker,用于构建和推送镜像
- IAM 权限:
ecs:*、ecr:*、elasticloadbalancing:*、logs:*、iam:PassRole - 用于存储容器镜像的 ECR 存储库
- 包含子网和 ALB 的 VPC(参见 aws-vpc)
集群设置
# Create an ECS cluster with Container Insights enabled
aws ecs create-cluster \
--cluster-name production \
--capacity-providers FARGATE FARGATE_SPOT \
--default-capacity-provider-strategy '[
{"capacityProvider": "FARGATE", "weight": 1, "base": 2},
{"capacityProvider": "FARGATE_SPOT", "weight": 3}
]' \
--settings '[{"name": "containerInsights", "value": "enabled"}]'
# List clusters
aws ecs list-clusters
# Describe cluster details
aws ecs describe-clusters --clusters production --include STATISTICS ATTACHMENTS
将镜像推送到 ECR
# Create ECR repository
aws ecr create-repository \
--repository-name myapp \
--image-scanning-configuration scanOnPush=true \
--encryption-configuration encryptionType=KMS
# Authenticate Docker to ECR
aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com
# Build, tag, and push
docker build -t myapp:latest .
docker tag myapp:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp:latest
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp:latest
任务定义
{
"family": "myapp",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789012:role/ecsTaskRole",
"containerDefinitions": [
{
"name": "myapp",
"image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp:latest",
"essential": true,
"portMappings": [
{
"containerPort": 8080,
"protocol": "tcp"
}
],
"environment": [
{"name": "NODE_ENV", "value": "production"},
{"name": "PORT", "value": "8080"}
],
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:myapp/db-password"
},
{
"name": "API_KEY",
"valueFrom": "arn:aws:ssm:us-east-1:123456789012:parameter/myapp/api-key"
}
],
"healthCheck": {
"command": ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"],
"interval": 30,
"timeout": 5,
"retries": 3,
"startPeriod": 60
},
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/myapp",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs",
"awslogs-create-group": "true"
}
},
"ulimits": [
{"name": "nofile", "softLimit": 65536, "hardLimit": 65536}
]
}
]
}
# Register the task definition
aws ecs register-task-definition --cli-input-json file://task-definition.json
# List task definition revisions
aws ecs list-task-definitions --family-prefix myapp
# Deregister an old revision
aws ecs deregister-task-definition --task-definition myapp:1
使用 ALB 创建服务
# Create the CloudWatch log group first
aws logs create-log-group --log-group-name /ecs/myapp
aws logs put-retention-policy --log-group-name /ecs/myapp --retention-in-days 30
# Create ECS service with load balancer
aws ecs create-service \
--cluster production \
--service-name myapp \
--task-definition myapp:2 \
--desired-count 3 \
--launch-type FARGATE \
--platform-version LATEST \
--deployment-configuration '{
"deploymentCircuitBreaker": {"enable": true, "rollback": true},
"maximumPercent": 200,
"minimumHealthyPercent": 100
}' \
--network-configuration '{
"awsvpcConfiguration": {
"subnets": ["subnet-private-a", "subnet-private-b"],
"securityGroups": ["sg-app"],
"assignPublicIp": "DISABLED"
}
}' \
--load-balancers '[{
"targetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/myapp-tg/abc123",
"containerName": "myapp",
"containerPort": 8080
}]' \
--service-registries '[{
"registryArn": "arn:aws:servicediscovery:us-east-1:123456789012:service/srv-abc123"
}]' \
--enable-execute-command \
--propagate-tags SERVICE
部署
# Rolling update - update task definition and force new deployment
aws ecs update-service \
--cluster production \
--service myapp \
--task-definition myapp:3 \
--force-new-deployment
# Watch deployment progress
aws ecs describe-services \
--cluster production \
--services myapp \
--query "services[0].deployments[].{Status:status,Running:runningCount,Desired:desiredCount,TaskDef:taskDefinition}" \
--output table
# Wait for service to stabilize
aws ecs wait services-stable --cluster production --services myapp
# Exec into a running container for debugging
aws ecs execute-command \
--cluster production \
--task arn:aws:ecs:us-east-1:123456789012:task/production/abc123 \
--container myapp \
--interactive \
--command "/bin/sh"
自动扩缩
# Register ECS service as a scalable target
aws application-autoscaling register-scalable-target \
--service-namespace ecs \
--resource-id service/production/myapp \
--scalable-dimension ecs:service:DesiredCount \
--min-capacity 2 \
--max-capacity 20
# Target tracking policy - scale on CPU utilization
aws application-autoscaling put-scaling-policy \
--service-namespace ecs \
--resource-id service/production/myapp \
--scalable-dimension ecs:service:DesiredCount \
--policy-name cpu-target-tracking \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration '{
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ECSServiceAverageCPUUtilization"
},
"TargetValue": 70.0,
"ScaleInCooldown": 300,
"ScaleOutCooldown": 60
}'
# Scale on request count per target (ALB)
aws application-autoscaling put-scaling-policy \
--service-namespace ecs \
--resource-id service/production/myapp \
--scalable-dimension ecs:service:DesiredCount \
--policy-name request-count-tracking \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration '{
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ALBRequestCountPerTarget",
"ResourceLabel": "app/my-alb/abc123/targetgroup/myapp-tg/def456"
},
"TargetValue": 1000.0,
"ScaleInCooldown": 300,
"ScaleOutCooldown": 60
}'
Terraform ECS Fargate 服务
resource "aws_ecs_cluster" "main" {
name = "production"
setting {
name = "containerInsights"
value = "enabled"
}
}
resource "aws_ecs_task_definition" "myapp" {
family = "myapp"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = 512
memory = 1024
execution_role_arn = aws_iam_role.ecs_execution.arn
task_role_arn = aws_iam_role.ecs_task.arn
container_definitions = jsonencode([{
name = "myapp"
image = "${aws_ecr_repository.myapp.repository_url}:latest"
essential = true
portMappings = [{
containerPort = 8080
protocol = "tcp"
}]
logConfiguration = {
logDriver = "awslogs"
options = {
awslogs-group = aws_cloudwatch_log_group.myapp.name
awslogs-region = "us-east-1"
awslogs-stream-prefix = "ecs"
}
}
healthCheck = {
command = ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"]
interval = 30
timeout = 5
retries = 3
startPeriod = 60
}
}])
}
resource "aws_ecs_service" "myapp" {
name = "myapp"
cluster = aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.myapp.arn
desired_count = 3
launch_type = "FARGATE"
deployment_circuit_breaker {
enable = true
rollback = true
}
network_configuration {
subnets = aws_subnet.private[*].id
security_groups = [aws_security_group.app.id]
assign_public_ip = false
}
load_balancer {
target_group_arn = aws_lb_target_group.myapp.arn
container_name = "myapp"
container_port = 8080
}
enable_execute_command = true
propagate_tags = "SERVICE"
}
查看日志
# Tail logs from CloudWatch
aws logs tail /ecs/myapp --follow --since 1h
# Get logs for a specific task
aws logs get-log-events \
--log-group-name /ecs/myapp \
--log-stream-name "ecs/myapp/abc123def456" \
--start-from-head
# Filter logs for errors
aws logs filter-log-events \
--log-group-name /ecs/myapp \
--filter-pattern "ERROR" \
--start-time $(date -d '1 hour ago' +%s000)
故障排查
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 任务卡在 PROVISIONING 状态 | 子网中没有可用容量 | 检查子网可用性和容量提供程序 |
| 任务启动后立即失败 | 容器启动时崩溃 | 检查 CloudWatch 日志;先在本地运行镜像 |
| 运行状况检查失败 | 应用在 startPeriod 内未就绪 | 增大 startPeriod;确认运行状况端点正常 |
| 无法拉取 ECR 镜像 | 执行角色缺少 ECR 权限 | 附加 AmazonECSTaskExecutionRolePolicy |
| 服务的运行任务数一直为 0 | 安全组阻止了 ALB 运行状况检查 | 允许 ALB SG 访问容器端口 |
| Exec 命令失败 | SSM Agent 未初始化 | 确保 enableExecuteCommand 为 true;检查任务角色 |
| Fargate 成本过高 | 对可容忍中断的工作负载未使用 Fargate Spot | 添加 FARGATE_SPOT 容量提供程序 |
| 容器因 OOM 被终止 | 内存限制过低 | 增大任务定义中的 memory;检查是否存在内存泄漏 |
| 部署缓慢 | minimumHealthyPercent 过高 | 将其设置为 50%,以加快滚动更新 |
相关技能
- docker-management - 容器基础知识
- container-registries - ECR 和镜像管理
- aws-vpc - ECS 任务的网络配置
- aws-iam - 任务角色和执行角色
- terraform-aws - 基础设施即代码部署
评论
支持 Markdown