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

使用AWS CLI创建的AMI无法保留user-data修改,控制台创建则正常

问题根源:运行中实例创建AMI时的磁盘一致性差异

你遇到的这个问题,核心原因是AWS控制台和CLI在创建AMI时,默认对实例的处理方式不同:

  • 控制台创建AMI时,默认会先停止实例,确保磁盘上所有未写入的缓存都同步到磁盘,然后再创建根卷快照,这样生成的AMI会完整包含实例上的所有修改。
  • 而CLI的aws ec2 create-image命令默认是重启实例(而非停止),虽然重启也会尝试同步磁盘,但在某些场景下(比如实例刚完成user-data操作,缓存还没完全写入),快照可能无法捕获所有最新修改;更极端的情况是,如果重启过程中出现异常,甚至可能导致快照和实例当前状态不一致。

另外还有个容易忽略的细节:aws ec2 wait instance-running只是等待实例进入运行状态,并不会等待cloud-init完全执行完毕。即使你通过SSH登录验证了修改存在,也可能存在部分写入操作还在后台缓存中,未持久化到磁盘。


解决方案:确保创建AMI时磁盘状态一致

方案1:创建AMI前先停止实例(推荐)

修改你的脚本,在创建AMI前先停止实例,等待实例完全停止后再执行create-image操作。这样能保证磁盘快照完整包含所有修改,和控制台的默认行为一致:

# 先停止实例,确保磁盘写入完全同步
echo "Stopping instance ${ec2_id}"
aws ec2 stop-instances --instance-ids ${ec2_id}
aws ec2 wait instance-stopped --instance-ids ${ec2_id}

# 创建AMI
echo "Creating image from instance ${ec2_id}"
image_id=$(aws ec2 create-image --name ${image_name} --instance-id ${ec2_id} --output text --query 'ImageId')
echo "Image ID is ${image_id}"

# 等待AMI可用
echo "Waiting for image ${image_id} to be available"
aws ec2 wait image-available --image-ids ${image_id}
echo "Image ${image_id} (${image_name}) is now available"

# 可选:如果需要保留实例,可以重新启动它
aws ec2 start-instances --instance-ids ${ec2_id}

方案2:创建前强制同步磁盘缓存

如果不想停止实例,可以通过SSH连接到实例,执行sync命令强制将内存中的缓存写入磁盘,然后再创建AMI:

# 获取实例公网IP(假设你的实例有公网访问权限)
instance_ip=$(aws ec2 describe-instances --instance-ids ${ec2_id} --output text --query 'Reservations[0].Instances[0].PublicIpAddress')

# 执行sync命令,确保缓存写入磁盘
echo "Syncing disk cache on instance ${ec2_id}"
ssh -i "${key_name}.pem" ec2-user@${instance_ip} "sync && sudo sync"

# 之后再执行create-image命令
echo "Creating image from instance ${ec2_id}"
image_id=$(aws ec2 create-image --name ${image_name} --instance-id ${ec2_id} --output text --query 'ImageId')
# ... 后续等待AMI可用的代码不变

验证方法:检查AMI的快照来源

你可以通过以下命令验证CLI创建的AMI是否使用了实例的根卷快照:

  1. 获取实例根卷的快照ID:
volume_id=$(aws ec2 describe-instances --instance-ids ${ec2_id} --output text --query 'Reservations[0].Instances[0].BlockDeviceMappings[0].Ebs.VolumeId')
snapshot_id=$(aws ec2 describe-volumes --volume-ids ${volume_id} --output text --query 'Volumes[0].SnapshotId')
echo "Instance root volume snapshot ID: ${snapshot_id}"
  1. 获取新创建AMI的根卷快照ID:
ami_snapshot_id=$(aws ec2 describe-images --image-ids ${image_id} --output text --query 'Images[0].BlockDeviceMappings[0].Ebs.SnapshotId')
echo "AMI root volume snapshot ID: ${ami_snapshot_id}"

如果两个快照ID不同,说明CLI创建的AMI没有使用实例的最新快照,这时候就需要检查实例状态和创建流程了。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:02:02