6.4. VM snapshot and restore

Snapshot and restore a virtual machine

KubeVirt provides a snapshot and restore functionality. This feature is only available if your storage driver supports VolumeSnapshots and a VolumeSnapshotClass is configured.

You can list the available VolumeSnapshotClass with:

kubectl get volumesnapshotclass --namespace lab-<username>
NAME                    DRIVER               DELETIONPOLICY   AGE
longhorn-snapshot-vsc   driver.longhorn.io   Delete           21d

You can snapshot virtual machines in running or stopped state. Using the QEMU guest agent the snapshot can temporarily freeze your VM to get a consistent backup.

Task 6.4.1: Prepare a virtual machine with a persistent disk

We want to snapshot a virtual machine with a persistent disk. We need to prepare our disk and virtual machine to be snapshotted.

Task 6.4.2: Prepare persistent disk

First, we need to create a persistent disk. We use a DataVolume which imports a container disk and saves it to a persistent volume. Create a file dv_lab06-cirros-disk.yaml in the folder labs/lab06 with the following specification:

apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
  name: lab06-cirros-disk
spec:
  source:
    registry:
      url: "docker://quay.io/kubevirt/cirros-container-disk-demo"
  pvc:
    accessModes:
      - ReadWriteOnce
    resources:
      requests:
        storage: 256Mi

Create the data volume with:

kubectl apply -f labs/lab06/dv_lab06-cirros-disk.yaml --namespace lab-<username>

Task 6.4.3: Create a virtual machine using the provisioned disk

Create a file vm_lab06-snapshot.yaml in the folder labs/lab06 for your virtual machine and add the following content:

apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: lab06-snapshot
spec:
  runStrategy: Halted
  template:
    metadata:
      labels:
        kubevirt.io/domain: lab06-snapshot
    spec:
      domain:
        devices:
          disks:
            - name: harddisk
              disk:
                bus: virtio
            - name: cloudinitdisk
              disk:
                bus: virtio
          interfaces:
            - name: default
              masquerade: {}
        resources:
          requests:
            memory: 64M
      networks:
        - name: default
          pod: {}
      volumes:
        - name: harddisk
          persistentVolumeClaim:
            claimName: lab06-cirros-disk
        - name: cloudinitdisk
          cloudInitNoCloud:
            userData: |
              #cloud-config              

Create the virtual machine with:

kubectl apply -f labs/lab06/vm_lab06-snapshot.yaml --namespace lab-<username>

Start your virtual machine with:

virtctl start lab06-snapshot --namespace lab-<username>

Task 6.4.4: Edit a file in your virtual machine

We now make a file change and validate if the change is persistent.

Enter the virtual machine with:

virtctl console lab06-snapshot --namespace lab-<username>

CirrOS’ login prompt always show the user and default password:

  ____               ____  ____
 / __/ __ ____ ____ / __ \/ __/
/ /__ / // __// __// /_/ /\ \ 
\___//_//_/  /_/   \____/___/ 
   http://cirros-cloud.net


login as 'cirros' user. default password: 'gocubsgo'. use 'sudo' for root.

Let’s get rid of this message and replace it with our own. Log in with the credentials and change our /etc/issue file:

sudo cp /etc/issue /etc/issue.orig
echo "Greetings from the KubeVirt Basics Training. This is a CirrOS virtual machine." | sudo tee /etc/issue

Check that the greeting is printed correctly by logging out:

exit
Greetings from the KubeVirt Basics Training. This is a CirrOS virtual machine.
lab06-snapshot login:

Log in again and restart the virtual machine to verify the change was persistent:

sudo reboot

After the restart completed, you should see your new message:

  ____               ____  ____
 / __/ __ ____ ____ / __ \/ __/
/ /__ / // __// __// /_/ /\ \ 
\___//_//_/  /_/   \____/___/ 
   http://cirros-cloud.net


Greetings from the KubeVirt Basics Training. This is a CirrOS virtual machine.

Task 6.4.5: Create a snapshot of the virtual machine

This is our configuration we want to save. We now create a snapshot of the virtual machine at this time.

Create a file vmsnapshot_lab06-snapshot-snap.yaml in the folder labs/lab06 with the following content:

apiVersion: snapshot.kubevirt.io/v1beta1
kind: VirtualMachineSnapshot
metadata:
  name: lab06-snapshot-snap
spec:
  source:
    apiGroup: kubevirt.io
    kind: VirtualMachine
    name: lab06-snapshot

Start the snapshot process by creating the VirtualMachineSnapshot resource:

kubectl apply -f labs/lab06/vmsnapshot_lab06-snapshot-snap.yaml

Make sure you wait until the snapshot is ready. You can issue the following command to wait for that to happen:

kubectl wait vmsnapshot lab06-snapshot-snap --for condition=Ready

It should complete with:

virtualmachinesnapshot.snapshot.kubevirt.io/lab06-snapshot-snap condition met

You can list your snapshots with:

kubectl get virtualmachinesnapshot --namespace lab-<username>

The output should be similar to:

NAME                  SOURCEKIND       SOURCENAME       PHASE       READYTOUSE   CREATIONTIME   ERROR
lab06-snapshot-snap   VirtualMachine   lab06-snapshot   Succeeded   true         102s 

You can describe the resource and have a look at the status of the VirtualMachineSnapshot and its subresource VirtualMachineSnapshotContent.

kubectl describe virtualmachinesnapshot --namespace lab-<username>
kubectl describe virtualmachinesnapshotcontent --namespace lab-<username>
apiVersion: snapshot.kubevirt.io/v1beta1
kind: VirtualMachineSnapshot
metadata:
  [...]
  name: lab06-snapshot-snap
status:
  [...]
  creationTime: "2024-09-05T08:34:31Z"
  indications:
    - Online
    - NoGuestAgent
  phase: Succeeded
  readyToUse: true
  snapshotVolumes:
    excludedVolumes:
      - cloudinitdisk
    includedVolumes:
      - harddisk
  [...]

In the status of the VirtualMachineSnapshot description, you may find information what volumes reside in the snapshot.

  • status.indications: Information how the snapshot was made
    • Online: Indicates that the VM was running during snapshot creation
    • GuestAgent Indicates that the QEMU guest agent was running during snapshot creation
    • NoGuestAgent Indicates that the QEMU guest agent was not running during snapshot creation or the QEMU guest agent could not be used due to an error
  • status.snapshotVolumes: Information of which volumes are included

Snapshots also include your virtual machine metadata spec.template.metadata and the specification spec.template.spec.

Task 6.4.6: Changing our greeting message again

Enter the virtual machine with:

virtctl console lab06-snapshot --namespace lab-<username>

Change the greeting message again:

sudo cp /etc/issue /etc/issue.bak
echo "Hello" | sudo tee /etc/issue

Now restart the virtual machine and verify the change was persistent:

sudo reboot

After the restart completed, you should see your new Hello message.

In addition to the changed file containing the greeting message, add a label acend.ch/training: kubevirt to the VirtualMachine’s metadata lab06-snapshot. This will allow us to see what happens to the labels once we restore the previous snapshot.

You can do this by patching your virtual machine with:

kubectl patch virtualmachine lab06-snapshot --type='json' -p='[{"op": "add", "path": "/spec/template/metadata/labels/acend.ch~1training", "value":"kubevirt"}]' --namespace lab-<username>
virtualmachine.kubevirt.io/lab06-snapshot patched

Describe the virtual machine to check if the label is present:

kubectl describe virtualmachine lab06-snapshot --namespace lab-<username>
API Version:  kubevirt.io/v1
Kind:         VirtualMachine
Name:         lab06-snapshot
[...]
Spec:
  Running:  true
  Template:
    Metadata:
      Labels:
        acend.ch/training:   kubevirt
        kubevirt.io/domain:  lab06-snapshot
[...]

Task 6.4.7: Restoring a virtual machine

Before we restore the virtual machine from the snapshot, let us do a quick recap:

  1. We provisioned a CirrOS VM with an attached persistent volume
  2. We then changed the greeting Message to Greetings from the KubeVirt Basics Training. This is a CirrOS virtual machine.
  3. We created a snapshot from that volume
  4. We change the greeting Message to Hello and added a label acend.ch/training: kubevirt

Now we want to restore the snapshot from step 3. Make sure your virtual machine is stopped:

virtctl stop lab06-snapshot --namespace lab-<username>

Create the file vmsnapshot_lab06-snapshot-restore.yaml in the folder labs/lab06 with the following content:

apiVersion: snapshot.kubevirt.io/v1beta1
kind: VirtualMachineRestore
metadata:
  name: lab06-snapshot-restore
spec:
  target:
    apiGroup: kubevirt.io
    kind: VirtualMachine
    name: lab06-snapshot
  virtualMachineSnapshotName: lab06-snapshot-snap

Start the restore process by creating a VirtualMachineRestore resource:

kubectl apply -f labs/lab06/vmsnapshot_lab06-snapshot-restore.yaml --namespace lab-<username>

Make sure you wait until the restore is done. You can use the following command to wait until the restore is finished:

kubectl wait vmrestore lab06-snapshot-restore --for condition=Ready --namespace lab-<username>

It should complete with:

virtualmachinerestore.snapshot.kubevirt.io/lab06-snapshot-restore condition met

Task 6.4.8: Check the restored virtual machine

Start the virtual machine:

virtctl start lab06-snapshot --namespace lab-<username>

If the restore was successful the Hello greeting should be gone and we should see below message again. Open the console to check the greeting message:

virtctl console lab06-snapshot --namespace lab-<username>
  ____               ____  ____
 / __/ __ ____ ____ / __ \/ __/
/ /__ / // __// __// /_/ /\ \ 
\___//_//_/  /_/   \____/___/ 
   http://cirros-cloud.net


Greetings from the KubeVirt Basics Training. This is a CirrOS virtual machine.

What about the label on the virtual machine manifest? Describe the virtual machine and validate that it has been removed as well:

kubectl describe virtualmachine lab06-snapshot --namespace lab-<username>
API Version:  kubevirt.io/v1
Kind:         VirtualMachine
Name:         lab06-snapshot
[...]
Spec:
  Running:  true
  Template:
    Metadata:
      Labels:
        kubevirt.io/domain:  lab06-snapshot
[...]