CloudFormation部署ECS栈时Service创建卡住超时无报错排查
ECS Service创建超时根本原因
该问题与容器任务无法正常启动、资源配置存在多处逻辑/语法错误直接相关。CloudFormation仅校验资源创建API是否返回成功,不会跟踪ECS服务后续的任务调度、负载均衡健康检查等异步流程,因此不会直接抛出明确错误。从提供的模板可定位到以下确定性问题:
- ECS容器实例未正常注册到集群
你使用的是基于自定义快照创建的AMI,并非AWS官方ECS优化版AMI,默认未预装ECS容器代理(ecs-agent)服务,即便UserData写入了集群配置,代理未运行的情况下实例永远不会注册到ECS集群,Service无法找到可调度任务的计算资源。同时UserData中配置的集群名为cluster-staging-internal,和模板定义的集群名cluster-staging-internal-poc后缀不匹配,即便代理正常运行也会接入错误集群。 - 任务调度规则与资源规模不匹配
模板仅创建1台位于单可用区的EC2实例,但Service配置了跨可用区、跨实例的双spread放置策略,且期望任务数为2,现有资源规模完全不满足放置策略要求。同时t3.micro实例仅具备1vCPU、1G内存,扣除系统与ECS代理占用的资源后,剩余容量无法支撑单任务1vCPU、512M内存的配置要求。此外任务定义硬编码了主机端口87,EC2启动模式下主机端口为独占资源,即便资源充足也仅能运行1个任务,第二个任务会因端口占用启动失败。 - 负载均衡配置存在多处冲突
模板中定义的HTTP监听器硬编码绑定了栈外的已有ALB,和栈内新创建的ALB无关联;新创建的ALB配置了无效的安全组IDsg-0,无法正常转发流量;目标组健康检查端口为80,和容器映射的87端口不匹配,即便任务启动成功也无法通过健康检查,ECS会持续判定部署未完成。同时监听器默认动作是将81端口的所有请求重定向到HTTPS 443,又配置优先级1的规则将所有路径转发到目标组,规则逻辑存在冲突。 - 模板语法与时序依赖错误
Service资源定义了两个DependsOn块,YAML语法中同键名会被后者覆盖,实际仅保留了对栈内ALB的依赖,未等待EC2实例注册、监听器规则、目标组等资源就绪就开始创建Service,时序逻辑错误。 - IAM配置存在隐患
EC2实例绑定的实例配置文件未明确关联具备ECS服务权限、ECR镜像拉取权限的角色,即便代理正常运行也可能因权限不足无法拉取镜像、上报状态。
排查与修复思路
按以下优先级操作即可快速定位问题:
- 校验容器实例注册状态
进入ECS控制台对应集群的「容器实例」页面,确认创建的EC2实例是否成功注册。若未注册:- 替换为AWS官方ECS优化版AMI,无需手动安装ecs-agent服务
- 修正UserData中的集群名,和模板定义的集群名完全一致
- 为EC2实例配置关联
AmazonEC2ContainerServiceforEC2Role托管策略的实例角色,确保具备ECS通信、ECR拉镜像权限
- 修正任务调度配置
- 要么将期望任务数调整为1,要么新增至少1台跨可用区的EC2实例,满足spread放置策略要求
- 调小单任务的CPU、内存配额,或升级EC2实例规格,确保单实例剩余资源可支撑任务运行
- 删除PortMappings中的硬编码HostPort配置,留空让Docker自动分配临时端口,支持单实例运行多任务
- 修正负载均衡配置
- 将HTTP监听器的ALB ARN改为引用栈内创建的ALB资源,删除硬编码的栈外ALB ARN
- 替换ALB安全组为环境内有效的安全组,放通ALB到EC2实例容器端口的入站流量
- 调整目标组健康检查配置,确保端口、路径与容器实际服务匹配,可正常返回200状态码
- 调整监听器规则逻辑,不要在配置了全站HTTPS重定向的监听器上挂载转发规则,可单独创建HTTPS监听器配置业务转发规则
- 修正模板逻辑
- 合并Service的两个DependsOn块为单个列表,将EC2实例、目标组、监听器规则都加入依赖列表,确保资源创建时序正确
- 开启Service部署断路器,将
DeploymentCircuitBreaker.Enable设为true,任务启动失败时会直接回滚,避免长时间等待超时
- 查看服务事件日志
待容器实例正常注册到集群后,进入ECS控制台对应Service的「事件」页面,可看到任务调度失败的明确原因,包括资源不足、端口冲突、镜像拉取失败、健康检查失败等具体信息,比CloudFormation事件日志的定位精度高10倍。
内容的提问来源于stack exchange,提问作者Dolevt85
相关产品推荐
相关产品推荐

