克隆虚拟机

克隆会创建现有虚拟机的完整副本——包括其规格、磁盘和网络配置——并将其作为同一命名空间中的新虚拟机。ACP 通过 KubeVirt VirtualMachineClone(clone.kubevirt.io/v1beta1)资源实现此功能,该资源通过内部 snapshot → restore 异步执行复制。

这与克隆可启动卷(PVC 或 snapshot 数据源)不同:VM 克隆会复制整台机器,而可启动卷克隆只会复制磁盘镜像。

前提条件

  • 支持 snapshot 的存储。 由于克隆是通过内部 snapshot → restore 实现的,因此源虚拟机的磁盘必须位于支持 volume snapshot 的 StorageClass 上(该存储后端存在匹配的 VolumeSnapshotClass)。如果存储不支持 snapshot,克隆将失败——请检查 VirtualMachineClone 的 status.phase 和 status.conditions 以查看错误。完整的前提条件列表请参见 在 KubeVirt 上克隆虚拟机。

注意事项

  • 仅限同一命名空间。 VirtualMachineClone.spec.target 没有 namespace 字段,因此新虚拟机始终会在源对象所在的命名空间中创建。若要将虚拟机复制到其他命名空间,请改为导出后重新导入。
  • 新虚拟机是异步出现的。 提交克隆请求后会立即返回;目标对象会在 snapshot → restore 完成时创建(status.phase 会推进到 Succeeded)。
  • 克隆已停止的虚拟机最可靠,因为此时磁盘状态是静止的。
  • MAC 地址默认会重置,因此克隆后的虚拟机不会在网络上与源虚拟机冲突。
  • Kube-OVN 网络:克隆会始终过滤掉源对象的 ovn.kubernetes.io/* pod 注解,因此新虚拟机会请求一个新的 IP,而不会继承(并与之冲突)源 IP。
  • 权限:克隆操作受 clone.kubevirt.io API group 中 virtualmachineclones 的 create verb 约束。该 group 不属于标准的 Virtual Machines 功能权限,因此仅持有 Virtual Machines 角色的用户会看到 Clone 操作被禁用。平台管理员或命名空间管理员必须先授予一个额外的 role/binding,允许对 virtualmachineclones.clone.kubevirt.io 执行 create,该用户才能进行克隆。

克隆虚拟机

在源命名空间中创建一个 VirtualMachineClone 对象。下面的示例将 web-01 克隆为 web-01-clone,重置 MAC 地址(newMacAddresses: {}),并从 pod 模板中移除 Kube-OVN 注解,使克隆后的虚拟机获得新的 IP:

apiVersion: clone.kubevirt.io/v1beta1
kind: VirtualMachineClone
metadata:
  name: web-01-clone
  namespace: demo
spec:
  source:
    apiGroup: kubevirt.io
    kind: VirtualMachine
    name: web-01
  target:
    apiGroup: kubevirt.io
    kind: VirtualMachine
    name: web-01-clone
  # Keep all VM-level labels and annotations. Interface MAC addresses are
  # regenerated by default; set newMacAddresses to pin specific MACs instead.
  labelFilters: ["*"]
  annotationFilters: ["*"]
  # Kube-OVN: keep every pod-template annotation EXCEPT the source's
  # ovn.kubernetes.io/* address bindings, so the clone gets a fresh IP instead of
  # inheriting the source's. Clone filters are whitelist-based: a bare pattern
  # keeps the matching keys (everything else is dropped) and a "!" prefix
  # excludes — so the "*" entry is required (a lone "!ovn.kubernetes.io/*" would
  # whitelist nothing and strip ALL pod-template annotations).
  template:
    annotationFilters:
      - "*"
      - "!ovn.kubernetes.io/*"

应用后,观察克隆进度直到 Succeeded:

kubectl apply -f vmclone.yaml
kubectl get virtualmachineclone web-01-clone -n demo \
  -o jsonpath='{.status.phase}{"\n"}'

当 status.phase 为 Succeeded 时,新的虚拟机 web-01-clone 就会存在于 demo 命名空间中。status.restoreName 和 status.snapshotName 分别引用了操作过程中创建的中间 restore 和 snapshot 对象。

如果只想复制部分元数据,请设置顶层的 labelFilters / annotationFilters(它们过滤的是虚拟机对象自身的 labels/annotations;template.* 过滤的是pod 模板元数据):

spec:
  labelFilters:
    - "*"
    - "!some/transient-label"
  annotationFilters:
    - "*"

相关操作

当克隆达到 Running 状态后,你可以像管理其他虚拟机一样管理它——请参见 管理虚拟机。由于 MAC 地址(以及在 Kube-OVN 中的 IP)会被重新生成,如果来宾系统内部固定了地址,请确认新虚拟机的网络配置。