你推送了镜像,创建了服务,但第一批任务始终无法进入 RUNNING。它们带着 ResourceInitializationError 停止:unable to pull secrets or registry auth。镜像没有问题。任务位于私有子网中,没有通往 Amazon ECR 或 Secrets Manager 的路由,所以 Fargate 无法启动它们。
许多 ECS on Fargate 的问题都是这样:容器本身能跑,但它周围的网络、角色或负载均衡器设置不对。本文介绍 Amazon ECS 加 AWS Fargate 上的一个生产 Web 服务,从网络和负载均衡到 IAM、扩缩容、部署以及 ECS 与 EKS 的比较,并附带一张可以直接复制的图。
一张表看懂 ECS 概念
| 概念 | 含义 | 示例中 |
|---|---|---|
| 集群(Cluster) | 服务和任务的逻辑分组 | prod |
| 任务定义(Task definition) | 带版本的蓝图:镜像、CPU、内存、端口、角色、密钥、日志 | orders-api:42 |
| 任务(Task) | 任务定义的一个运行副本;在 Fargate 上拥有独立的内核、内存和网络接口 | 2 到 10 个副本 |
| 服务(Service) | 保持期望的任务数,把任务注册到负载均衡器,执行部署 | orders-api |
| 容量提供程序(Capacity provider) | 任务运行的位置:FARGATE、FARGATE_SPOT、EC2 Auto Scaling 组或 ECS Managed Instances |
FARGATE 和 FARGATE_SPOT |
集群不是网络边界:任务运行在你指定的子网中,并处于各自安全组的保护之下。ECS 不收取编排费用;Fargate 按秒计费每个任务的 vCPU、内存和存储,最少计费一分钟。
网络:每个任务一个 ENI
Fargate 任务始终使用 awsvpc 网络模式:每个任务都有自己的弹性网络接口(ENI)、来自其子网的私有 IP 和自己的安全组(Fargate 任务网络)。这带来三个后果:
- 子网需要空间。 每个任务占用一个 IP,AWS 在每个子网中保留五个。两个 AZ 中的六十个任务意味着每个子网 30 个,而 200% 的滚动部署会短暂需要 60 个。/24(251 个可用)够用;/27(27 个可用)不够。
- 安全组按任务生效。 只向负载均衡器的组开放容器端口,只向任务的组开放数据库的 5432 端口。
- 任务需要一条通往 AWS API 的路径。 在你的代码运行之前,Fargate 会通过任务的 ENI 拉取镜像、获取密钥并开始发送日志。
在私有子网中,这条路径是 NAT 网关或 VPC 终端节点(US East 价格,撰写时为 2026 年 11 月):
| 路径 | 需要创建 | 成本 | 取舍 |
|---|---|---|---|
| NAT 网关 | 每个 AZ 一个,或一个区域级 NAT 网关 | 每个 AZ 每小时 $0.045,外加每 GB $0.045 | 也能访问第三方 API |
| VPC 终端节点 | 接口终端节点 ecr.api、ecr.dkr、logs、secretsmanager,外加 S3 网关终端节点 |
每个终端节点每个 AZ 每小时 $0.01,外加每 GB $0.01;S3 网关免费 | 完全没有通往互联网的路径 |
不要漏掉 S3 网关终端节点:ECR 把镜像层存放在 S3 中(ECR 接口终端节点)。两个 AZ 中的四个接口终端节点,在计入数据费用之前每月约 $58(8 × $0.01 × 730 小时),接近两个 $66 的 NAT 网关。所以在数据费用和隐私方面终端节点胜出,在访问范围方面 NAT 胜出。自 2025 年 11 月起,区域级 NAT 网关可自行跨 AZ,并且不需要公有子网。给任务分配公有 IP 也可行,但每个任务离互联网只差一条安全组规则。AWS VPC 图介绍了路由和 NAT 的放置。
负载均衡器:目标组与健康检查
ALB 需要至少两个 AZ 中的子网,每个子网为 /27 或更大,并有八个空闲地址。由于 awsvpc 任务是 ENI 而不是 EC2 实例,目标组的类型必须是 ip。每个服务使用一个目标组;任务由 ECS 注册和注销。
| 设置 | 默认值 | 建议考虑 |
|---|---|---|
| 健康检查间隔 | 30 秒 | 如果服务在 10 秒内启动,用 5 秒(AWS 的建议) |
| 不健康阈值 | 2 次检查 | 出错的任务大约一分钟后被摘除 |
| 健康阈值 | 5 次检查 | 新目标只需通过一次检查 |
| 注销延迟(deregistration delay) | 300 秒 | 短请求用 30 秒或更少;旧任务最多会排空这么久 |
healthCheckGracePeriodSeconds |
0 | 要覆盖启动时间,否则启动慢的任务会被循环替换 |
自 2025 年 11 月起,ECS Express Mode 可以根据容器镜像创建这套 ALB、HTTPS 和扩缩容配置。负载均衡器图概括地介绍了健康检查和排空。
IAM:执行角色与任务角色
两个角色,两项工作:
- 任务执行角色由 ECS 和 Fargate 代理使用,而不是你的代码:它拉取镜像、写入日志,并读取任务定义中指定的密钥(任务执行角色)。
AmazonECSTaskExecutionRolePolicy涵盖 ECR 和日志;secretsmanager:GetSecretValue需要你自己添加,客户管理的密钥还要加上kms:Decrypt。 - 任务角色是你的代码通过 AWS SDK 使用的角色,比如访问 S3 或 SQS,ECS Exec 也需要它。
密钥以环境变量的形式传入:
"secrets": [{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:us-east-1:111122223333:secret:prod/orders/db-AbCdEf:password::"
}]
ECS 在容器启动时读取该值。轮换后的密钥不会到达正在运行的任务,所以轮换后要重新部署,或者让应用用任务角色自己读取密钥。像上面这样只选一个 JSON 键,需要平台版本 1.4.0,也就是当前的 LATEST。
扩缩容:目标跟踪与 Fargate Spot
对于 Service Auto Scaling,先从 ECSServiceAverageCPUUtilization、ECSServiceAverageMemoryUtilization 或 ALBRequestCountPerTarget 的目标跟踪开始。它扩容快、缩容慢,并在部署期间暂停缩容;有多个策略时,只有全部同意才会缩容。每个 AZ 至少保留一个任务。
Fargate Spot 最多便宜 70%。当 AWS 回收容量时,任务会收到两分钟的警告,形式是停止代码为 SpotInterruption 的 EventBridge 事件和 SIGTERM(Fargate 容量提供程序)。stopTimeout 最大为 120 秒,而且 Fargate 绝不会自行回退到常规容量,所以要保留一个 base:
"capacityProviderStrategy": [
{ "capacityProvider": "FARGATE", "base": 2, "weight": 1 },
{ "capacityProvider": "FARGATE_SPOT", "weight": 1 }
]
前两个任务始终运行在常规 Fargate 上;其余的按一比一分配。Spot 上只有一个任务的服务,会直接停止,直到容量恢复。
部署:滚动、蓝绿、线性与金丝雀
滚动是默认方式:minimumHealthyPercent 为 100、maximumPercent 为 200 时,ECS 会先启动新任务再停止旧任务。请开启带回滚的 deployment circuit breaker;默认情况下,一旦失败的任务达到期望数量的一半(至少 3 个,至多 200 个),它就会判定部署失败。CloudWatch 告警也可以触发同样的回滚。
自 2025 年 7 月起,ECS 无需 CodeDeploy 就能自己执行蓝绿部署,自 2025 年 10 月起还支持线性和金丝雀。它们把新版本启动在第二个目标组之后,切换监听器流量,并把旧任务保留一段 bake time,所以回滚只是一次流量切换。
| 策略 | 流量切换 | 回滚 | 额外容量 |
|---|---|---|---|
| 滚动 | 任务分批替换 | 重新部署 | 最多到 maximumPercent |
| 蓝绿 | 在可选的测试流量之后一次性切换 | 切回 | 2 倍 |
| 线性 | 等量分步,例如每隔几分钟 10% | 切回 | 2 倍 |
| 金丝雀 | 先切一小部分,再切其余 | 切回 | 2 倍 |
Lambda 或暂停钩子可以为每个阶段设置关卡。蓝绿部署不支持对 ALBRequestCountPerTarget 的目标跟踪。部署策略图比较了这些模式。
可观测性
awslogs 驱动需要 awslogs-group、awslogs-region,在 Fargate 上还需要 awslogs-stream-prefix。自 2025 年 6 月 25 日起,它默认使用带 10 MB 缓冲区的 non-blocking 模式:CloudWatch 出现故障不会再卡住你的应用,但缓冲区满了会丢日志行。再加上启用增强可观测性的 Container Insights、用于进入 shell 的 ECS Exec,以及针对任务状态变化的 EventBridge 规则;停止原因(stopped reason)会告诉你任务为什么终止。要采集链路追踪,可在任务中以边车方式运行 OpenTelemetry Collector;它是用 OpenTelemetry 处理日志、指标和链路追踪这条管道中的代理层。
ECS 与 EKS
| Amazon ECS | Amazon EKS | |
|---|---|---|
| 控制平面 | 免费 | 每个集群每小时 $0.10,每月约 $73 |
| API | AWS 任务定义和服务 | Kubernetes、Helm、Operator |
| 计算 | Fargate、EC2、ECS Managed Instances | Fargate、EC2 节点组、EKS Auto Mode |
| 升级 | 控制平面无需升级 | 每个 Kubernetes 版本提供 14 个月标准支持,之后每个集群每小时 $0.60 |
| 内置部署 | 滚动、蓝绿、线性、金丝雀 | 滚动;其他通过 Argo Rollouts 等工具 |
价格来自撰写时(2026 年 11 月)的 EKS 定价页面。需要 Kubernetes 的可移植性或生态时选择 EKS;Kubernetes 架构图展示了那种情形。对于短时、事件驱动的工作,基于 Lambda 的无服务器设计完全不需要常驻运行的服务。
ECS on Fargate 图
图表内容
- VPC
- Public subnet · AZ a
- Public subnet · AZ b
- Private subnet · AZ a
- Private subnet · AZ b
- Application Load Balancer
- orders-api task
- RDS for PostgreSQL
- VPC endpoints
- Users
- Amazon ECR
- Secrets Manager
- CloudWatch Logs
- HTTPS 443
- HTTP 8080
- SQL 5432
- image pull
- secrets at start
- awslogs
这张图的读法如下:
- AZ 是行。 每个 AZ 有一个公有子网和一个私有子网。ALB、RDS 和终端节点位于行与行之间,因为它们都跨两个 AZ:每个公有子网中各有一个 ALB 节点,数据库有一个 Multi-AZ 备用实例。
- 蓝色实线是请求路径:到 ALB 的 HTTPS,到每个 AZ 一个任务的 HTTP 8080,以及 5432 端口上的 SQL。
- 紫色虚线是平台流量:镜像拉取、密钥和日志,由 Fargate 使用任务执行角色,通过 VPC 终端节点发送。
- 只有公有子网会把 0.0.0.0/0 路由到互联网网关。
- Markdown 块列出了服务设置。
把 ECS 图画清楚
- 把任务放进每个 AZ 的子网里。 一个包住一切的“ECS 集群”方框,会隐藏任务运行的位置以及它们能访问什么。
- 每个 AZ 画一个任务,并在旁边标出扩缩容范围。
- 画出通往 ECR、Secrets Manager 和 CloudWatch Logs 的路径。 缺少这条路径是任务无法启动的常见原因。
- 在 ALB 的连线上标注端口和目标类型,并在图例中说明虚线背后使用的角色。
- 省略边车、CI/CD 和 DNS 记录,除非图本身就是讲它们的。
AWS 三层架构模板用 EC2 实现了同样的 VPC 布局。
在 Archboard 中构建
- 用 Google 或 GitHub 登录并创建一个图表。
- 从网络包添加一个 VPC,并在其中放入四个子网节点,每个 AZ 一个公有、一个私有。
- 从云包在公有子网之间添加一个云负载均衡器,并在公有子网中添加文本备注,用于路由和 ALB 节点。
- 从云包在每个私有子网中添加一个计算实例节点,并在实例类型字段中填写任务规格。
- 在私有子网之间添加开启高可用的托管数据库,以及用于 VPC 终端节点的云资源,两者都来自云包。
- 在 VPC 之外,从网络包添加互联网,从 Docker 包添加镜像仓库,从安全包添加密钥保管库,从 DevOps 包添加日志。
- 画出带标签的连线,平台流量用虚线,并从基础包添加一个写有设置的 Markdown 块。
CloudFormation 转图表和 Terraform 转图表工具可以把现有的 stack 代码变成初稿;从 Terraform 画出服务时,先精简初稿,再手动补上请求路径。
这个示例共用 15 个图表节点,在 Free 套餐的限制之内。
常见问题
Fargate 必须使用 awsvpc 网络模式吗?
是的。每个 Fargate 任务都有自己的网络接口和私有 IP 地址,所以它的目标组必须使用 ip 目标类型。
ECS 任务角色和任务执行角色有什么区别? 执行角色让 ECS 启动任务:拉取镜像、获取密钥、发送日志。任务角色是你的应用代码用于自己的 AWS 调用的角色。
私有子网中的 Fargate 任务需要 NAT 网关吗? 访问 AWS 服务时不需要。ECR、CloudWatch Logs 和 Secrets Manager 的接口终端节点,加上 S3 网关终端节点就够了。只有要访问互联网时才需要 NAT。
ECS 支持不用 CodeDeploy 的蓝绿部署吗? 支持。ECS 自 2025 年 7 月起原生支持蓝绿,自 2025 年 10 月起原生支持线性和金丝雀,并带有 bake time、生命周期钩子和基于告警的回滚。
ECS 比 EKS 便宜吗? 就控制平面而言是的:ECS 没有编排费用,而标准支持下的 EKS 集群每小时 $0.10。Fargate 和 EC2 实例的价格在两者下是一样的。