本文作者: 封磊

Eclicktech SA | AWS Ambassador | AWS Community Builder DevTool | AWS UGL | 亚马逊云科技云博主

阿里云&InfoQ&CSDN签约作者

亚马逊云科技已停止提供 Ubuntu 18.04、CentOS 7 等经典系统的基础 AMI?Marketplace 镜像又贵又不灵活?别急!本文将带你从零开始,利用 Ubuntu 官方免费 Cloud 镜像 + AWS 原生工具(如 vmimport 和 EC2 Image Builder),以近乎 0 成本的方式,安全、合规地构建属于你自己的定制化 AMI。全程无需第三方付费服务,适合开发者、运维和解决方案架构师参考部署。附详细步骤、避坑指南与资源清理建议!

1. 下载镜像

从 Ubuntu Cloud Images 官方下载 QCow2 格式镜像:

# 下载 Ubuntu 18.04 (Bionic) 镜像
wget https://cloud-images.ubuntu.com/bionic/current/bionic-server-cloudimg-amd64.img

# 或使用 curl
curl -O https://cloud-images.ubuntu.com/bionic/current/bionic-server-cloudimg-amd64.img

其他版本镜像地址:

2. 安装转换工具

# Ubuntu/Debian
sudo apt-get update
sudo apt-get install qemu-utils

# CentOS/RHEL
sudo yum install qemu-img

# macOS
brew install qemu

3. 转换镜像格式

将 QCow2 格式转换为 AWS 支持的 RAW 格式:

qemu-img convert -f qcow2 -O raw bionic-server-cloudimg-amd64.img bionic-server-cloudimg-amd64.raw

查看转换后的镜像信息:

qemu-img info bionic-server-cloudimg-amd64.raw

4. 创建 S3 存储桶

# 创建 S3 bucket(bucket 名称必须全局唯一)
aws s3 mb s3://my-vm-import-bucket --region us-east-1

# 或使用现有 bucket

5. 上传镜像到 S3

aws s3 cp bionic-server-cloudimg-amd64.raw s3://my-vm-import-bucket/ --region us-east-1

对于大文件,可以使用分段上传加速:

aws s3 cp bionic-server-cloudimg-amd64.raw s3://my-vm-import-bucket/ \
  --region us-east-1 \
  --storage-class STANDARD \
  --metadata imported-from=ubuntu-cloud

6. 配置 IAM 角色(vmimport)

创建 trust-policy.json

{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": { "Service": "vmie.amazonaws.com" },
         "Action": "sts:AssumeRole",
         "Condition": {
            "StringEquals":{
               "sts:Externalid": "vmimport"
            }
         }
      }
   ]
}

创建 role-policy.json

{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Effect": "Allow",
         "Action": [
            "s3:GetBucketLocation",
            "s3:GetObject",
            "s3:ListBucket" 
         ],
         "Resource": [
            "arn:aws:s3:::my-vm-import-bucket",
            "arn:aws:s3:::my-vm-import-bucket/*"
         ]
      },
      {
         "Effect": "Allow",
         "Action": [
            "s3:GetBucketLocation",
            "s3:GetObject",
            "s3:ListBucket",
            "s3:PutObject",
            "s3:GetBucketAcl"
         ],
         "Resource": [
            "arn:aws:s3:::my-vm-import-bucket",
            "arn:aws:s3:::my-vm-import-bucket/*"
         ]
      },
      {
         "Effect": "Allow",
         "Action": [
            "ec2:ModifySnapshotAttribute",
            "ec2:CopySnapshot",
            "ec2:RegisterImage",
            "ec2:Describe*"
         ],
         "Resource": "*"
      }
   ]
}

创建 IAM 角色:

# 创建角色
aws iam create-role --role-name vmimport --assume-role-policy-document file://trust-policy.json

# 附加策略
aws iam put-role-policy --role-name vmimport --policy-name vmimport --policy-document file://role-policy.json

7. 导入镜像

方式一:导入为快照(推荐)

创建 containers.json

{
  "Description": "Ubuntu 18.04 Bionic Image",
  "Format": "raw",
  "UserBucket": {
    "S3Bucket": "my-vm-import-bucket",
    "S3Key": "bionic-server-cloudimg-amd64.raw"
  }
}

执行导入:

aws ec2 import-snapshot --description "Ubuntu 18.04 Bionic" \
  --disk-container file://containers.json \
  --region us-east-1

查看导入进度:

aws ec2 describe-import-snapshot-tasks --region us-east-1

方式二:直接导入为 AMI

创建 image-containers.json

[
  {
    "Description": "Ubuntu 18.04 Bionic Root Volume",
    "Format": "raw",
    "UserBucket": {
      "S3Bucket": "my-vm-import-bucket",
      "S3Key": "bionic-server-cloudimg-amd64.raw"
    }
  }
]

执行导入:

aws ec2 import-image --description "Ubuntu 18.04 Bionic AMI" \
  --disk-containers file://image-containers.json \
  --region us-east-1

查看导入进度:

aws ec2 describe-import-image-tasks --region us-east-1

8. 从快照创建 AMI(如果使用方式一)

# 获取快照 ID(从上一步的输出中)
SNAPSHOT_ID=snap-xxxxxxxxx

# 创建 AMI
aws ec2 register-image \
  --name "Ubuntu-18.04-Bionic-Custom" \
  --description "Ubuntu 18.04 Bionic Custom Image" \
  --architecture x86_64 \
  --root-device-name /dev/sda1 \
  --block-device-mappings DeviceName=/dev/sda1,Ebs={SnapshotId=$SNAPSHOT_ID} \
  --virtualization-type hvm \
  --ena-support \
  --region us-east-1

9.通过EC2 Image Builder构建AMI镜像

9.1 创建映像管道

9.2 查看EC2 镜像




9. 启动 EC2 实例&连接

aws ec2 run-instances \
  --image-id ami-xxxxxxxxx \
  --instance-type t3.micro \
  --key-name your-key-pair \
  --security-group-ids sg-xxxxxxxxx \
  --subnet-id subnet-xxxxxxxxx \
  --region us-east-1




10. 清理资源(可选)

# 删除 S3 中的镜像文件
aws s3 rm s3://my-vm-import-bucket/bionic-server-cloudimg-amd64.raw

# 删除本地文件
rm bionic-server-cloudimg-amd64.img bionic-server-cloudimg-amd64.raw

注意事项

  1. 区域一致性:S3 bucket 和 EC2 导入必须在同一区域
  2. 文件大小:RAW 格式文件会比 QCow2 大很多,确保有足够的磁盘空间
  3. 导入时间:根据镜像大小,导入可能需要几分钟到几小时
  4. 成本:S3 存储和数据传输会产生费用
  5. 权限:确保 IAM 角色配置正确,否则导入会失败
  6. 架构支持:确认镜像架构(x86_64 或 arm64)与目标实例类型匹配

故障排查

查看导入任务详细信息:

# 查看快照导入任务
aws ec2 describe-import-snapshot-tasks --import-task-ids import-snap-xxxxxxxxx

# 查看镜像导入任务
aws ec2 describe-import-image-tasks --import-task-ids import-ami-xxxxxxxxx

常见错误:

  • ClientError: Not authorized:检查 IAM 角色配置
  • InvalidFormat:确认镜像格式转换正确
  • InvalidParameter:检查 S3 路径和 bucket 名称

更多推荐