mcpField
E
ecs

ecs

github.com/itsmostafa云与 DevOps1.2k149 次安装2 天前更新
代码仓库

关于 ecs

面向在 AWS 上部署和运维容器工作负载团队的 Amazon Elastic Container Service(ECS)参考技能。介绍 Fargate 与 EC2 上的集群、任务和服务管理,并提供扩缩容、部署、安全及故障排查的命令行示例。

主要功能

  1. 01管理集群、任务定义、任务和服务
  2. 02在 Fargate 或 EC2 上运行工作负载
  3. 03配置服务扩缩容与部署
  4. 04在适用工作负载中使用 Fargate Spot
  5. 05排查任务、容器和部署问题

适用场景

  1. 01部署带负载均衡器的 Web 服务
  2. 02运行独立批处理或队列处理任务
  3. 03根据工作负载指标扩缩 ECS 服务
  4. 04调查启动失败或部署停滞

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/itsmostafa/aws-agent-skills --skill ecs

安装后在 Claude Code 中输入/ecs确认已加载。

附带文件task-definitions.md

详细介绍

AWS ECS

Amazon Elastic Container Service(ECS)是一项全托管的容器编排服务。可在 AWS Fargate(无服务器)或 EC2 实例上运行容器。

目录

核心概念

集群

任务或服务的逻辑分组。可包含 Fargate 任务、EC2 实例,或两者兼有。

任务定义

应用的蓝图。用于定义容器、资源、网络和 IAM 角色。

任务

任务定义的运行实例。可独立运行,也可作为服务的一部分运行。

服务

维持任务的期望数量,并负责部署、负载均衡和自动扩缩。

启动类型
类型说明用例
Fargate无服务器,按任务付费大多数工作负载
EC2自行管理的实例GPU、Windows、特定需求

常见模式

创建 Fargate 集群

AWS CLI:

# Create cluster
aws ecs create-cluster --cluster-name my-cluster

# With capacity providers
aws ecs create-cluster \
  --cluster-name my-cluster \
  --capacity-providers FARGATE FARGATE_SPOT \
  --default-capacity-provider-strategy \
    capacityProvider=FARGATE,weight=1 \
    capacityProvider=FARGATE_SPOT,weight=1
注册任务定义
cat > task-definition.json << 'EOF'
{
  "family": "web-app",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512",
  "executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
  "taskRoleArn": "arn:aws:iam::123456789012:role/ecsTaskRole",
  "containerDefinitions": [
    {
      "name": "web",
      "image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latest",
      "portMappings": [
        {
          "containerPort": 8080,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {"name": "NODE_ENV", "value": "production"}
      ],
      "secrets": [
        {
          "name": "DB_PASSWORD",
          "valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:db-password"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/web-app",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs",
          "mode": "non-blocking",
          "max-buffer-size": "25m"
        }
      },
      "healthCheck": {
        "command": ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"],
        "interval": 30,
        "timeout": 5,
        "retries": 3,
        "startPeriod": 60
      }
    }
  ]
}
EOF

aws ecs register-task-definition --cli-input-json file://task-definition.json
创建带负载均衡器的服务
aws ecs create-service \
  --cluster my-cluster \
  --service-name web-service \
  --task-definition web-app:1 \
  --desired-count 2 \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={
    subnets=[subnet-12345678,subnet-87654321],
    securityGroups=[sg-12345678],
    assignPublicIp=DISABLED
  }" \
  --load-balancers "targetGroupArn=arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/web-tg/1234567890123456,containerName=web,containerPort=8080" \
  --health-check-grace-period-seconds 60 \
  --deployment-configuration "deploymentCircuitBreaker={enable=true,rollback=true}"
运行独立任务
aws ecs run-task \
  --cluster my-cluster \
  --task-definition my-batch-job:1 \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={
    subnets=[subnet-12345678],
    securityGroups=[sg-12345678],
    assignPublicIp=ENABLED
  }"
更新服务(部署新映像)
# Register new task definition with updated image
aws ecs register-task-definition --cli-input-json file://task-definition.json

# Update service to use new version
aws ecs update-service \
  --cluster my-cluster \
  --service web-service \
  --task-definition web-app:2 \
  --force-new-deployment
使用基于 SQS 的扩缩容配置 Fargate Spot

对批处理/队列工作负载使用 FARGATE_SPOT,可将成本降低约 70%。务必设置回退到常规 FARGATE 的机制。

# Create service with Spot + fallback
aws ecs create-service \
  --cluster batch-cluster \
  --service-name queue-processor \
  --task-definition my-processor:1 \
  --desired-count 0 \
  --capacity-provider-strategy \
    capacityProvider=FARGATE_SPOT,weight=4,base=0 \
    capacityProvider=FARGATE,weight=1,base=1 \
  --network-configuration "awsvpcConfiguration={
    subnets=[subnet-12345678],
    securityGroups=[sg-12345678],
    assignPublicIp=DISABLED
  }"

# Register scalable target (scale to zero when queue empty)
aws application-autoscaling register-scalable-target \
  --service-namespace ecs \
  --resource-id service/batch-cluster/queue-processor \
  --scalable-dimension ecs:service:DesiredCount \
  --min-capacity 0 \
  --max-capacity 20

# Scale-out alarm: messages > 100
aws cloudwatch put-metric-alarm \
  --alarm-name queue-scale-out \
  --metric-name ApproximateNumberOfMessagesVisible \
  --namespace AWS/SQS \
  --dimensions Name=QueueName,Value=my-queue \
  --statistic Average \
  --period 60 \
  --evaluation-periods 1 \
  --threshold 100 \
  --comparison-operator GreaterThanThreshold \
  --alarm-actions <scale-out-policy-arn>

# Scale-in alarm: queue empty for 3 periods (conservative to avoid flapping)
aws cloudwatch put-metric-alarm \
  --alarm-name queue-scale-in \
  --metric-name ApproximateNumberOfMessagesVisible \
  --namespace AWS/SQS \
  --dimensions Name=QueueName,Value=my-queue \
  --statistic Average \
  --period 60 \
  --evaluation-periods 3 \
  --threshold 0 \
  --comparison-operator LessThanOrEqualToThreshold \
  --alarm-actions <scale-in-policy-arn>

**每个任务的积压量(AWS 推荐):**直接使用队列深度会导致过度扩缩容。改用指标数学计算 queue depth / RunningTaskCount 并进行目标跟踪;Application Auto Scaling 会管理告警。集群需要启用 Container Insights(ECS/ContainerInsights 中的 RunningTaskCount)。当运行任务数为 0 时,除数没有数据,因此无法从 0 扩容;如果 min-capacity 为 0,请保留上方的告警模式。

# TargetValue = acceptable latency / avg processing time per message (e.g. 10s / 0.1s = 100)
aws application-autoscaling put-scaling-policy \
  --service-namespace ecs \
  --resource-id service/batch-cluster/queue-processor \
  --scalable-dimension ecs:service:DesiredCount \
  --policy-name sqs-backlog-per-task \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration '{
    "TargetValue": 100,
    "CustomizedMetricSpecification": {
      "Metrics": [
        {"Id": "m1", "ReturnData": false, "MetricStat": {"Stat": "Sum",
          "Metric": {"Namespace": "AWS/SQS", "MetricName": "ApproximateNumberOfMessagesVisible",
            "Dimensions": [{"Name": "QueueName", "Value": "my-queue"}]}}},
        {"Id": "m2", "ReturnData": false, "MetricStat": {"Stat": "Average",
          "Metric": {"Namespace": "ECS/ContainerInsights", "MetricName": "RunningTaskCount",
            "Dimensions": [{"Name": "ClusterName", "Value": "batch-cluster"},
                           {"Name": "ServiceName", "Value": "queue-processor"}]}}},
        {"Id": "e1", "Expression": "m1 / m2", "ReturnData": true}
      ]
    }
  }'

**防止缩容时中断进行中的工作:**工作进程在处理期间将 ProtectionEnabled=true(使用容器 Agent 端点 $ECS_AGENT_URI/task-protection/v1/state,或运行 aws ecs update-task-protection --cluster <c> --tasks <id> --protection-enabled --expires-in-minutes 60),处理完成后将其清除。任务角色需要 ecs:GetTaskProtection 和 ecs:UpdateTaskProtection 权限。仅适用于服务任务。

**Fargate Spot 中断处理:**Spot 任务会在终止前 2 分钟收到 SIGTERM。在应用中捕获该信号,以便优雅关闭。对于 SQS 消费者,调用 ChangeMessageVisibility 处理正在进行的消息,使其返回队列,而不是超时。

自动扩缩容
# Register scalable target
aws application-autoscaling register-scalable-target \
  --service-namespace ecs \
  --resource-id service/my-cluster/web-service \
  --scalable-dimension ecs:service:DesiredCount \
  --min-capacity 2 \
  --max-capacity 10

# Target tracking policy
aws application-autoscaling put-scaling-policy \
  --service-namespace ecs \
  --resource-id service/my-cluster/web-service \
  --scalable-dimension ecs:service:DesiredCount \
  --policy-name cpu-target-tracking \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration '{
    "TargetValue": 70.0,
    "PredefinedMetricSpecification": {
      "PredefinedMetricType": "ECSServiceAverageCPUUtilization"
    },
    "ScaleOutCooldown": 60,
    "ScaleInCooldown": 120
  }'

**使用 20 秒指标加快扩缩容:**启用高分辨率服务指标,然后将 ECSServiceAverageCPUUtilizationHighResolution 或 ECSServiceAverageMemoryUtilizationHighResolution 用作 PredefinedMetricType。对于现有服务,更改 --monitoring 会触发部署;请在部署完成后再创建高分辨率策略。部署控制器为 CODE_DEPLOY/EXTERNAL 时不支持此功能。将产生额外的 CloudWatch 费用。

aws ecs update-service \
  --cluster my-cluster \
  --service web-service \
  --monitoring "metricConfigurations=[{metricNames=[CPUUtilization,MemoryUtilization],resolutionSeconds=20}]"

CLI 参考

集群管理
命令说明
aws ecs create-cluster创建集群
aws ecs describe-clusters获取集群详情
aws ecs list-clusters列出集群
aws ecs delete-cluster删除集群
任务定义
命令说明
aws ecs register-task-definition创建任务定义
aws ecs describe-task-definition获取任务定义
aws ecs list-task-definitions列出任务定义
aws ecs deregister-task-definition注销版本
服务
命令说明
aws ecs create-service创建服务
aws ecs update-service更新服务
aws ecs describe-services获取服务详情
aws ecs delete-service删除服务
任务
命令描述
aws ecs run-task运行独立任务
aws ecs stop-task停止正在运行的任务
aws ecs describe-tasks获取任务详情
aws ecs list-tasks列出任务

最佳实践

安全
  • 使用任务角色访问 AWS API(而非访问密钥)
  • 使用执行角色访问 ECR/Secrets
  • 将机密存储在 Secrets Manager 或 Parameter Store 中
  • 使用带 NAT 网关的私有子网
  • 启用 CloudTrail 进行 API 审计
  • 通过 IAM 限制任务规格——ecs:task-cpu / ecs:task-memory 条件键适用于 RunTask 和 StartTask,也适用于 RegisterTaskDefinition、CreateService、UpdateService
性能
  • 合理设置 CPU/内存规格——监控并调整
  • 对容错工作负载使用 Fargate Spot(节省 70%)
  • 启用容器洞察进行监控
  • 使用服务发现进行内部通信
可靠性
  • 跨多个 AZ 部署
  • 正确配置运行状况检查
  • 设置适当的注销延迟
  • 在部署中使用断路器
aws ecs update-service \
  --cluster my-cluster \
  --service web-service \
  --deployment-configuration '{
    "deploymentCircuitBreaker": {
      "enable": true,
      "rollback": true,
      "resetOnHealthyTask": true,
      "thresholdConfiguration": {"type": "BOUNDED_PERCENT", "value": 50}
    }
  }'
  • **调整断路器阈值:**默认值 BOUNDED_PERCENT/50 = 期望任务数的 50%,失败次数限制在 3 到 200 次之间。UNBOUNDED_PERCENT 取消此限制(适用于大型服务);COUNT 将 value 用作固定失败次数(例如,为快速开发回滚设置较低值)。resetOnHealthyTask: false 会累计计算失败次数,而非只计算连续失败次数。
  • 提前成功条件(仅适用于滚动部署):当新修订版中达到 healthyPercent 比例的期望任务运行状况正常时,即标记部署成功;其余任务通过常规服务扩缩启动。healthyPercent 必须介于 minimumHealthyPercent 和 100 之间;副本服务默认 minimumHealthyPercent 为 100,因此使用较低的 healthyPercent 时需显式设置该值。提前完成后,断路器和警报回滚将不再适用。sourceServiceRevisionCleanup:BLOCKING 会在成功前排空旧任务;DEFERRED 会先声明成功,再异步排空旧任务(适用于长连接、缩容保护)。
aws ecs update-service \
  --cluster my-cluster \
  --service web-service \
  --deployment-configuration '{
    "strategy": "ROLLING",
    "minimumHealthyPercent": 75,
    "earlySuccessCriteria": {"enable": true, "healthyPercent": 90, "sourceServiceRevisionCleanup": "BLOCKING"}
  }'
  • Service Connect 区域感知路由默认启用(优先选择同一 AZ 的端点,降低跨 AZ 成本);现有服务需要重新部署一次才能启用该功能。
  • EC2 启动类型:迁移到 Amazon Linux 2023 ECS 优化型 AMI。AL2 ECS 优化型 AMI 将于 2026 年 6 月 30 日结束生命周期(不再发布新 AMI,Agent 版本将固定)。
  • **Fargate:**平台版本 1.3.0 已于 2026 年 6 月 15 日弃用。请使用 LATEST 或 1.4.0。
成本优化
  • 对批处理工作负载使用 Fargate Spot
  • 合理设置任务资源规格
  • 不需要时缩容至零
  • 对混合使用 Fargate/Spot 的场景使用容量提供程序

故障排除

任务无法启动

检查:

# View stopped tasks
aws ecs describe-tasks \
  --cluster my-cluster \
  --tasks $(aws ecs list-tasks --cluster my-cluster --desired-status STOPPED --query 'taskArns[0]' --output text)

常见原因:

  • 找不到镜像(ECR 权限)
  • 访问机密遭拒
  • 网络配置(子网、安全组)
  • 超出资源限制
容器不断重启

调试:

# Check CloudWatch logs
aws logs get-log-events \
  --log-group-name /ecs/web-app \
  --log-stream-name "ecs/web/abc123"

# Check task details
aws ecs describe-tasks \
  --cluster my-cluster \
  --tasks task-arn \
  --query 'tasks[0].containers[0].{reason:reason,exitCode:exitCode}'

原因:

  • 运行状况检查失败
  • 应用程序崩溃
  • 内存不足
使用 ECS Exec 实时调试

无需 SSH,即可直接连接到正在运行的容器。需要在服务中设置 enableExecuteCommand: true,并在容器镜像中安装 SSM Agent(大多数基础镜像都包含该 Agent)。

# Enable on existing service
aws ecs update-service \
  --cluster my-cluster \
  --service web-service \
  --enable-execute-command

# Get a shell in a running task
TASK_ARN=$(aws ecs list-tasks --cluster my-cluster --service-name web-service \
  --query 'taskArns[0]' --output text)

aws ecs execute-command \
  --cluster my-cluster \
  --task $TASK_ARN \
  --container web \
  --interactive \
  --command "/bin/sh"

**要求:**任务角色必须具有 ssmmessages:CreateControlChannel、ssmmessages:CreateDataChannel、ssmmessages:OpenControlChannel、ssmmessages:OpenDataChannel 权限。

服务部署卡住
# Check deployment status
aws ecs describe-services \
  --cluster my-cluster \
  --services web-service \
  --query 'services[0].deployments'

# Check events
aws ecs describe-services \
  --cluster my-cluster \
  --services web-service \
  --query 'services[0].events[:5]'

原因:

  • 新任务的运行状况检查失败
  • 容量不足
  • 目标组运行状况检查失败
操作日志(部署期间 ECS 执行了哪些操作)

每个集群可选择启用。记录 ECS 在服务部署期间执行的操作(状态转换、回滚、生命周期钩子)以及托管式守护进程的生命周期,并包含时间戳、logLevel INFO/WARN/ERROR 和状态原因。即使停止的任务保留时间超过 1 小时,这些日志仍会保留失败元数据。按 CloudWatch 托管日志计费。

aws logs put-delivery-source \
  --name my-ecs-action-logs \
  --resource-arn arn:aws:ecs:us-east-1:123456789012:cluster/my-cluster \
  --log-type EcsActionLogs

aws logs put-delivery-destination \
  --name my-ecs-logs-destination \
  --output-format json \
  --delivery-destination-configuration '{"destinationResourceArn": "arn:aws:logs:us-east-1:123456789012:log-group:/aws/vendedlogs/ecs/action-logs/my-cluster"}'

aws logs create-delivery \
  --delivery-source-name my-ecs-action-logs \
  --delivery-destination-arn arn:aws:logs:us-east-1:123456789012:delivery-destination:my-ecs-logs-destination

需要: logs:PutDeliverySource、logs:PutDeliveryDestination、logs:CreateDelivery、logs:GetDelivery、ecs:AllowVendedLogDeliveryForResource;日志组资源策略必须允许 delivery.logs.amazonaws.com 执行 logs:CreateLogStream/logs:PutLogEvents。每个服务/守护进程 ARN 对应一个日志流。

将 EC2 主机迁移到 AL2023 后发生 OOM 终止

AL2023 使用 cgroup v2:如果只设置任务级别的 memory,容器将无法读取该限制,因此 JVM 和类似运行时会根据主机内存来确定堆大小。将容器级别的 memory 设置为与任务内存相同,或者在 /etc/ecs/ecs.config 中设置 ECS_PROPAGATE_TASK_MEMORY_LIMIT_CGROUPV2=true(agent 1.104.0+)。在 cgroup v2 上,报告的内存用量还包括页面缓存,因此利用率读数会高于 AL2。

无法从 ECR 拉取映像

检查执行角色是否具有:

{
  "Effect": "Allow",
  "Action": [
    "ecr:GetAuthorizationToken",
    "ecr:BatchCheckLayerAvailability",
    "ecr:GetDownloadUrlForLayer",
    "ecr:BatchGetImage"
  ],
  "Resource": "*"
}

另请检查:

  • ECR 的 VPC 端点(如果使用私有子网)
  • NAT 网关(如果使用私有子网)
  • 安全组是否允许出站 HTTPS

参考资料

评论

支持 Markdown