ECS中Sidekiq任务突发Aws::Errors::MissingCredentialsError问题排查求助
排查与解决ECS中Sidekiq的Aws::Errors::MissingCredentialsError问题
核心问题定位
日志里的Failed to open TCP connection to 169.254.170.2:80是关键——ECS任务通过这个本地元数据端点获取IAM角色临时凭证,连接超时说明凭证获取请求被阻塞或拒绝,不一定是限流,但优先从ECS Agent的行为入手排查。
排查ECS Agent限流/异常的具体方法
- 查看ECS Agent日志:
- EC2模式:在容器实例上执行
docker logs ecs-agent,搜索rate limit、credentials、169.254.170.2关键词,找是否有凭证请求被限流的记录。 - Fargate模式:在CloudWatch日志组(通常是
/aws/ecs/container-instance/你的集群名)筛选ECS Agent日志,排查相同关键词。
- EC2模式:在容器实例上执行
- 手动测试凭证获取:在容器内或实例上执行
curl -v http://169.254.170.2/v2/credentials/你的任务角色ARN,看是否超时或报错,验证端点可用性。 - 检查CloudWatch指标:查看ECS服务的
ContainerInstance指标,重点关注AgentConnectionErrors、TaskCredentialsRequests、TaskCredentialsErrors,这些指标能直接反映凭证请求的成功率和错误趋势。 - 排查网络状态:在EC2实例上用
netstat -an | grep 169.254.170.2:80,查看是否有大量TIME_WAIT连接,判断是否存在连接泄漏导致的端口耗尽。
针对性解决措施
1. 减少凭证请求频率(最有效)
- 开启AWS SDK凭证缓存:在Rails项目中修改AWS初始化代码,缓存临时凭证,降低对元数据端点的请求次数:
Aws.config.update({ credentials: Aws::InstanceProfileCredentials.new( http_open_timeout: 5, http_read_timeout: 5, cache_refresh_attempts: 2, cache_ttl: 3600 # 缓存1小时,可根据业务调整 ) }) - 复用AWS客户端实例:不要在Sidekiq任务每次执行时都新建AWS客户端,全局复用实例,避免重复触发凭证获取。
2. 调整ECS Agent限流阈值(EC2模式)
如果日志确认是Agent限流,可修改Agent的ECS_CREDENTIALS_RATE_LIMIT环境变量(默认100次/分钟),适当提高阈值(注意不要超过IAM临时凭证请求的默认限制:每个角色每秒5次)。修改容器实例的ECS Agent启动参数,添加-e ECS_CREDENTIALS_RATE_LIMIT=200后重启Agent。
3. 网络层面修复
- 检查安全组/NACLs:确保容器实例的安全组和子网NACLs允许169.254.0.0/16网段的流量(元数据服务专属网段),禁止对该网段的出站限制。
- 验证容器网络路由:确认任务使用的网络模式(bridge/awsvpc)下,169.254.170.2能被正确路由到ECS Agent的凭证服务,无路由冲突。
4. 紧急兜底方案(不推荐长期使用)
临时在任务定义中添加AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY环境变量,绕过元数据端点获取凭证。注意给该凭证配置最小权限,并定期轮换。
长期预防
- 配置CloudWatch告警:针对
TaskCredentialsErrors指标设置阈值告警,异常时及时通知。 - 升级ECS Agent:旧版本Agent可能存在凭证服务bug,定期升级到AWS官方推荐的稳定版。
内容的提问来源于stack exchange,提问作者Richard Hurt
相关产品推荐
相关产品推荐

