Guided Exercise: Use CDI to Manage VM Disk Images

Check Default Storage Class

Before we can install the Containerized Data Importer (CDI), we have a prerequisite. CDI requires PVCs, so we need a supported (and default) storage class and provisioner. Setting this up is beyond the scope of this lesson, but at least in a sandbox environment like a Minikube or Kind deployment, there is a working local storage class available. Here is an example from a Kind node (using our Killercoda CDI lesson):

 

kubectl get storageclass

NAME                   PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
local-path (default)   rancher.io/local-path   Delete          WaitForFirstConsumer   false                  6m4s

Install CDI

Much as we did with the Installing KubeVirt exercise above, we first gather the most recent CDI version into an environment variable.

export VERSION=$(curl -Ls https://github.com/kubevirt/containerized-data-importer/releases/latest | grep -m 1 -o "v[0-9]\.[0-9]*\.[0-9]*")

echo $VERSION

kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/$VERSION/cdi-operator.yaml

 

Create a CDI Custom Resource to trigger the operator's deployment of CDI:

kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/$VERSION/cdi-cr.yaml

 

Check the status of the CDI deployment. It may take some time before the cdi resource's  "PHASE" reads "Deployed"

kubectl get cdi -n cdi

NAME   AGE    PHASE
cdi    3m     Deployed

Create a DataVolume

Here is the Cirros DataVolume from before:

kubectl create -f - <<EOF
apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
  name: "cirros"
spec:
  source:
    http:
      url: "https://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img" # S3 or GCS
  pvc:
    accessModes:
    - ReadWriteOnce
    resources:
      requests:
        storage: "64Mi"
EOF

datavolume.cdi.kubevirt.io/cirros created

Next, we check the status of the newly created DV:

kubectl get dv

NAME                PHASE                  PROGRESS   RESTARTS   AGE
cirros              WaitForFirstConsumer   N/A                   8s

As you can see here, the DV is waiting for a consumer to come along and request the PVC. This is because we are using a node local StorageClass, and the storage provider needs to know which node to import the DV into.

Create a VirtualMachine using the DataVolume

Let’s create a consumer for the DV from the previous step:

kubectl create -f - <<EOF
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  labels:
    kubevirt.io/os: linux
  name: vm1
spec:
  running: true
  template:
    metadata:
      creationTimestamp: null
      labels:
        kubevirt.io/domain: vm1
    spec:
      domain:
        cpu:
          cores: 1
        devices:
          disks:
          - disk:
              bus: virtio
            name: disk0
          - cdrom:
              bus: sata
              readonly: true
            name: cloudinitdisk
        resources:
          requests:
            memory: 128M
      volumes:
      - name: disk0
        persistentVolumeClaim:
          claimName: cirros
      - cloudInitNoCloud:
          userData: |
            #cloud-config
            hostname: vm1
            ssh_pwauth: True
            disable_root: false
            ssh_authorized_keys:
            - ssh-rsa YOUR_SSH_PUB_KEY_HERE
        name: cloudinitdisk
EOF

virtualmachine.kubevirt.io/vm1 created

We can watch the DV populating with kubectl get commands:

kubectl get dv,pvc,vm

NAME                                PHASE      PROGRESS   RESTARTS   AGE
datavolume.cdi.kubevirt.io/cirros   PVCBound   N/A                   32s

NAME                           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/cirros   Bound    pvc-428372e3-e7eb-47e5-8179-2a4e9bdaff92   64Mi       RWO            local-path     32s

NAME                             AGE   STATUS     READY
virtualmachine.kubevirt.io/vm1   10s   Starting   False

Then the DV goes through a few updates:

NAME                                PHASE             PROGRESS   RESTARTS   AGE
datavolume.cdi.kubevirt.io/cirros   ImportScheduled   N/A                   42s

Once the import starts, the PROGRESS field will show a percentage:

NAME                                PHASE              PROGRESS   RESTARTS   AGE
datavolume.cdi.kubevirt.io/cirros   ImportInProgress   11.90%                51s

Finally, when the import finishes, the DataVolume will be deleted and only the PVC will be left:

kubectl get dv,pvc,vm
NAME                           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/cirros   Bound    pvc-428372e3-e7eb-47e5-8179-2a4e9bdaff92   64Mi       RWO            local-path     2m44s

NAME                             AGE     STATUS    READY
virtualmachine.kubevirt.io/vm1   2m22s   Running   True