KubeVirt 06:VM 的快照和克隆

KubeVirt 支持虚拟机快照和克隆,但是都依赖 Kubernetes 中 CSI 提供的功能。

快照

在做快照之前需要创建 VolumeSnapshot 资源,参考以下连接:

安装好 snapshot controller 和创建好 VolumeSnapshotClass 后,可以通过以下命令进行检查:

vagrant@master01:~$ kubectl get volumesnapshotclass
NAME                      DRIVER                       DELETIONPOLICY   AGE
csi-rbdplugin-snapclass   rook-ceph.rbd.csi.ceph.com   Delete           10s

启用快照的特性

同样的, KubeVirt 的快照功能也是需要手动开启的,可以直接编辑 kubevirt 进行开启:

vagrant@master01:~$ kubectl edit kubevirt kubevirt -n kubevirt

spec:
  certificateRotateStrategy: {}
  configuration:
    developerConfiguration:
      featureGates:
      - HotplugVolumes
      - Snapshot

创建快照

KubeVirt 支持对在线和离线的虚拟机创建快照。
对于在线的虚拟机创建快照需要 qemu agent guest 处于运行的状态,确保在拍摄快照的时候冻结文件系统,拍摄完成后解除冻结,如果虚拟机没有运行 qemu agent guest 将无法拍摄运行时的快照,只能关机拍摄快照。

查看虚拟机中的 qemu agent guest 的状态,只需查看 VM 中的 AgentConnected

vagrant@master01:~$ k describe vm fedora-vm -n cdi-test | grep -A 1 Agent
    Type:                  AgentConnected
  Created:                 true

使用以下资源定义为 cdi-test 命令空间中的 fedora-vm 创建快照:

apiVersion: snapshot.kubevirt.io/v1alpha1
kind: VirtualMachineSnapshot
metadata:
  name: snap-fedora-vm
spec:
  source:
    apiGroup: kubevirt.io
    kind: VirtualMachine
    name: fedora-vm

拍摄快照:

vagrant@master01:~$ kubectl get vmi -n cdi-test
NAME        AGE   PHASE     IP              NODENAME   READY
fedora-vm   40m   Running   10.244.241.93   master01   True
vagrant@master01:~$ kubectl -n cdi-test apply -f snap-fedora-vm.yaml 
virtualmachinesnapshot.snapshot.kubevirt.io/snap-fedora-vm created

vagrant@master01:~$ kubectl wait vmsnapshot snap-fedora-vm -n cdi-test --for condition=Ready
virtualmachinesnapshot.snapshot.kubevirt.io/snap-fedora-vm condition met

vagrant@master01:~$ kubectl get volumesnapshot -n cdi-test
NAME                                                                            READYTOUSE   SOURCEPVC                SOURCESNAPSHOTCONTENT   RESTORESIZE   SNAPSHOTCLASS             SNAPSHOTCONTENT                                    CREATIONTIME   AGE
vmsnapshot-3331182f-bd76-4f9b-9e93-c253322c1f49-volume-disk0                    true         fedora                                           5Gi           csi-rbdplugin-snapclass   snapcontent-77ea2f79-0411-4702-b343-1c93112a6142   17s            18s
vmsnapshot-3331182f-bd76-4f9b-9e93-c253322c1f49-volume-example-volume-hotplug   true         example-volume-hotplug                           10Gi          csi-rbdplugin-snapclass   snapcontent-62f50a95-6987-44bb-b248-74988a0c7b70   17s            18s

可以看到针对 fedora-vm 创建了两个快照,因为前面附加了一块磁盘。

恢复快照

在恢复快照之前,对 fedora-vm 进行内容的更改,方便恢复快照后进行对比:

vagrant@master01:~$ virtctl ssh -i .ssh/id_rsa fedora@fedora-vm.cdi-test
Last login: Sun Apr 28 10:41:35 2024 from 10.244.30.110

[fedora@fedora-vm ~]$ sudo -i
[root@fedora-vm ~]# echo test > /etc/test.txt

[root@fedora-vm ~]# parted /dev/sda mklabel msdos
Information: You may need to update /etc/fstab.

[root@fedora-vm ~]# parted /dev/sda mkpart primary xfs 2048s 100%
Information: You may need to update /etc/fstab.

[root@fedora-vm ~]# udevadm settle                                      

[root@fedora-vm ~]# lsblk /dev/sda
NAME   MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda      8:0    0  10G  0 disk 
└─sda1   8:1    0  10G  0 part 

首先需要将 VM 停止:

vagrant@master01:~$ virtctl stop fedora-vm -n cdi-test
VM fedora-vm was scheduled to stop

vagrant@master01:~$ kubectl get vm -n cdi-test
NAME        AGE   STATUS    READY
fedora-vm   24h   Stopped   False

然后使用以下资源定义进行还原快照:

apiVersion: snapshot.kubevirt.io/v1alpha1
kind: VirtualMachineRestore
metadata:
  name: restore-fedora-vm
spec:
  target:
    apiGroup: kubevirt.io
    kind: VirtualMachine
    name: fedora-vm
  virtualMachineSnapshotName: snap-fedora-vm

还原快照:

vagrant@master01:~$ kubectl -n cdi-test apply -f restore-fedora-vm.yaml 
virtualmachinerestore.snapshot.kubevirt.io/restore-fedora-vm created

vagrant@master01:~$ kubectl get virtualmachinerestore -n cdi-test
NAME                TARGETKIND       TARGETNAME   COMPLETE   RESTORETIME   ERROR
restore-fedora-vm   VirtualMachine   fedora-vm    true       41s

启动 VM 进行检查磁盘是否被还原:

vagrant@master01:~$ virtctl start fedora-vm -n cdi-test
VM fedora-vm was scheduled to start

vagrant@master01:~$ virtctl ssh -i .ssh/id_rsa fedora@fedora-vm.cdi-test
Last login: Sun Apr 28 10:41:35 2024 from 10.244.30.110
[fedora@fedora-vm ~]$ cat /etc/test.txt
cat: /etc/test.txt: No such file or directory
[fedora@fedora-vm ~]$ lsblk /dev/sda
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda    8:0    0  10G  0 disk

可以看到两块的磁盘的内容已经还原到了拍摄快照时候的内容。

克隆

在满足 Snapshot & Restore 后,就可以对虚拟机实现克隆了,如果不满足,参考前面的链接首先创建 VolumeSnapshotClass 。

通过创建 VirtualMachineClone CDR 资源来对虚拟机进行克隆:

kind: VirtualMachineClone
apiVersion: "clone.kubevirt.io/v1alpha1"
metadata:
  name: testclone

spec:
  # source & target definitions
  source:
    apiGroup: kubevirt.io
    kind: VirtualMachine
    name: fedora-vm
  target:
    apiGroup: kubevirt.io
    kind: VirtualMachine
    name: fedora-vm-clone

  # labels & annotations definitions
  labelFilters:
    - "*"
    - "!someKey/*"
  annotationFilters:
    - "anotherKey/*"

  # template labels & annotations definitions
  template:
    labelFilters:
      - "*"
      - "!someKey/*"
    annotationFilters:
      - "anotherKey/*"

  # other identity stripping specs:
  newMacAddresses:
    interfaceName: "00-11-22"
  newSMBiosSerial: "new-serial"

其中 labelFiltersannotationFilters 是筛选要 copy 的标签和注释。
template 一些网络 CNI 会将网络信息注入到 template.labeltemplate.annotation 中,此处也是筛选要 copy 的标签和注释。
newMacAddresses 是在克隆时为特定的网卡设置新的 Mac Addresses。
newSMBiosSerial 也是一样克隆时生成新的 SMBios Serial。

克隆虚拟机:

vagrant@master01:~$ cat testclone.yaml 
kind: VirtualMachineClone
apiVersion: "clone.kubevirt.io/v1alpha1"
metadata:
  name: testclone

spec:
  # source & target definitions
  source:
    apiGroup: kubevirt.io
    kind: VirtualMachine
    name: fedora-vm
  target:
    apiGroup: kubevirt.io
    kind: VirtualMachine
    name: fedora-vm-clone

  # labels & annotations definitions
  labelFilters:
    - "*"
  annotationFilters:
    - "*"

  # template labels & annotations definitions
  template:
    labelFilters:
      - "*"
    annotationFilters:
      - "*"

vagrant@master01:~$ kubectl -n cdi-test apply -f testclone.yaml 
virtualmachineclone.clone.kubevirt.io/testclone created

验证克隆的虚拟机:

vagrant@master01:~$ kubectl get virtualmachineclone -n cdi-test
NAME        PHASE       SOURCEVIRTUALMACHINE   TARGETVIRTUALMACHINE
testclone   Succeeded   fedora-vm              fedora-vm-clone

vagrant@master01:~$ kubectl get vm -n cdi-test
NAME              AGE   STATUS    READY
fedora-vm         25h   Running   True
fedora-vm-clone   51s   Stopped   False

vagrant@master01:~$ virtctl start fedora-vm-clone -n cdi-test
VM fedora-vm-clone was scheduled to start

vagrant@master01:~$ virtctl ssh -i .ssh/id_rsa fedora@fedora-vm-clone.cdi-test
The authenticity of host 'vmi/fedora-vm-clone.cdi-test:22 (192.168.121.1:7890)' can't be established.
ECDSA key fingerprint is SHA256:xyti2s597SmKOZ+m4Jalsgi5CdW65CvlzjgvasU/v6s.
Are you sure you want to continue connecting (yes/no)? yes
Last login: Mon Apr 29 06:43:51 2024 from 10.244.30.66
[fedora@fedora-vm-clone ~]$ 
[fedora@fedora-vm-clone ~]$ hostnamectl status
 Static hostname: fedora-vm-clone
       Icon name: computer-vm
         Chassis: vm 🖴
      Machine ID: bb0bebea15a455d18a61c5e10c294b1d
         Boot ID: 68efaf1d0f2149a8811ed34e7e6909df
  Virtualization: qemu
Operating System: Fedora Linux 37 (Cloud Edition) 
     CPE OS Name: cpe:/o:fedoraproject:fedora:37
          Kernel: Linux 6.0.7-301.fc37.x86_64
    Architecture: x86-64
 Hardware Vendor: KubeVirt
  Hardware Model: None
Firmware Version: 1.16.1-1.el9

虚拟机封装

当从官网下载构建好的虚拟机后,在企业中针对每个虚拟机还要做好安全基线,监控等任务,如果每个虚拟机都手动一遍一遍从头操作的话,效率很低下,比较好的方法是制作虚拟机的模板,然后基于模板创建虚拟机。

基于现有的虚拟机做模板首先需要对虚拟机进行封装(sysprep),封装的过程会清楚主机特有的信息。

先假设对默认的虚拟机做设置:

vagrant@master01:~$ virtctl ssh -i .ssh/id_rsa root@centos9s-vm.vm-clone
The authenticity of host 'vmi/centos9s-vm.vm-clone:22 (192.168.121.168:6443)' can't be established.
ECDSA key fingerprint is SHA256:rMimCVGTHp59dJFFJRfEs8ItM67IsmuR4CCOyq1zCFg.
Are you sure you want to continue connecting (yes/no)? yes
Activate the web console with: systemctl enable --now cockpit.socket

[root@centos9s-vm ~]# echo "CentOS Stream 9 Template" > /etc/motd

在对虚拟机封装之前,首先要停止虚拟机:

vagrant@master01:~$ virtctl stop centos9s-vm -n vm-clone
VM centos9s-vm was scheduled to stop

vagrant@master01:~$ kubectl get vm -n vm-clone
NAME          AGE     STATUS    READY
centos9s-vm   9m14s   Stopped   False

使用 virtctl guestfs 对虚拟机使用的 PVC 进行挂载:

vagrant@master01:~$ virtctl guestfs centos9s -n vm-clone
Use image: quay.io/kubevirt/libguestfs-tools:v1.2.0 
The PVC has been mounted at /dev/vda 

Waiting for container libguestfs still in pending, reason: ContainerCreating, message:  
If you don't see a command prompt, try pressing enter.
bash-5.1$

此时 PVC 已经挂载到了 /dev/vda ,接下来对 vda 进行封装:

bash-5.1$ virt-sysprep -a /dev/vda
[   0.0] Examining the guest ...
[   6.5] Performing "abrt-data" ...
[   6.6] Performing "backup-files" ...
[   7.6] Performing "bash-history" ...
[   7.6] Performing "blkid-tab" ...
[   7.7] Performing "crash-data" ...
[   7.7] Performing "cron-spool" ...
[   7.7] Performing "dhcp-client-state" ...
[   7.7] Performing "dhcp-server-state" ...
[   7.7] Performing "dovecot-data" ...
[   7.8] Performing "ipa-client" ...
[   7.8] Performing "kerberos-hostkeytab" ...
[   7.8] Performing "logfiles" ...
[   7.9] Performing "lvm-system-devices" ...
[   7.9] Performing "machine-id" ...
[   8.0] Performing "mail-spool" ...
[   8.0] Performing "net-hostname" ...
[   8.0] Performing "net-hwaddr" ...
[   8.1] Performing "net-nmconn" ...
[   8.1] Performing "pacct-log" ...
[   8.1] Performing "package-manager-cache" ...
[   8.2] Performing "pam-data" ...
[   8.2] Performing "passwd-backups" ...
[   8.2] Performing "puppet-data-log" ...
[   8.2] Performing "rh-subscription-manager" ...
[   8.2] Performing "rhn-systemid" ...
[   8.3] Performing "rpm-db" ...
[   8.3] Performing "samba-db-log" ...
[   8.3] Performing "script" ...
[   8.3] Performing "smolt-uuid" ...
[   8.3] Performing "ssh-hostkeys" ...
[   8.3] Performing "ssh-userdir" ...
[   8.4] Performing "sssd-db-log" ...
[   8.4] Performing "tmp-files" ...
[   8.4] Performing "udev-persistent-net" ...
[   8.4] Performing "utmp" ...
[   8.4] Performing "yum-uuid" ...
[   8.4] Performing "customize" ...
[   8.4] Setting a random seed
[   8.5] Setting the machine ID in /etc/machine-id
[   8.5] SELinux relabelling
[  27.8] Performing "lvm-uuids" ...

执行完毕后 exit 退出即可,此时不要启动 VM,否则又会生成主机特有信息。

如果虚拟机使用的文件系统是 Btrfs ,将会遇到错误(所以我使用了 CentOS9Stream 作为测试):

bash-5.1$ virt-sysprep -a /dev/vda
[   0.0] Examining the guest ...
virt-sysprep: error: libguestfs error: inspect_os: mount exited with status 
32: mount: /tmp/btrfse339EF: unknown filesystem type 'btrfs'.

If reporting bugs, run virt-sysprep with debugging enabled and include the 
complete output:

  virt-sysprep -v -x [...]

通过使用 DataVolume 对虚拟机的根盘的克隆:

apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
  name: "centos9s-template"
spec:
  storage:
    resources:
      requests:
        storage: 30Gi
  source:
    pvc:
      name: centos9s
      namespace: vm-clone

应用:

vagrant@master01:~$ kubectl -n vm-clone apply -f dv_template.yaml
datavolume.cdi.kubevirt.io/centos9s-template created
vagrant@master01:~$ 
vagrant@master01:~$ kubectl get dv -n vm-clone
NAME                PHASE       PROGRESS   RESTARTS   AGE
centos9s            Succeeded   100.0%                3h34m
centos9s-template   Succeeded   100.0%                9s

后续可以基于 centos9s-template 再做克隆卷,然后用于虚拟机。

vagrant@master01:~$ kubectl get dv -n vm-clone
NAME                    PHASE       PROGRESS   RESTARTS   AGE
centos9s                Succeeded   100.0%                3h37m
centos9s-template       Succeeded   100.0%                3m18s
centos9s-template-vm1   Succeeded   100.0%                23s

基于 centos9s-template 创建了 centos9s-template-vm1 ,然后将 centos-template-vm1 用于 centos9s-template-vm1 虚拟机(此处仅仅是快速演示,最佳实践是创建 Virtual Machine Template 这个需要基于 OpenShift 的 Template 资源):

vagrant@master01:~$ kubectl get vm -n vm-clone
NAME                    AGE   STATUS    READY
centos9s-template-vm1   13s   Running   True
centos9s-vm             22m   Stopped   False

vagrant@master01:~$ virtctl ssh -i .ssh/id_rsa root@centos9s-template-vm1.vm-clone
The authenticity of host 'vmi/centos9s-template-vm1.vm-clone:22 (192.168.121.168:6443)' can't be established.
ECDSA key fingerprint is SHA256:l+naPMcmcDr+zslu4Uqakpuxq9Mbfa1XwzbmObYkPRs.
Are you sure you want to continue connecting (yes/no)? yes
CentOS Stream 9 Template
Activate the web console with: systemctl enable --now cockpit.socket

可以看到之前写入 motd 的内容了。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

滚动至顶部