如何解决EC2实例访问元数据时出现的401未授权错误?
问题根源
你尝试通过修改/etc/nitro/eni.cfg禁用IMDSv2,但该配置修改后不会立即生效,需要重启实例或nitro网络服务才能加载新配置。而你的UserData脚本在修改文件后立刻执行curl,此时IMDSv2仍处于启用状态,导致401错误。此外,直接修改系统文件并非AWS官方推荐的IMDS配置方式,存在持久化失效风险。
推荐解决方案
方案1:创建实例时直接配置元数据选项(最优)
在调用create_instances时添加MetadataOptions参数,设置允许IMDSv1访问,无需修改系统文件:
import boto3 import webbrowser import time ec2 = boto3.resource('ec2') myInstance = ec2.create_instances( ImageId='ami-0f34c5ae932e6f0e4', KeyName='mykey', MinCount=1, MaxCount=1, SecurityGroupIds=['sg-070cacabf704f07ef'], InstanceType='t2.nano', # 添加元数据配置,允许IMDSv1和IMDSv2 MetadataOptions={ 'HttpTokens': 'optional', 'HttpPutResponseHopLimit': 1 }, UserData=f"""#!/bin/bash yum update -y yum install httpd -y systemctl enable httpd systemctl start httpd # 直接用IMDSv1获取元数据,无需修改系统文件 instance_id=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) ami_id=$(curl -s http://169.254.169.254/latest/meta-data/ami-id) instance_type=$(curl -s http://169.254.169.254/latest/meta-data/instance-type) cat > /var/www/html/index.html <<EOF <!DOCTYPE html> <html> <head> <title>Instance Metadata</title> </head> <body> <h1>Hello World</h1> <p>Instance ID: $instance_id</p> <p>AMI ID: $ami_id</p> <p>Instance Type: $instance_type</p> </body> </html> EOF """, TagSpecifications=[ { 'ResourceType': 'instance', 'Tags': [ { 'Key': 'Name', 'Value': 'MyInstance' } ] } ] ) # 后续代码不变 myInstance[0].wait_until_running() myInstance[0].reload() instance_id = myInstance[0].id image_id = myInstance[0].image_id instance_type = myInstance[0].instance_type time.sleep(30) public_ip = myInstance[0].public_ip_address print('Instance ID:', instance_id) print('Public IP Address:', public_ip) webbrowser.open_new_tab(f'http://{public_ip}/') print('Opened web browser')
方案2:使用IMDSv2协议获取元数据(无需禁用v2)
如果不想修改实例元数据配置,可在UserData中使用IMDSv2的token方式访问:
# 获取IMDSv2 token TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") # 通过token访问元数据 instance_id=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id) ami_id=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/ami-id) instance_type=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-type)
为什么修改/etc/nitro/eni.cfg无效?
/etc/nitro/eni.cfg是Nitro实例的网络配置文件,修改后需要重启nitro-enimgr服务或实例才能生效:
systemctl restart nitro-enimgr
但在UserData中执行该操作会中断网络,导致后续脚本无法完成,因此这种方式不适用初始化场景。
内容的提问来源于stack exchange,提问作者Ciaran Hickey
相关产品推荐
相关产品推荐

