在AWS云平台上,AMI(Amazon Machine Image)是启动EC2实例的基础模板。官方提供的AMI虽然方便,但存在几个痛点:
提示:根据AWS官方文档,使用自建AMI相比Marketplace商业镜像平均可节省60-80%的镜像成本。
| 方案类型 | 成本 | 复杂度 | 定制灵活性 | 适用场景 |
|---|---|---|---|---|
| Marketplace商业镜像 | 高 | 低 | 差 | 快速验证场景 |
| Packer构建 | 中 | 高 | 优 | 持续集成环境 |
| 官方Cloud镜像导入(本文方案) | 低 | 中 | 良 | 定制化生产环境 |
本方案采用的技术栈:
推荐使用具备以下配置的本地机器:
安装必备工具:
bash复制# Ubuntu/Debian
sudo apt update && sudo apt install -y qemu-utils awscli
# RHEL/CentOS
sudo yum install -y qemu-img awscli
# macOS
brew install qemu awscli
bash复制aws s3 mb s3://my-ami-import-$(date +%s) --region us-east-1
bash复制aws configure
# 输入您的Access Key ID、Secret Access Key、默认区域
推荐从Ubuntu官方镜像站获取:
bash复制# Ubuntu 18.04
wget https://cloud-images.ubuntu.com/bionic/current/bionic-server-cloudimg-amd64.img
# 校验文件完整性
sha256sum bionic-server-cloudimg-amd64.img
转换命令详解:
bash复制qemu-img convert \
-f qcow2 \ # 输入格式
-O raw \ # 输出格式
-p \ # 显示进度
-c \ # 压缩(可选)
bionic-server-cloudimg-amd64.img \
ubuntu-18.04.raw
转换耗时参考:
对于大文件(>5GB),建议使用分段上传:
bash复制aws s3 cp ubuntu-18.04.raw s3://my-ami-import/ \
--storage-class STANDARD \
--metadata imported-from=ubuntu-cloud \
--region us-east-1 \
--expected-size $(stat -c %s ubuntu-18.04.raw)
上传速度参考:
创建专用策略文档vmimport-policy.json:
json复制{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": [
"arn:aws:s3:::my-ami-import",
"arn:aws:s3:::my-ami-import/*"
]
},
{
"Effect": "Allow",
"Action": [
"ec2:ModifySnapshotAttribute",
"ec2:CopySnapshot",
"ec2:RegisterImage",
"ec2:Describe*"
],
"Resource": "*"
}
]
}
bash复制# 创建角色
aws iam create-role \
--role-name vmimport \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "vmie.amazonaws.com"},
"Action": "sts:AssumeRole",
"Condition": {"StringEquals": {"sts:Externalid": "vmimport"}}
}]
}'
# 附加策略
aws iam put-role-policy \
--role-name vmimport \
--policy-name vmimport-policy \
--policy-document file://vmimport-policy.json
snapshot-container.json:json复制{
"Description": "Ubuntu 18.04 Bionic Base Image",
"Format": "raw",
"UserBucket": {
"S3Bucket": "my-ami-import",
"S3Key": "ubuntu-18.04.raw"
}
}
bash复制aws ec2 import-snapshot \
--description "Ubuntu 18.04 Base" \
--disk-container file://snapshot-container.json \
--region us-east-1 \
--tag-specifications 'ResourceType=import-snapshot-task,Tags=[{Key=Name,Value=Ubuntu-18.04}]'
bash复制watch -n 60 'aws ec2 describe-import-snapshot-tasks \
--filters Name=task-state,Values=active \
--query "ImportSnapshotTasks[*].{ID:ImportTaskId,Status:SnapshotTaskDetail.Status,Progress:SnapshotTaskDetail.Progress}" \
--output table'
ami-container.json:json复制[{
"Description": "Ubuntu 18.04 Root Volume",
"DeviceName": "/dev/sda1",
"Format": "raw",
"UserBucket": {
"S3Bucket": "my-ami-import",
"S3Key": "ubuntu-18.04.raw"
}
}]
bash复制aws ec2 import-image \
--architecture x86_64 \
--description "Ubuntu 18.04 AMI" \
--disk-containers file://ami-container.json \
--license-type BYOL \
--platform Linux \
--region us-east-1
bash复制aws imagebuilder create-infrastructure-configuration \
--name "ubuntu-18.04-infra" \
--instance-types "t3.medium" \
--key-pair "your-key-pair" \
--subnet-id "subnet-xxxxxx" \
--security-group-ids "sg-xxxxxx" \
--terminate-instance-on-failure \
--region us-east-1
bash复制aws imagebuilder create-image-recipe \
--name "ubuntu-18.04-recipe" \
--semantic-version "1.0.0" \
--components '[{
"componentArn": "arn:aws:imagebuilder:us-east-1:aws:component/update-linux/x.x.x"
}]' \
--parent-image "ami-imported-id" \
--working-directory "/tmp" \
--description "Custom Ubuntu 18.04 image" \
--region us-east-1
bash复制sudo apt clean
sudo rm -rf /var/lib/apt/lists/*
bash复制sudo find /var/log -type f -exec truncate -s 0 {} \;
bash复制sudo apt install zerofree
sudo zerofree -v /dev/sda1
完整导入自动化脚本import-ami.sh:
bash复制#!/bin/bash
set -e
# 参数配置
IMAGE_URL="https://cloud-images.ubuntu.com/bionic/current/bionic-server-cloudimg-amd64.img"
S3_BUCKET="my-ami-import"
REGION="us-east-1"
# 下载镜像
echo "Downloading image..."
wget -q --show-progress "$IMAGE_URL"
# 格式转换
echo "Converting image format..."
qemu-img convert -f qcow2 -O raw bionic-server-cloudimg-amd64.img ubuntu.raw
# 上传到S3
echo "Uploading to S3..."
aws s3 cp ubuntu.raw "s3://${S3_BUCKET}/" \
--storage-class STANDARD \
--metadata imported-from=ubuntu-cloud \
--region "$REGION"
# 导入快照
echo "Importing snapshot..."
IMPORT_TASK=$(aws ec2 import-snapshot \
--description "Ubuntu 18.04" \
--disk-container "{\"Format\":\"raw\",\"UserBucket\":{\"S3Bucket\":\"${S3_BUCKET}\",\"S3Key\":\"ubuntu.raw\"}}" \
--region "$REGION" \
--output json)
TASK_ID=$(echo "$IMPORT_TASK" | jq -r '.ImportTaskId')
# 等待导入完成
echo -n "Waiting for import to complete"
while true; do
STATUS=$(aws ec2 describe-import-snapshot-tasks \
--import-task-ids "$TASK_ID" \
--query "ImportSnapshotTasks[0].SnapshotTaskDetail.Status" \
--output text \
--region "$REGION")
if [[ "$STATUS" == "completed" ]]; then
break
elif [[ "$STATUS" == "error" ]]; then
echo "Import failed!"
exit 1
fi
echo -n "."
sleep 30
done
# 获取快照ID
SNAPSHOT_ID=$(aws ec2 describe-import-snapshot-tasks \
--import-task-ids "$TASK_ID" \
--query "ImportSnapshotTasks[0].SnapshotTaskDetail.SnapshotId" \
--output text \
--region "$REGION")
# 注册AMI
echo "Registering AMI..."
aws ec2 register-image \
--name "Ubuntu-18.04-Custom" \
--description "Custom Ubuntu 18.04 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 "$REGION"
echo "AMI creation complete!"
S3存储费用:
EC2资源费用:
计算资源费用:
bash复制# 删除S3临时文件
aws s3 rm s3://my-ami-import/ubuntu.raw
# 删除本地文件
rm -f bionic-server-cloudimg-amd64.img ubuntu.raw
# 注销不再使用的AMI
aws ec2 deregister-image --image-id ami-xxxxxx
# 删除关联快照
aws ec2 delete-snapshot --snapshot-id snap-xxxxxx
bash复制aws s3api put-bucket-lifecycle-configuration \
--bucket my-ami-import \
--lifecycle-configuration '{
"Rules": [{
"ID": "TempFileExpiration",
"Status": "Enabled",
"Prefix": "",
"Expiration": {"Days": 1},
"AbortIncompleteMultipartUpload": {"DaysAfterInitiation": 1}
}]
}'
| 错误代码 | 原因分析 | 解决方案 |
|---|---|---|
| InvalidFormat | 镜像格式不匹配 | 确认使用qemu-img info检查格式 |
| Client.UnauthorizedOperation | IAM权限不足 | 检查vmimport角色策略附件 |
| ResourceLimitExceeded | 资源配额不足 | 申请提高EBS快照配额 |
| InvalidParameterValue | S3路径错误 | 确认bucket名称和对象key |
导入速度慢:
c5.large实例运行Image Builder镜像启动失败:
/etc/fstab配置hvm虚拟化类型镜像加固建议:
bash复制sudo apt update && sudo apt full-upgrade -y
bash复制sudo apt install -y fail2ban unattended-upgrades
IAM安全配置:
网络隔离建议:
在实际操作中,我发现导入过程中最耗时的环节通常是S3上传和EC2导入服务处理阶段。对于生产环境使用,建议提前24小时开始准备镜像,并做好版本管理。一个实用的技巧是为每个镜像版本创建描述性标签,例如:
bash复制aws ec2 create-tags \
--resources ami-xxxxxx \
--tags Key=Version,Value=1.0.0 Key=OS,Value=Ubuntu-18.04