上传自定义镜像到AWS
难度等级: ⭐⭐⭐ (中级)
预计耗时: 30-45分钟
适用环境:
- 本地虚拟化: Hyper-V (Windows 10/11 Pro, Windows Server)
- 操作系统: Ubuntu 24.04 LTS
- AWS区域: ap-east-1 (香港)
任务目标: 将本地自定义虚拟机镜像转换并上传至AWS,创建可启动的AMI
文档范围说明:
- 本文档专注于自定义操作系统镜像的上传,不涉及完整虚拟机迁移
- 数据盘迁移不在本次讨论范围
- 如需完整虚拟机迁移(包括应用和数据),请使用 AWS Application Migration Service
必备条件:
- AWS账户,具有创建S3、EC2、IAM角色的权限
- 本地Hyper-V虚拟机(已安装Ubuntu 24.04)
- 至少20GB可用磁盘空间
- 稳定的网络连接(建议带宽≥10Mbps)
权限要求:
- IAM权限:创建 VM Import/Export角色
- S3权限:创建Bucket、上传对象
- EC2权限:导入镜像、创建AMI
参考文档:
01. 准备虚拟机镜像
Section titled “01. 准备虚拟机镜像”1.1 配置虚拟机
Section titled “1.1 配置虚拟机”关键配置步骤:
- 安装cloud-init(必需)
cloud-init 是AWS EC2实例初始化的核心组件,必须安装并正确配置。未安装cloud-init的AMI将无法正常启动。
# 在Ubuntu虚拟机内执行sudo apt update && sudo apt upgrade -ysudo apt install cloud-init -y
# 配置cloud-init数据源sudo nano /etc/cloud/cloud.cfg.d/90_dpkg.cfg在配置文件中添加:
datasource_list: [ Ec2, None ]datasource: Ec2: strict_id: false- 配置网络为DHCP
# 检查netplan配置sudo nano /etc/netplan/50-cloud-init.yaml确保配置为:
network: version: 2 ethernets: eth0: dhcp4: true- 清理系统
# 清理缓存和临时文件sudo apt clean && sudo rm -rf /tmp/* && sudo rm -rf /var/tmp/*
# 清理SSH主机密钥(不是用户密钥)sudo rm -f /etc/ssh/ssh_host_*
# 清理机器IDsudo truncate -s 0 /etc/machine-id
# 清理cloud-init状态(重要)sudo cloud-init clean --logs --seed
# 清理Shell历史并立即关机history -c && sudo poweroff重要说明:
- 删除的是SSH主机密钥(
ssh_host_*),不是用户的authorized_keys - cloud-init会在EC2实例首次启动时自动重新生成SSH主机密钥
- 用户通过EC2密钥对登录,不受此操作影响
- 如果不删除主机密钥,所有基于此AMI的实例会共享相同主机密钥(安全风险)
1.2 关于其他Linux发行版
Section titled “1.2 关于其他Linux发行版”Red Hat / SUSE 注意事项:
-
Red Hat Enterprise Linux (RHEL):
- 需要 BYOL许可证
- 必须启用Red Hat Update Infrastructure (RHUI)或自建更新源
- 使用
cloud-init替代cloud-init-0.7.x旧版本
-
SUSE Linux Enterprise Server (SLES):
- 需要SUSE订阅或使用PAYG镜像
- 确保安装
cloud-init-config-suse包 - 检查防火墙规则允许AWS元数据服务 (169.254.169.254)
1.3 Hyper-V安全启动配置
Section titled “1.3 Hyper-V安全启动配置”是否启用安全启动(Secure Boot)?
建议: 禁用安全启动
原因:
- AWS不支持UEFI安全启动导入
- 导入镜像时会自动转换为Legacy BIOS或UEFI无安全启动模式
- 启用安全启动会导致导入失败或启动异常
在Hyper-V中禁用:
虚拟机设置 → 安全 → 取消勾选"启用安全启动"
1.4 导出虚拟机磁盘
Section titled “1.4 导出虚拟机磁盘”- 关闭虚拟机
- 打开Hyper-V管理器
- 选择虚拟机 → 右键 → 导出
- 选择导出路径


导出内容为当前虚拟机名称命名的目录,比如ubuntu-6下的Virtual Hard Disks

02. 准备镜像文件
Section titled “02. 准备镜像文件”2.1 AWS支持的镜像格式
Section titled “2.1 AWS支持的镜像格式”根据 AWS VM Import/Export官方文档,支持以下格式直接导入:
- VHDX - Hyper-V原生格式,支持固定和动态两种类型 ✅
- VHD - 旧版Hyper-V格式,支持固定和动态两种类型 ✅
- VMDK - VMware格式
- OVA - 开放虚拟化格式
- RAW - 原始磁盘格式
2.2 是否需要转换格式?
Section titled “2.2 是否需要转换格式?”两种选择:
选择一:直接使用VHDX(✅ 推荐 - 最简单)
- Hyper-V导出的VHDX文件可以直接上传到S3
- AWS会在导入过程中自动处理格式
- 固定大小和动态扩展的VHDX都支持
- 无需额外操作
2.3 优化镜像大小(可选)
Section titled “2.3 优化镜像大小(可选)”如果VHDX文件过大,可以优化:
# 使用PowerShell优化VHDX(需要管理员权限)Optimize-VHD -Path "C:\path\to\ubuntu24.vhdx" -Mode Full
# 查看优化后大小Get-VHD -Path "C:\path\to\ubuntu24.vhdx"03. 上传镜像到S3
Section titled “03. 上传镜像到S3”3.1 创建S3 Bucket
Section titled “3.1 创建S3 Bucket”使用AWS控制台(推荐新手使用):
- 登录 AWS S3控制台
- 点击”创建存储桶”
- 配置如下:
- 存储桶名称:
custom-ami-upload-hk(全局唯一) - 区域:
亚太地区(香港)ap-east-1 - 阻止公共访问: ✅ 全部阻止
- 版本控制: 禁用
- 加密: 启用SSE-S3(默认)
- 存储桶名称:
3.2 上传镜像文件
Section titled “3.2 上传镜像文件”方法一: AWS控制台上传(文件<5GB) ✅ 推荐小文件
- 进入创建的Bucket
- 点击”上传”
- 拖拽VHDX或VHD文件
- 点击”上传”

方法二: AWS CLI(文件>5GB) ✅ 最佳实践
# 配置访问密钥aws configure# 转到.vhdx文件所在的导出目录cd D:\Temps\ubuntu-6\"Virtual Hard Disks"
# 执行上传aws s3 cp ./ubuntu-6.vhdx s3://5apme2v0rjr4esv6-ami-upload-hk
04. 导入镜像为AMI
Section titled “04. 导入镜像为AMI”4.1 创建VM Import角色
Section titled “4.1 创建VM Import角色”仅首次使用时需要创建
方法一:使用AWS托管策略(✅ 推荐 - 最简单)
-
访问 IAM角色控制台
-
点击”创建角色”
-
选择受信任实体类型:
- 选择”AWS服务”
- 用例选择”EC2”
-
添加权限策略:
- 搜索并选择
VMImportExportRoleForAWSConnector(AWS托管策略) - 搜索并选择
AmazonS3ReadOnlyAccess(或根据需要授予S3权限)
- 搜索并选择
-
角色名称:必须命名为
vmimport(大小写敏感) -
点击”创建角色”
-
修改信任关系(重要):
- 进入刚创建的vmimport角色
- 点击”信任关系”选项卡 → “编辑信任策略”
- 将
"Service": "ec2.amazonaws.com"修改为"Service": "vmie.amazonaws.com" - 添加ExternalId条件
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "vmie.amazonaws.com" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals":{ "sts:Externalid": "vmimport" } } } ]}4.2 导入镜像
Section titled “4.2 导入镜像”使用EC2控制台:
- 访问 EC2 Image Builder
- 选择镜像
- 选择导入镜像
- 配置参数:

- 通用
- 名称:
ubuntu24 - 版本:
1.0.0 
- 名称:
- 基础映像操作系统
- 导入类型:
虚拟机导入 - 映像操作系统(OS):
Ubuntu - 操作系统版本:
Ubuntu 24.04 
- 导入类型:
- VM 导入配置
- 源:
S3存储桶 - 浏览:找到已经上传的镜像文件
- IAM角色:
vmimport 
- 源:
- 点击导入映像
导入时间: 通常20-60分钟,取决于镜像大小

4.3 监控导入进度
Section titled “4.3 监控导入进度”在EC2 Image Builder控制台 → 映像 → 我拥有的,查看状态:

05. 测试和验证
Section titled “05. 测试和验证”5.1 启动测试实例
Section titled “5.1 启动测试实例”- EC2控制台 → AMI
- 选择导入的AMI → 启动实例
- 配置:
- 实例类型: t3.micro(测试用)
- 网络: 默认VPC
- 安全组: 允许SSH (22端口)
- 存储配置:GP3


5.2 验证清单
Section titled “5.2 验证清单”连接实例:
# 使用原先的密钥进行登录ssh -i /path/to/your-key.pem ubuntu@<EC2-Public-IP>登录实例后检查:
# 1. 验证SSH主机密钥已重新生成(应该有新文件)ls -la /etc/ssh/ssh_host_*# 预期:看到新生成的密钥文件,创建时间为实例启动时间
# 2. 验证cloud-init运行成功sudo cloud-init status# 预期输出: status: done
# 3. 检查网络配置ip addr show# 应显示从DHCP获取的IP
# 4. 验证用户authorized_keys已注入cat ~/.ssh/authorized_keys# 应显示启动实例时指定的EC2密钥对公钥
# 5. 验证系统日志无错误sudo journalctl -b | grep -i error5.3 性能基准测试(可选)
Section titled “5.3 性能基准测试(可选)”# 磁盘IO测试sudo dd if=/dev/zero of=/tmp/testfile bs=1M count=1024 oflag=direct
# 网络测试sudo apt install iperf3iperf3 -c speedtest.hk.clouvider.netQ1: 导入失败提示”ClientError: Invalid S3 Bucket”
Section titled “Q1: 导入失败提示”ClientError: Invalid S3 Bucket””原因: VM Import角色无权访问S3 Bucket
解决:
- 检查
role-policy.json中Bucket名称是否正确 - 确认Bucket与EC2在同一区域(香港)
- 重新附加策略到vmimport角色
Q2: 实例无法启动,显示”Operating system not found”
Section titled “Q2: 实例无法启动,显示”Operating system not found””原因:
- 虚拟机磁盘未正确准备
- GRUB引导损坏
- 启动模式不匹配
解决:
- 重新检查虚拟机内GRUB配置
- 确保
/boot分区可访问 - 导入时选择正确的启动模式(Legacy BIOS或UEFI)
Q3: cloud-init未运行,无法获取元数据
Section titled “Q3: cloud-init未运行,无法获取元数据”原因: cloud-init未安装或配置错误
解决:
# 重新配置cloud-initsudo dpkg-reconfigure cloud-init
# 检查配置sudo cat /etc/cloud/cloud.cfg.d/90_dpkg.cfg
# 手动运行sudo cloud-init initQ4: 上传速度太慢
Section titled “Q4: 上传速度太慢”解决方案:
- 启用S3传输加速(推荐)
- 使用AWS Snowball(镜像>80GB时考虑)
- 优化VHDX文件大小:
# 压缩VHDX减少文件大小Optimize-VHD -Path ubuntu24.vhdx -Mode FullQ5: 导入后AMI大小比原始文件大
Section titled “Q5: 导入后AMI大小比原始文件大”原因: AWS自动将磁盘转换为EBS快照,并对齐到块大小
说明: 这是正常行为,实际计费按使用空间计算,不是快照大小
Q6: 清理SSH密钥后如何登录实例?
Section titled “Q6: 清理SSH密钥后如何登录实例?”说明:
- 清理的是SSH主机密钥(服务器身份标识),不是用户登录凭证
- 用户登录使用EC2密钥对(启动实例时指定)
- cloud-init会在首次启动时:
- 自动生成新的SSH主机密钥
- 从AWS元数据获取EC2公钥
- 将公钥写入
~/.ssh/authorized_keys
登录方式:
ssh -i your-ec2-key.pem ubuntu@<instance-ip>如果无法登录,检查:
- 安全组是否允许SSH(22端口)
- cloud-init是否正常运行(通过EC2控制台查看系统日志)
- 密钥对权限是否正确(
chmod 400 your-key.pem)
Q7: VHDX和VHD应该选择哪个?
Section titled “Q7: VHDX和VHD应该选择哪个?”官方支持情况:
- ✅ VHDX(固定和动态)- 直接支持
- ✅ VHD(固定和动态)- 直接支持
建议:
- VHDX直接上传 - 最简单,Hyper-V原生格式
- 转换为VHD固定格式 - 如果遇到动态VHDX导入问题时使用
自定义镜像的优劣势
Section titled “自定义镜像的优劣势”- 完全控制: 预装所需软件、配置、安全加固
- 快速部署: 无需每次重新配置系统
- 一致性: 确保所有实例使用相同基础镜像
- 合规性: 满足企业内部镜像标准和审计要求
- 成本优化: BYOL许可证可节省成本
- 维护负担: 需要定期更新镜像(安全补丁、软件版本)
- 存储成本: AMI和EBS快照产生存储费用
- 区域限制: AMI仅在创建区域可用(需跨区域复制)
- 兼容性风险: 硬件抽象层差异可能导致驱动问题
- 调试困难: 自定义配置错误可能难以排查
建议:
- 小型团队: 使用AWS Marketplace官方镜像 + 配置管理工具(Ansible/Chef)
- 大型企业: 建立镜像管道,定期更新和测试自定义AMI
graph TB
A[准备Hyper-V虚拟机] --> B{是否安装cloud-init?}
B -->|否| C[安装并配置cloud-init]
B -->|是| D[清理系统和SSH主机密钥]
C --> D
D --> E[关闭虚拟机]
E --> F[导出或复制VHDX文件]
F --> G{是否转换格式?}
G -->|否-直接使用VHDX| H[创建S3 Bucket<br/>区域: ap-east-1]
G -->|是-转换为VHD固定| I[PowerShell转换]
I --> H
H --> J{文件大小}
J -->|小于5GB| K[控制台直接上传]
J -->|大于5GB| L[启用传输加速上传]
K --> M[创建vmimport角色]
L --> M
M --> N[EC2控制台导入镜像<br/>支持VHDX和VHD]
N --> O[等待转换完成<br/>20-60分钟]
O --> P{导入状态}
P -->|completed| Q[创建测试实例]
P -->|failed| R[检查错误日志]
R --> S[修复问题后重新导入]
Q --> T[使用EC2密钥对登录验证]
T --> U{测试通过?}
U -->|是| V[创建生产AMI]
U -->|否| R
- AWS VM Import/Export 用户指南
- VM Import/Export 的资源导入要求
- 准备Linux虚拟机以供导入
- cloud-init官方文档
- AMI最佳实践
- S3传输加速
- Hyper-V虚拟机导出指南
文档版本: 1.1
最后更新: 2024年12月
适用AWS服务: EC2, S3, IAM
维护者: Cloud Support Team