
如果要我在所有虚拟化迁移里选一个最被高估的操作VMware到PVE的迁移一定排前三。网上教程要么让你导出OVF再倒腾一圈要么让你装一堆转换工具实际上绕来绕去都是多余动作。我自己在机房和家里折腾过几十台VMware虚拟机迁到PVE结论很直接真正绕不开的命令就两条一条把虚拟磁盘送进PVE一条让PVE建好虚拟机并把磁盘挂上去剩下的全是驱动和引导的收尾问题。这篇文章我会把两条命令的完整用法、vmdk文件的各种“坑”、Windows和Linux迁移后怎么避免蓝屏和emergency mode、以及导入后磁盘卷到哪里去找这些问题全部过一遍。无论你的源虚拟机是VMware Workstation还是ESXi只要最后能拿到一份完整的vmdk文件这套流程就能用。适合正好在规划迁移、或者被网上复杂教程劝退的朋友先把思路理清楚再动手操作会顺很多。1. 迁移前想清楚为什么两条命令就能完成迁移1.1 vmdk本质上就是个通用的磁盘镜像很多人一听“异构虚拟化迁移”就觉得天要塌了觉得VMware和PVE是两个世界的平台文件格式、驱动、分区表全都不一样。其实把问题拆到最底层虚拟机迁移搬的永远是一个东西磁盘里的数据。VMware的虚拟磁盘文件叫vmdkPVE底层用的QEMU/KVM而qemu-img这个工具原生就认识vmdk格式。换句话说vmdk就是一块硬盘的完整照片PVE要做的事情非常简单建一台新机器把这块硬盘插上去。只要插法对、驱动对系统根本不在乎自己是从VMware还是PVE启动的。真正会导致迁移失败的从来不是“格式不兼容”而是文件没拿全、磁盘控制器驱动缺失、引导顺序不对这三类问题。所以两条命令能完成迁移前提不是魔法而是PVE的qm命令本身就内置了从vmdk导入磁盘的能力不需要你再单独装任何转换软件。1.2 方案选型一步到位还是三段式围绕这个需求实际操作中有两条路可以走。第一条是“两条命令”方案适合PVE 7.2之后、尤其是8.x版本先用scp把vmdk文件传到PVE再用qm create一条命令同时完成建虚拟机和导入磁盘创建时直接把--boot order也带上严格来说就是两条命令收工。第二条是经典三段式方案用qm create建一台空虚拟机再用qm importdisk把vmdk导入成PVE自己的磁盘卷最后用qm set把磁盘挂上去并设置引导顺序这样分步操作的好处是过程透明、兼容老版本PVE排查问题也方便。两条命令方案是我现在的主力做法因为它真的省时间。但要提醒一点不管走哪条路目标存储选什么格式在动手前最好先定下来。PVE的local-lvm存储底层是LVM-thin导入时用raw格式最好性能和快照能力都拉满如果是local这类目录存储或者NFS共享目录用qcow2格式更合适一方面是占用空间小另一方面也方便直接拷贝备份。这个选择会直接影响qm importdisk时的-format参数后面我会单独展开。1.3 动手前需要准备的清单迁移虽然只有两条核心命令但准备工作不做扎实很容易做到一半卡住。我的习惯是在开始前把下面这些东西都确认好源虚拟机处于正常关机状态不是挂起、不是休眠。挂起状态的内存映像对迁移没有意义强行导出的磁盘可能处于不一致状态。PVE版本确认一下可以在Shell里执行pveversion查看。如果是7.x或8.x优先用两条命令方案如果版本很老就老老实实走三段式。规划好PVE上的VMID和虚拟机名比如102、103这种避免和现有虚拟机冲突。预留足够的存储空间。导入过程会把vmdk“洗”成raw或qcow2目标存储上的剩余空间最好大于vmdk的实际数据量宁可多留不要少留。准备好virtio-win驱动ISO尤其是要迁移Windows的话。网上搜virtio-win就能找到这个在Windows迁移后的驱动修复阶段非常重要。2. 迁移前准备把vmdk完整、正确地搞到手2.1 Workstation下的常见坑分割文件与快照如果你的源虚拟机是VMware Workstation创建的第一步不是急着拷贝文件而是先看一眼磁盘文件长什么样。Workstation默认会把大磁盘拆成多个2GB的分片文件你能看到一堆类似vm-disk-s001.vmdk、vm-disk-s002.vmdk这样的文件真正描述整个磁盘的descriptor文件是那个不带-数字后缀的vm-disk.vmdk体积很小只有几KB。这种分割状态的vmdk直接拷到PVE去导入不是不行但文件太多容易漏而且PVE的导入过程对于分割文件的支持并不稳定。我的建议是先在Workstation里把磁盘“合并”成单文件。做法很简单在虚拟机设置里把硬盘选项从“将虚拟磁盘存储为多个文件”改成“将虚拟磁盘存储为单个文件”或者用命令行的vmware-vdiskmanager工具执行vmware-vdiskmanager.exe -r vm-disk.vmdk -t 0 merged.vmdk完成后再拷贝。另外一个隐藏大坑是快照如果虚拟机有快照磁盘目录里会出现vm-disk-000001.vmdk这类增量文件这个状态下的vmdk不能直接用作迁移。建议先在Workstation里删除快照或者做一次磁盘整合等磁盘回到单层状态再继续。还有一点很容易被忽略虚拟机要正常关机而不是“挂起”。挂起时内存和磁盘状态是冻结在一起的直接拷贝vmdk导出的是一份“冻在一半”的磁盘可能在迁移后出现文件系统不一致。这个我在实际迁移中踩过后来凡是遇到怪异的启动失败第一反应都是先回源机确认关机方式。2.2 ESXi下的文件结构descriptor与flat如果源虚拟机在ESXi上事情会稍微复杂一点但原理是一样的。ESXi的数据存储里一个虚拟机的磁盘通常包含两个关键文件一个体积很小的vm-disk.vmdk描述符文件和一个体积庞大的vm-disk-flat.vmdk数据文件。很多人第一次去ESXi里拉文件看到几KB的vmdk就慌了以为文件没拷全其实这段小文件是“地图”真正的数据都在-flat文件里。要从ESXi把文件拉出来第一步先开启ESXi主机的SSH服务然后通过scp -r把整个虚拟机目录拷走这是最省心的方式因为descriptor和flat文件会一起被带出来不会漏。举个例子scp -r root192.168.1.10:/vmfs/volumes/datastore1/Win10 /var/lib/vz/template/iso/如果ESXi上这台虚拟机是精简置备磁盘文件本质上还是descriptor加数据文件的组合同样建议整个目录拷贝。拷贝完成后进入目录看一眼确认descriptor文件和数据文件都在同一层目录下不要分开存放否则导入时会因为找不到数据文件而失败。2.3 文件到达PVE后的“体检”vmdk文件传到PVE之后先别急着建虚拟机花一分钟做个体检能避免后续大量返工。我每次都会在PVE的Shell里执行两个命令file /var/lib/vz/template/iso/win10.vmdk qemu-img info /var/lib/vz/template/iso/win10.vmdkfile能看出来文件是不是vmdk格式qemu-img info会返回虚拟磁盘的大小和格式信息。如果qemu-img能正确读出类似virtual size: 100G、format: vmdk这样的内容说明文件完整、可以被PVE识别。如果报错提示无法打开最常见的原因是只拷贝了descriptor文件而没拷贝数据文件或者快照没整合文件根本不是一个完整的磁盘镜像。还有一种情况是qemu-img虽然能打开但导入过程不顺利这种情况我一般会绕一步用qemu-img把vmdk先转换成qcow2再导入qemu-img convert -f vmdk -O qcow2 win10.vmdk win10.qcow2转换这一步相当于把vmdk里可能的格式怪癖全部抹平qcow2是PVE完全自家的格式后续怎么折腾都稳。转换时间视磁盘大小而定但通常比你反复试错要快。3. 核心实操两条命令完成迁移3.1 命令一把vmdk送到PVE第一步要做的事很朴素把vmdk文件从源机器送到PVE主机上。文件放到/var/lib/vz/template/iso/只是一个约定俗成的临时中转位置放别的目录也行只要PVE的Shell能读到路径就行。从Windows机器上传直接在cmd或PowerShell里执行scp D:\vms\win10\win10.vmdk root192.168.2.100:/var/lib/vz/template/iso/从ESXi上拉取就在PVE的Shell里执行scp -r root192.168.1.10:/vmfs/volumes/datastore1/Win10 /var/lib/vz/template/iso/如果你的网络环境支持也可以用rsync替代scp断点续传和进度显示都会更好一点但PVE默认不一定装了rsync所以scp是最不依赖环境的方案。传输过程中注意看文件大小一个几十GB的vmdk传输时间取决于你的网络环境千兆局域网大概是几十秒到几分钟别一看到进度条不动就慌属于正常现象。3.2 命令二建机加导入一步到位文件就位后核心时刻就到了。在PVE的Shell里执行下面这条命令它会在建虚拟机的同一条命令里完成磁盘导入qm create 102 \ --name win10-mig \ --memory 4096 \ --cores 4 \ --sockets 1 \ --cpu host \ --machine q35 \ --bios seabios \ --net0 e1000e,bridgevmbr0 \ --sata0 local-lvm:0,import-from/var/lib/vz/template/iso/win10.vmdk \ --boot ordersata0我逐段解释一下。--memory和--cores按源机器的配置填--cpu host让虚拟机直接使用物理CPU特性性能和兼容性都比较理想。--machine q35配--bios seabios是PVE默认的组合兼容性好。--net0 e1000e这里选了Intel网卡型号是因为Windows系统自带e1000e驱动迁移后网络大概率直接通后面再换virtio也不迟。--sata0 local-lvm:0,import-from...是整个命令的灵魂local-lvm后面的0是容量占位符真正的大小会以导入文件为准PVE会自动把vmdk转换并导入到local-lvm存储里生成一个叫vm-102-disk-0的卷。--boot ordersata0确保虚拟机从这块导入的硬盘引导。命令执行后如果看到终端停在导入进度上说明正在干活耗时跟磁盘大小成正比。完成后你会惊讶地发现虚拟机建好了磁盘也挂上了直接去PVE的Web界面点启动就行。如果你是导入Linux虚拟机且确定系统内核较新、内置virtio驱动可以把命令里的磁盘和网卡都换成virtio性能和PVE的契合度更高qm create 103 \ --name debian-mig \ --memory 2048 \ --cores 2 \ --sockets 1 \ --cpu host \ --net0 virtio,bridgevmbr0 \ --scsihw virtio-scsi-pci \ --scsi0 local-lvm:0,import-from/var/lib/vz/template/iso/debian.vmdk \ --boot orderscsi0这里多了一个--scsihw virtio-scsi-pci意思是给虚拟机挂一个virtio-scsi控制器再把磁盘挂到scsi0上。现代Linux发行版的安装内核默认都编译了virtio相关模块所以这么干一般没问题。3.3 老版本PVE的Plan B三段式命令如果你用的PVE版本比较老或者执行上一条命令报“unknown parameter import-from”之类的错误那就走经典三段式。道理一样只是把“建机加导入”拆成三步走# 第一步创建一台空虚拟机 qm create 102 --name win10-mig --memory 4096 --cores 4 --cpu host \ --net0 e1000e,bridgevmbr0 # 第二步导入vmdk到目标存储 qm importdisk 102 /var/lib/vz/template/iso/win10.vmdk local-lvm -format raw # 第三步把导入的卷挂到SATA0上并设为启动盘 qm set 102 --sata0 local-lvm:vm-102-disk-0 --boot ordersata0qm importdisk执行完后会生成一个名为vm-102-disk-0的卷路径取决于目标存储。如果目标是local-lvm卷会出现在LVM逻辑卷里如果目标是目录存储则会生成一个qcow2或raw文件。第三步的qm set就是把这块卷正式挂到虚拟机的SATA0接口上同时设置引导顺序这一步千万别漏不然开机大概率找不到启动设备。如果源虚拟机有多块磁盘操作方式也是一样的第二块磁盘导入后挂到--sata1或者--scsi1上继续执行qm set即可。3.4 开机前的检查清单导入完成后不要着急点启动先在Web界面上把虚拟机的配置过一遍。重点看三个地方存储卷是否挂在正确的位置、引导顺序是否已经设置为导入的那块磁盘、以及显示方式是否正常。如果这台虚拟机原来用的是UEFI引导而你创建时用了seabios启动会卡住反过来也一样所以创建前确认一下源机器的固件类型PVE里对应参数是--bios seabios或者--bios ovmf。首次开机建议直接点开Web界面的控制台窗口实时盯着启动过程。如果看到GRUB菜单或者Windows启动动画说明迁移的核心已经成功了。要是卡在奇怪的界面看控制台的信息比反复重启要好得多很多新手问题就是在这一步浪费了大量时间。4. 驱动适配与启动细节迁移不蓝屏的关键4.1 Windows迁移后的7B蓝屏与解法Windows虚拟机迁到PVE后最常见的失败现场就是蓝屏错误代码一般是INACCESSIBLE_BOOT_DEVICE或者0x0000007B。原因很简单Windows在启动时要加载磁盘控制器的驱动原来VMware里用的控制器驱动在PVE里不存在Windows找不到能驱动硬盘的玩意直接蓝给你看。这也是我在命令里为什么默认用--sata0而不是--scsi0的原因。SATA控制器是Windows自带驱动的迁移后基本不需要额外处理就能直接启动。所以遇到蓝屏不要慌回到硬件配置里把磁盘总线改成SATA或者IDE多半就能起来了。等系统正常进入桌面后再下载virtio-win驱动ISO安装里面的驱动和guest agent然后关机去Web界面把磁盘总线从SATA改成SCSI重新开机Windows会自动识别virtio-scsi磁盘不会蓝屏。这个流程我用过很多次成功率很高。更极客一点的做法是迁移之前在VMware里就给Windows预装virtio驱动在VMware里给虚拟机挂载virtio-win ISO手动安装驱动再迁移。这样迁移后直接挂SCSI也能启动。但预装流程对新手来说容易漏装所以我自己日常更推荐SATA过渡这种钝刀子割肉的方式稳。4.2 Linux进emergency mode的处理Linux虚拟机迁移后如果启动卡在一个写着You are in emergency mode的界面原因和Windows蓝屏本质上是一样的内核的initramfs里没有包含virtio相关模块导致系统挂载不了根分区。不过解法比Windows更直接。改成SATA总线先进系统然后重新生成initramfs。Debian/Ubuntu系执行update-initramfs -uCentOS/RHEL系执行dracut --force执行完关机把总线改回SCSI再开机系统就能顺利在virtio磁盘上启动了。如果你不想来回切换总线也可以先在PVE里临时挂一个Live CD镜像进救援模式chroot进原系统重新生成initramfs但对新手来说切换SATA更简单直观我推荐后者。怎么判断要不要担心virtio问题迁移前在源Linux虚拟机里执行一下modinfo virtio_blk如果能返回模块信息说明内核支持virtio迁移后直接挂SCSI一般没问题如果提示找不到模块那还是老老实实先用SATA过渡。4.3 网卡与虚拟机附加配置磁盘驱动解决之后网卡是第二个要处理的硬件。Windows系统自带e1000e驱动所以迁移后保持e1000e网卡是最省事的Linux则可以直接用virtio网卡性能和直通效果都更好。如果你希望Windows也用上virtio网卡在virtio-win驱动安装时一并把NetKVM装上就行。迁移完成后记得修改PVE里的网络配置把网桥设为vmbr0再根据你要跑的服务配置好IP这一步属于PVE网络基本功不再赘述。还有一个收尾动作卸载VMware Tools。Windows环境下卸载“VMware Tools”Linux环境看情况卸载open-vm-tools。随后装上qemu-guest-agentPVE的Web控制台就能显示客户机IP、执行优雅关机等动作和原来VMware Tools的作用对等。Linux安装很简单apt install qemu-guest-agent或者yum install qemu-guest-agent装完在PVE虚拟机的选项里把“QEMU Agent”启用一下即可。5. 常见问题与排查实录5.1 启动异常自查表这类问题我整理成了一个速查表排查的时候先从表格里对号入座现象原因快速解法Windows蓝屏代码7B或INACCESSIBLE_BOOT_DEVICE磁盘控制器驱动缺失把磁盘总线改成SATA或IDE进系统装virtio驱动后改回SCSILinux卡在emergency modeinitramfs缺少virtio模块用SATA启动执行update-initramfs或dracut后改回virtio启动提示找不到启动设备引导顺序不对或BIOS模式不匹配检查qm config的boot order核对原机是UEFI还是BIOS开机黑屏无反应machine类型或bios不匹配尝试切换q35/i440fxseabios/ovmf网络不通网卡驱动或网桥配置问题先换e1000e保证能用再检查vmbr0和IP配置5.2 文件与导入失败自查表文件层面的问题比启动问题更靠前如果卡在导入阶段对照这张表现象原因快速解法qemu-img报无法打开文件vmdk不完整、缺数据文件、快照未整合检查目录文件Workstation删除快照或整合磁盘ESXi检查descriptor和flat文件是否齐全拷贝来的vmdk只有几KB这通常只是descriptor描述文件数据在-flat文件里两个文件必须放同一目录再导入import-from参数报错PVE版本过老改用qm create空机qm importdiskqm set三段式导入完成后磁盘空间不足目标存储剩余空间不够提前用du估算优先导入到local-lvmraw格式配合thin池不会立即占满拷文件时提示权限错误scp目标目录权限问题确认PVE用户对/var/lib/vz/template/iso有写权限或用root执行5.3 导入后的磁盘卷去哪了vm-102-disk-0存储位置很多人导完磁盘后在文件管理器里找不到vm-102-disk-0就开始怀疑是不是导丢了。不是丢了是你找的地方不对。导入到local-lvm存储时磁盘卷是LVM逻辑卷不是普通文件所在路径是/dev/pve/vm-102-disk-0要用lvs或者lvdisplay命令查看。导入到local这类目录存储时它才会以文件形式出现在/var/lib/vz/images/102/下面文件名类似vm-102-disk-0.qcow2。日常操作中我建议直接依赖PVE Web界面的“硬件”页面来管理磁盘它会明确显示卷被挂在哪个存储上不需要去底层路径折腾。如果你真的需要搬运或备份这个卷不要直接去拷/dev下的设备文件要用PVE的存储迁移或qemu-img convert这种正式渠道否则很容易搞出数据不一致。5.4 关于磁盘容量的那些事导入后你会在Web界面看到磁盘的虚拟容量和源机一致比如源机分配了100G导入后就是100G。但要注意虚拟容量不等于实际占用空间。local-lvm是thin池qcow2格式也会按需增长只要源vmdk里实际数据只有30G导入后PVE主机的物理占用就不会立刻变成100G不用担心。真正要留意的是逻辑容量确实有限制如果后续虚拟机磁盘要扩容在PVE里调整大小就行。如果你觉得虚拟容量太大想“缩小”磁盘这就比较复杂了需要先在虚拟机内部收缩分区和文件系统再处理磁盘尾部空间。我的建议是迁移阶段不要纠结这个先把服务跑起来后续再专门安排时间做数据精简。顺便提一句PVE里复制磁盘有专门的命令qm disk copy可以把某个虚拟机的磁盘复制到另一存储、另一种格式这在做备份和多副本部署时很实用但不要用它去直接处理未导入的vmdk文件。最后再分享一个我自己的习惯迁移前一定先把vmdk备份到另一个地方哪怕只是多拷贝一份到移动硬盘。原因很简单vmdk是源虚拟机的唯一“底牌”一旦在导入过程中误操作覆盖了哭都来不及。我见过太多人因为图省事跳过备份结果一个错误的qm命令把所有数据送走。另外如果你是第一次做PVE迁移强烈建议先用一台不重要的测试虚拟机完整走一遍流程熟悉了之后再对生产机器下手。我自己就是从一个小型软路由虚拟机练手开始的等流程跑顺了后面每台机器从拷贝到开机基本控制在十分钟以内。