You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ECS(EC2启动类型)Docker容器获取实例元数据报错如何解决?

问题原因

该JSON解析报错本质是请求实例元数据服务(IMDS)后返回的响应为空或非JSON格式,触发的直接原因通常有三类:

  • 最常见的是EC2实例启用了IMDSv2且配置的响应跳数限制为1:Docker默认bridge网络模式下,容器访问宿主机IMDS服务需要经过1次网络转发,跳数刚好超出限制,IMDS会直接丢弃请求返回空响应,直接调用x.json()就会抛出解析失败异常。同集群其他容器正常大概率是因为那些容器使用了host网络模式,不需要经过网络转发,跳数不会超出限制。
  • 其次可能是出问题的容器缺少访问IMDS的权限:比如容器对应的ECS任务定义中配置了禁用元数据访问的参数,或者容器内部/宿主机的iptables规则拦截了到169.254.169.254的请求。
  • 代码本身缺少响应合法性校验:没有判断响应状态码是否为200就直接解析JSON,只要响应不符合JSON格式就会触发报错。
修复方案

可以根据实际场景选择对应方案:

  • 调整EC2实例的IMDSv2跳数限制,执行命令aws ec2 modify-instance-metadata-options --instance-id <你的实例ID> --http-put-response-hop-limit 2 --http-endpoint enabled,将跳数调整为2适配bridge网络的容器访问。
  • 修改ECS任务定义,将出问题的容器网络模式改为host模式,和正常运行的容器配置保持一致。
  • 优化代码兼容IMDSv2同时增加响应校验,参考实现如下:
import requests
import logging

def get_aws_account_id():
    try:
        # 先获取IMDSv2的访问token
        token_url = 'http://169.254.169.254/latest/api/token'
        token_headers = {'X-aws-ec2-metadata-token-ttl-seconds': '21600'}
        token = requests.put(token_url, headers=token_headers, timeout=10).text
        
        # 携带token请求IAM元数据
        url = 'http://169.254.169.254/latest/meta-data/iam/info/'
        headers = {'X-aws-ec2-metadata-token': token}
        x = requests.get(url, headers=headers, timeout=10)
        
        # 先校验状态码再解析JSON
        if x.status_code == 200:
            data = x.json()
            return data['InstanceProfileArn'].split(':')[4]
        else:
            logging.error(f"请求元数据失败,状态码:{x.status_code},响应内容:{x.text}")
            return None
    except Exception as e:
        logging.error(f"exception ==> {e}")
        return None

内容的提问来源于stack exchange,提问作者ca9163d9

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 00:15:01