Skip to content

上传自定义镜像到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

必备条件:

  1. AWS账户,具有创建S3、EC2、IAM角色的权限
  2. 本地Hyper-V虚拟机(已安装Ubuntu 24.04)
  3. 至少20GB可用磁盘空间
  4. 稳定的网络连接(建议带宽≥10Mbps)

权限要求:

  • IAM权限:创建 VM Import/Export角色
  • S3权限:创建Bucket、上传对象
  • EC2权限:导入镜像、创建AMI

参考文档:


关键配置步骤:

  1. 安装cloud-init(必需)

cloud-init 是AWS EC2实例初始化的核心组件,必须安装并正确配置。未安装cloud-init的AMI将无法正常启动。

# 在Ubuntu虚拟机内执行
sudo apt update && sudo apt upgrade -y
sudo 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
  1. 配置网络为DHCP
# 检查netplan配置
sudo nano /etc/netplan/50-cloud-init.yaml

确保配置为:

network:
version: 2
ethernets:
eth0:
dhcp4: true
  1. 清理系统
# 清理缓存和临时文件
sudo apt clean && sudo rm -rf /tmp/* && sudo rm -rf /var/tmp/*
# 清理SSH主机密钥(不是用户密钥)
sudo rm -f /etc/ssh/ssh_host_*
# 清理机器ID
sudo 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的实例会共享相同主机密钥(安全风险)

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)

是否启用安全启动(Secure Boot)?

建议: 禁用安全启动

原因:

  • AWS不支持UEFI安全启动导入
  • 导入镜像时会自动转换为Legacy BIOS或UEFI无安全启动模式
  • 启用安全启动会导致导入失败或启动异常

在Hyper-V中禁用:

虚拟机设置 → 安全 → 取消勾选"启用安全启动"

Hyper-V安全启动设置

  1. 关闭虚拟机
  2. 打开Hyper-V管理器
  3. 选择虚拟机 → 右键 → 导出
  4. 选择导出路径

选择导出

设置导出路径

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

找到导出文件


根据 AWS VM Import/Export官方文档,支持以下格式直接导入

  • VHDX - Hyper-V原生格式,支持固定和动态两种类型 ✅
  • VHD - 旧版Hyper-V格式,支持固定和动态两种类型 ✅
  • VMDK - VMware格式
  • OVA - 开放虚拟化格式
  • RAW - 原始磁盘格式

两种选择

选择一:直接使用VHDX(✅ 推荐 - 最简单)

  • Hyper-V导出的VHDX文件可以直接上传到S3
  • AWS会在导入过程中自动处理格式
  • 固定大小和动态扩展的VHDX都支持
  • 无需额外操作

如果VHDX文件过大,可以优化:

# 使用PowerShell优化VHDX(需要管理员权限)
Optimize-VHD -Path "C:\path\to\ubuntu24.vhdx" -Mode Full
# 查看优化后大小
Get-VHD -Path "C:\path\to\ubuntu24.vhdx"

使用AWS控制台(推荐新手使用):

  1. 登录 AWS S3控制台
  2. 点击”创建存储桶”
  3. 配置如下:
    • 存储桶名称: custom-ami-upload-hk(全局唯一)
    • 区域: 亚太地区(香港)ap-east-1
    • 阻止公共访问: ✅ 全部阻止
    • 版本控制: 禁用
    • 加密: 启用SSE-S3(默认)

方法一: AWS控制台上传(文件<5GB)推荐小文件

  1. 进入创建的Bucket
  2. 点击”上传”
  3. 拖拽VHDX或VHD文件
  4. 点击”上传”

上传镜像

方法二: 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

上传完成

仅首次使用时需要创建

方法一:使用AWS托管策略(✅ 推荐 - 最简单)

  1. 访问 IAM角色控制台

  2. 点击”创建角色”

  3. 选择受信任实体类型:

    • 选择”AWS服务”
    • 用例选择”EC2”
  4. 添加权限策略:

    • 搜索并选择 VMImportExportRoleForAWSConnector(AWS托管策略)
    • 搜索并选择 AmazonS3ReadOnlyAccess(或根据需要授予S3权限)
  5. 角色名称:必须命名为 vmimport(大小写敏感)

  6. 点击”创建角色”

  7. 修改信任关系(重要):

    • 进入刚创建的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"
}
}
}
]
}

使用EC2控制台:

  1. 访问 EC2 Image Builder
  2. 选择镜像
  3. 选择导入镜像
  4. 配置参数:

导入镜像

  • 通用
    • 名称:ubuntu24
    • 版本:1.0.0
    • 通用
  • 基础映像操作系统
    • 导入类型:虚拟机导入
    • 映像操作系统(OS):Ubuntu
    • 操作系统版本:Ubuntu 24.04
    • 基础映像操作系统
  • VM 导入配置
    • 源:S3存储桶
    • 浏览:找到已经上传的镜像文件
    • IAM角色:vmimport
    • VM 导入配置
  1. 点击导入映像

导入时间: 通常20-60分钟,取决于镜像大小

等待导入完成

EC2 Image Builder控制台 → 映像 → 我拥有的,查看状态:

查看进度


  1. EC2控制台 → AMI
  2. 选择导入的AMI → 启动实例
  3. 配置:
    • 实例类型: t3.micro(测试用)
    • 网络: 默认VPC
    • 安全组: 允许SSH (22端口)
    • 存储配置:GP3

从AMI启动实例 启动实例

连接实例

# 使用原先的密钥进行登录
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 error
# 磁盘IO测试
sudo dd if=/dev/zero of=/tmp/testfile bs=1M count=1024 oflag=direct
# 网络测试
sudo apt install iperf3
iperf3 -c speedtest.hk.clouvider.net

Q1: 导入失败提示”ClientError: Invalid S3 Bucket”

Section titled “Q1: 导入失败提示”ClientError: Invalid S3 Bucket””

原因: VM Import角色无权访问S3 Bucket

解决:

  1. 检查 role-policy.json 中Bucket名称是否正确
  2. 确认Bucket与EC2在同一区域(香港)
  3. 重新附加策略到vmimport角色

Q2: 实例无法启动,显示”Operating system not found”

Section titled “Q2: 实例无法启动,显示”Operating system not found””

原因:

  • 虚拟机磁盘未正确准备
  • GRUB引导损坏
  • 启动模式不匹配

解决:

  1. 重新检查虚拟机内GRUB配置
  2. 确保/boot分区可访问
  3. 导入时选择正确的启动模式(Legacy BIOS或UEFI)

Q3: cloud-init未运行,无法获取元数据

Section titled “Q3: cloud-init未运行,无法获取元数据”

原因: cloud-init未安装或配置错误

解决:

# 重新配置cloud-init
sudo dpkg-reconfigure cloud-init
# 检查配置
sudo cat /etc/cloud/cloud.cfg.d/90_dpkg.cfg
# 手动运行
sudo cloud-init init

解决方案:

  1. 启用S3传输加速(推荐)
  2. 使用AWS Snowball(镜像>80GB时考虑)
  3. 优化VHDX文件大小:
# 压缩VHDX减少文件大小
Optimize-VHD -Path ubuntu24.vhdx -Mode Full

原因: AWS自动将磁盘转换为EBS快照,并对齐到块大小

说明: 这是正常行为,实际计费按使用空间计算,不是快照大小

Q6: 清理SSH密钥后如何登录实例?

Section titled “Q6: 清理SSH密钥后如何登录实例?”

说明:

  • 清理的是SSH主机密钥(服务器身份标识),不是用户登录凭证
  • 用户登录使用EC2密钥对(启动实例时指定)
  • cloud-init会在首次启动时:
    1. 自动生成新的SSH主机密钥
    2. 从AWS元数据获取EC2公钥
    3. 将公钥写入~/.ssh/authorized_keys

登录方式:

ssh -i your-ec2-key.pem ubuntu@<instance-ip>

如果无法登录,检查:

  1. 安全组是否允许SSH(22端口)
  2. cloud-init是否正常运行(通过EC2控制台查看系统日志)
  3. 密钥对权限是否正确(chmod 400 your-key.pem

官方支持情况:

  • ✅ VHDX(固定和动态)- 直接支持
  • ✅ VHD(固定和动态)- 直接支持

建议:

  • VHDX直接上传 - 最简单,Hyper-V原生格式
  • 转换为VHD固定格式 - 如果遇到动态VHDX导入问题时使用

  1. 完全控制: 预装所需软件、配置、安全加固
  2. 快速部署: 无需每次重新配置系统
  3. 一致性: 确保所有实例使用相同基础镜像
  4. 合规性: 满足企业内部镜像标准和审计要求
  5. 成本优化: BYOL许可证可节省成本
  1. 维护负担: 需要定期更新镜像(安全补丁、软件版本)
  2. 存储成本: AMI和EBS快照产生存储费用
  3. 区域限制: AMI仅在创建区域可用(需跨区域复制)
  4. 兼容性风险: 硬件抽象层差异可能导致驱动问题
  5. 调试困难: 自定义配置错误可能难以排查

建议:

  • 小型团队: 使用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


文档版本: 1.1
最后更新: 2024年12月
适用AWS服务: EC2, S3, IAM
维护者: Cloud Support Team