ESXi克隆虚拟机踩坑实录

开机报错、网络不通------ESXi 克隆虚拟机的那些坑我帮你踩完了

上周在实验室搭环境,需要快速复制一台 Oracle Linux 10 的虚拟机出来。原本以为三分钟的事,结果搞了快一个小时------开机报"在当前状况下不允许执行此操作",开机后网络全挂,克隆完发现两台虚拟机 MAC 地址一模一样......

踩了一圈坑之后,我把整个流程彻底捋清楚了。今天写下来,希望你能比我少花点时间。

先说清楚这是什么情况

很多人第一次在 ESXi 上克隆虚拟机,下意识会去找 Web 界面的"克隆"按钮。找了一圈才发现:免费版的 ESXi 没有这个功能,那是 vCenter 才有的能力。

但其实不买 vCenter 照样能克隆,而且一点都不复杂------SSH 连上去,几条命令搞定。核心工具就一个:vmkfstoolsESXi 自带的磁盘操作命令,专门用来做这种事。

我这次的场景:

  • 源虚拟机:oel10-192.168.26.13,已经装好了 Oracle Linux 10,配置好了基础环境
  • 目标:快速复制出一台 oel10-192.168.26.15,改个 IP 就能用
  • 存储路径:/vmfs/volumes/data

整个流程只有六步

第一步:先把源虚拟机关掉

这步不能省。虚拟机运行状态下直接复制文件,轻则数据不一致,重则克隆出来的系统启动就崩。

bash 复制代码
# 先查 VMID
vim-cmd vmsvc/getallvms | grep 26.13

# 关机,假设 VMID 是 1
vim-cmd vmsvc/power.off 1

# 确认已关机
vim-cmd vmsvc/get.state 1

当然,直接去 ESXi Web 界面右键关机也行,看你习惯。

第二步:建目录,把配置文件复制过去

bash 复制代码
cd /vmfs/volumes/data

# 建目标虚拟机的目录
mkdir oel10-192.168.26.15

# 复制配置文件(注意不是复制磁盘,磁盘要用专用命令)
cp oel10-192.168.26.13/oel10-192.168.26.13.vmx oel10-192.168.26.15/oel10-192.168.26.15.vmx
cp oel10-192.168.26.13/oel10-192.168.26.13.nvram oel10-192.168.26.15/oel10-192.168.26.15.nvram

这里复制的是 .vmx(虚拟机配置文件)和 .nvram(BIOS 固件存储)。磁盘文件要单独处理。

第三步:克隆磁盘------这步最慢,但最关键

不能直接 cp 复制 vmdk 文件。 直接 cp 会把磁盘的 UUID 也一并复制过去,两台虚拟机磁盘 UUID 相同,ESXi 会疯掉。必须用 vmkfstools

bash 复制代码
vmkfstools -i /vmfs/volumes/data/oel10-192.168.26.13/oel10-192.168.26.13.vmdk \
           /vmfs/volumes/data/oel10-192.168.26.15/oel10-192.168.26.15.vmdk \
           -d thin

-d thin 是精简置备,磁盘文件只占实际使用量,不会一下子把空间吃满。如果你需要厚置备(比如追求稳定的 I/O 性能),用 -d eagerzeroedthick

这一步耗时取决于磁盘大小,通常几十 GB 的盘大概需要几分钟到十几分钟,有进度条,等着就行。

第四步:改 vmx 配置------坑最集中的地方

这步是整个流程里最容易出问题的。很多人把文件复制完就直接注册虚拟机,然后就开始了一系列诡异报错。

克隆之后必须重新生成 UUID 和 MAC 地址,否则两台虚拟机会互相冲突。

bash 复制代码
cd /vmfs/volumes/data/oel10-192.168.26.15

# 把所有文件里的旧虚拟机名批量替换
sed -i 's/oel10-192.168.26.13/oel10-192.168.26.15/g' oel10-192.168.26.15.vmx

# 删掉旧的 UUID,重新生成
sed -i '/^uuid.bios/d' oel10-192.168.26.15.vmx
sed -i '/^uuid.location/d' oel10-192.168.26.15.vmx
echo "uuid.bios = \"$(uuidgen)\"" >> oel10-192.168.26.15.vmx
echo "uuid.location = \"$(uuidgen)\"" >> oel10-192.168.26.15.vmx

# 删掉旧的 MAC 地址,让 ESXi 开机时自动生成新的
sed -i '/ethernet0.generatedAddress/d' oel10-192.168.26.15.vmx
sed -i '/ethernet0.addressType/d' oel10-192.168.26.15.vmx
echo 'ethernet0.addressType = "generated"' >> oel10-192.168.26.15.vmx

改完之后验证一下,确认 displayName 和 uuid 都正确:

bash 复制代码
grep -E "displayName|uuid\.|ethernet0" oel10-192.168.26.15.vmx

第五步:注册虚拟机

bash 复制代码
vim-cmd solo/registervm /vmfs/volumes/data/oel10-192.168.26.15/oel10-192.168.26.15.vmx

执行成功后会返回一个数字,这是新虚拟机的 VMID,记下来后面要用。

bash 复制代码
[root@bogon:/vmfs/volumes/68d7222b-5832bf30-789b-d0946685487f/oel10-192.168.26.15] vim-cmd solo/registervm /vmfs/volumes/da
ta/oel10-192.168.26.15/oel10-192.168.26.15.vmx
55
[root@bogon:/vmfs/volumes/68d7222b-5832bf30-789b-d0946685487f/oel10-192.168.26.15] 

第六步:启动虚拟机

bash 复制代码
# 先确认主机不在维护模式(这是我踩的第一个坑)
esxcli system maintenanceMode get

# 如果返回 true,先退出维护模式
esxcli system maintenanceMode set --enable false

# 启动(VMID 换成上一步的返回值)
vim-cmd vmsvc/power.on <VMID>

开机后还有几步收尾

虚拟机起来了,但现在它和源机器除了 MAC 地址不同,其他配置都一样------主机名、IP、machine-id,这些都得改。

改主机名:

bash 复制代码
hostnamectl set-hostname oel10-192.168.26.15

改 IP 地址:

bash 复制代码
# 先看一下当前的连接名
nmcli connection show

# 修改 IP(连接名换成实际的,比如 ens34)
nmcli connection modify ens34 ipv4.addresses 192.168.26.15/22
nmcli connection modify ens34 ipv4.gateway 192.168.27.254
nmcli connection modify ens34 ipv4.dns "114.114.114.114"
nmcli connection up ens34

改 /etc/hosts:

bash 复制代码
sed -i 's/192.168.26.13/192.168.26.15/g' /etc/hosts

重新生成 machine-id,然后重启:

bash 复制代码
rm -f /etc/machine-id
dbus-uuidgen --ensure=/etc/machine-id
reboot

machine-id 这个很多人忽略。如果你的环境里有 DHCP、Kerberos 或者某些依赖 systemd 机器唯一性的服务,两台机器 machine-id 相同会出各种奇怪问题,最好养成习惯每次克隆都改掉。

嫌步骤多?有一键脚本

把上面所有步骤打包成一个脚本,改三个变量直接粘贴到 SSH 终端跑:

bash 复制代码
SRC_VM="oel10-192.168.26.13"
DST_VM="oel10-192.168.26.15"
DATASTORE="/vmfs/volumes/data"

# 关闭源虚拟机
SRC_ID=$(vim-cmd vmsvc/getallvms | grep "$SRC_VM" | awk '{print $1}')
echo "源 VMID: $SRC_ID"
vim-cmd vmsvc/power.off $SRC_ID
sleep 10

# 复制文件
mkdir -p $DATASTORE/$DST_VM
cp $DATASTORE/$SRC_VM/$SRC_VM.vmx $DATASTORE/$DST_VM/$DST_VM.vmx
cp $DATASTORE/$SRC_VM/$SRC_VM.nvram $DATASTORE/$DST_VM/$DST_VM.nvram

# 克隆磁盘
vmkfstools -i $DATASTORE/$SRC_VM/$SRC_VM.vmdk $DATASTORE/$DST_VM/$DST_VM.vmdk -d thin

# 改 vmx
cd $DATASTORE/$DST_VM
sed -i "s/$SRC_VM/$DST_VM/g" $DST_VM.vmx
sed -i '/^uuid.bios/d' $DST_VM.vmx
sed -i '/^uuid.location/d' $DST_VM.vmx
echo "uuid.bios = \"$(uuidgen)\"" >> $DST_VM.vmx
echo "uuid.location = \"$(uuidgen)\"" >> $DST_VM.vmx
sed -i '/ethernet0.generatedAddress/d' $DST_VM.vmx
sed -i '/ethernet0.addressType/d' $DST_VM.vmx
echo 'ethernet0.addressType = "generated"' >> $DST_VM.vmx

# 注册并启动
NEW_ID=$(vim-cmd solo/registervm $DATASTORE/$DST_VM/$DST_VM.vmx)
echo "新 VMID: $NEW_ID"

esxcli system maintenanceMode set --enable false
vim-cmd vmsvc/power.on $NEW_ID
echo "完成,登录后记得改主机名和 IP"

脚本执行完,去虚拟机里改一下主机名和 IP 就行了。

踩过的那几个坑

坑1:开机报"在当前状况下不允许执行此操作"

大概率是主机在维护模式。执行这条退出来:

bash 复制代码
esxcli system maintenanceMode set --enable false

坑2:开机后网络完全不通

有两种可能。第一,vmx 里 MAC 地址没改干净------按照上面第四步重新检查一遍。第二,虚拟机内 IP 还是旧的------进系统用 nmcli 改掉。

检查方法:

bash 复制代码
# 在 ESXi 上看虚拟机的 MAC
vim-cmd vmsvc/get.guestinfo <VMID> | grep -i mac

# 在虚拟机内确认 IP
ip addr show

坑3:注册虚拟机失败

一般是路径写错了,或者文件没复制成功。检查一下:

bash 复制代码
ls -la /vmfs/volumes/data/oel10-192.168.26.15/

看看 vmx 和 vmdk 文件是不是都在。

小结

整个流程回顾一下:

  1. 关源虚拟机
  2. 建目录,复制 vmx 和 nvram
  3. vmkfstools 克隆磁盘
  4. 修改 vmx 里的 UUID 和 MAC 地址
  5. 注册虚拟机
  6. 退出维护模式,开机
  7. 进系统改主机名、IP、machine-id

绕过 vCenter,全程 SSH,不依赖任何付费功能。一个字:稳。

如果你也在折腾 ESXi 实验环境,或者遇到了其他奇怪的克隆问题,欢迎评论区聊聊------说不定你的坑我也踩过。

相关推荐
乘云数字DATABUFF4 天前
5分钟部署开源APM Databuff:OpenTelemetry全链路追踪入门实战
运维·后端
荣--6 天前
一键部署不是为了省时间 —— 它是把"买来的 PaaS"变成"自己的平台"的拐点
运维·zabbix·工程化·一键部署·平台化·边界设计
江华森6 天前
动手实战学 Docker — 从零到集群编排完全指南
运维
Avan_菜菜6 天前
FRP 内网穿透完整实战:从 HTTP 映射到 HTTPS 自签代理
运维·nginx·https
SelectDB7 天前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
XIAOHEZIcode9 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220709 天前
如何搭建本地yum源(上)
运维
大树8812 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠12 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质12 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务