手动从OS磁盘EBS卷创建AMI的所需修改及增量备份启动异常问题
首先给你明确答案:是的,你必须手动执行import-image做的那些系统适配修改,否则你的VMware裸盘镜像无法在EC2上正常启动。下面我会一步步拆解问题、给出具体的修改步骤、自动化方案,以及纠正你对Packer的误解。
为什么会出现Kernel panic - not syncing: VFS: Unable to mount root fs?
你已经观察到了关键差异:AWS的import-image工具会对导入的裸盘镜像做EC2专属的系统适配修改,而你的手动快照/卷完全没做这些。这些修改是让VMware的OS能在EC2的虚拟化环境下正常启动的核心:
- 安装AWS PV/ENA驱动(用于EC2的存储、网络适配)
- 修改initramfs/initrd,添加EC2启动所需的模块(比如你看到的
.vmimport后缀的镜像文件) - 调整GRUB启动配置,适配EC2的块设备命名、控制台输出
- 修正
/etc/fstab,用UUID而非固定设备名挂载根文件系统(EC2的块设备名可能动态变化) - 禁用VMware相关服务/驱动,避免启动冲突
你的VMware裸盘是针对VMware的硬件层做的配置,直接放到EC2上,内核找不到适配的存储驱动,自然无法挂载根文件系统,触发panic。
你需要手动执行的具体修改步骤(以CentOS 7为例)
你可以把VMware裸盘挂载到一个临时EC2实例(建议用同版本的CentOS 7 AMI启动),然后通过losetup挂载镜像,chroot进去执行以下操作:
1. 安装AWS驱动和工具
# 安装AWS PV驱动、网络工具、CloudFormation bootstrap工具 yum install -y aws-cli ec2-net-utils aws-cfn-bootstrap # 安装ENA驱动(针对HVM实例,现代EC2实例都用这个) yum install -y kernel-devel-$(uname -r) gcc git git clone https://github.com/amzn/amzn-drivers.git cd amzn-drivers make -C kernel/ena make -C kernel/ena install
2. 生成适配EC2的initramfs
# 生成包含VMimport模块的initramfs dracut -f /boot/initramfs-$(uname -r).img.vmimport $(uname -r)
3. 修改GRUB启动配置
编辑/boot/grub2/grub.cfg(或者修改/etc/default/grub后用grub2-mkconfig -o /boot/grub2/grub.cfg重新生成):
- 把启动项中的
root=/dev/sda1改成根文件系统的UUID(可以用blkid查看) - 添加
console=ttyS0参数(用于EC2控制台查看启动日志) - 指定initramfs路径为刚才生成的
.vmimport文件
示例修改后的GRUB条目核心部分:
linux16 /vmlinuz-3.10.0-327.36.3.el7.x86_64 root=UUID=<你的根分区UUID> ro console=ttyS0 crashkernel=auto rhgb quiet initrd16 /initramfs-3.10.0-327.36.3.el7.x86_64.img.vmimport
4. 修正/etc/fstab
把根文件系统的挂载项从/dev/sda1改成UUID,比如:
UUID=<你的根分区UUID> / xfs defaults 0 0
5. 清理VMware相关组件
# 禁用vmtoolsd服务 systemctl disable vmtoolsd # 删除VMware相关驱动文件(如果存在) rm -rf /usr/lib/vmware*
如何通过代码/脚本自动化这些操作?
你可以写一个bash脚本,结合AWS CLI实现全自动化:
- 启动一个临时EC2实例(用同OS版本的AMI)
- 将VMware裸盘从S3下载到临时实例
- 用
losetup挂载裸盘镜像,创建挂载点并挂载分区 chroot到挂载的文件系统,执行上述修改脚本- 卸载分区和镜像,创建EBS快照
- 基于快照创建AMI(HVM镜像无需指定AKI,PV镜像需要找对应OS的AKI)
- 终止临时EC2实例
示例脚本核心片段:
# 挂载裸盘镜像 losetup /dev/loop0 vmware_disk.raw partprobe /dev/loop0 mount /dev/loop0p1 /mnt/vm_disk # chroot执行修改 chroot /mnt/vm_disk /bin/bash << EOF # 这里放上面的修改命令:安装驱动、生成initramfs、修改GRUB、修正fstab等 EOF # 卸载并清理 umount /mnt/vm_disk losetup -d /dev/loop0
Packer是否适用?你之前的理解有误!
Packer完全可以满足你的需求,而且是非常优的自动化方案:
- Packer不需要依赖
source_ami,它支持直接从raw镜像导入并做provisioning。你可以用amazon-importbuilder,或者先把raw镜像上传到S3,用Packer的chrootprovisioner修改镜像,再导入生成AMI。 - 对于增量备份,Packer的
amazon-ebsbuilder支持previous_snapshot_id参数,可以基于之前的增量快照构建新的快照,再生成AMI,大大减少耗时。 - Packer可以把所有系统适配修改写到provisioner里(比如shell脚本),完全自动化整个流程,不需要手动操作。
举个简单的Packer配置思路:
source "amazon-ebs" "centos7" { region = "us-east-1" instance_type = "t2.micro" source_ami_filter { filters = { name = "CentOS Linux 7 x86_64 HVM EBS*" root-device-type = "ebs" } owners = ["125523088429"] # CentOS官方账号ID most_recent = true } ssh_username = "centos" previous_snapshot_id = "${var.previous_snapshot_id}" # 增量备份用的之前的快照ID } build { sources = ["source.amazon-ebs.centos7"] provisioner "shell" { inline = [ "yum install -y aws-cli ec2-net-utils", "dracut -f /boot/initramfs-$(uname -r).img.vmimport $(uname -r)", # 其他修改步骤... ] } post-processor "amazon-ami" { ami_name = "centos7-incremental-{{timestamp}}" } }
更优方案:用AWS原生的增量导入功能
如果你不想自己处理系统适配,AWS的VM Import/Export服务其实支持增量导入VMware镜像:
- 首次全量导入VMware VM到AWS生成AMI
- 后续增量备份VMware的变更数据,用AWS的增量导入工具(结合VMware的快照)直接生成新的AMI,AWS会自动处理系统适配和增量同步
- 你可以用AWS CLI的
import-image命令,指定--disk-containers中的SnapshotId为之前的快照,实现增量导入
这个方案完全不需要自己做系统修改,所有适配工作由AWS完成,而且增量效率很高。
内容的提问来源于stack exchange,提问作者Subbu

