これまで、KubernetesにKuberVirtを導入し、仮想マシンを利用できるようにしました。
前回はKubeVirt VMにKubernetesのサービスを適用しました。
今回はKubeVirtのボリューム割り当てについて試しました。 いろいろな方法でボリュームのアタッチが可能ですが、今回はよく使うemptyDiskとPVCを使う方法を試してみます。
参考にした情報はKubeVirt User-Guide - Disks and Volumesです。
KubeVirt VMにemptyDiskを追加する
KubeVirtのemptyDiskは、KubernetesのemptyDirと同様に機能し、追加のqcow2ディスクが割り当てられてVMと同様に存続します。 ゲストVMの再起動時もボリュームは存続しますが、VMの再作成時は削除されます。
前回KubeVirtの動作確認に使ったYAMLファイルをベースに書いてみます。
# wget https://raw.githubusercontent.com/kubevirt/kubevirt.github.io/master/labs/manifests/vm.yaml
diffで差分を取ってみました。 meta data nameとkubevirt.io/domainの差分はVMにつけられる名前なので置いておいて、 domain deviceのemptydiskという名前のdiskを列挙し、volumesに2GBのemptyDiskを列挙する形で記述します。
$ diff -u vm.yaml vm1.yaml --- vm.yaml 2021-04-15 06:53:46.986242330 +0000 +++ vm1.yaml 2021-04-15 06:13:33.122816673 +0000 @@ -1,14 +1,14 @@ apiVersion: kubevirt.io/v1alpha3 kind: VirtualMachine metadata: - name: testvm + name: vm1 spec: running: false template: metadata: labels: kubevirt.io/size: small - kubevirt.io/domain: testvm + kubevirt.io/domain: vm1 spec: domain: devices: @@ -19,6 +19,9 @@ - name: cloudinitdisk disk: bus: virtio + - name: emptydisk + disk: + bus: virtio interfaces: - name: default bridge: {} @@ -35,3 +38,6 @@ - name: cloudinitdisk cloudInitNoCloud: userDataBase64: SGkuXG4= + - name: emptydisk + emptyDisk: + capacity: 2Gi
全体は次のようになります。
$ cat vm1.yaml apiVersion: kubevirt.io/v1alpha3 kind: VirtualMachine metadata: name: vm1 spec: running: false template: metadata: labels: kubevirt.io/size: small kubevirt.io/domain: vm1 spec: domain: devices: disks: - name: containerdisk disk: bus: virtio - name: cloudinitdisk disk: bus: virtio - name: emptydisk disk: bus: virtio interfaces: - name: default bridge: {} resources: requests: memory: 64M networks: - name: default pod: {} volumes: - name: containerdisk containerDisk: image: quay.io/kubevirt/cirros-container-disk-demo - name: cloudinitdisk cloudInitNoCloud: userDataBase64: SGkuXG4= - name: emptydisk emptyDisk: capacity: 2Gi
それではこのYAMLを使ってVMを作成してみます。
$ kubectl create -f vm1.yaml virtualmachine.kubevirt.io/vm1 created $ virtctl start vm1 VM vm1 was scheduled to start $ kubectl get vmi NAME AGE PHASE IP NODENAME vm1 10s Scheduling $ kubectl get vmi NAME AGE PHASE IP NODENAME vm1 15s Running 10.244.224.117 ml110gen9.maas
ログインしてデバイスが割り当てられた確認してみます。
Disk /dev/vdc
が追加したデバイスです。
$ virtctl console vm1 Successfully connected to vm1 console. The escape sequence is ^] login as 'cirros' user. default password: 'gocubsgo'. use 'sudo' for root. vm1 login: cirros Password: gocubsgo $ sudo fdisk -l ... Disk /dev/vda: 44 MiB, 46137344 bytes, 90112 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: gpt Disk identifier: 127BB530-4FDD-4855-B653-77C39F7AE9C4 Device Start End Sectors Size Type /dev/vda1 18432 90078 71647 35M Linux filesystem /dev/vda15 2048 18431 16384 8M EFI System Partition table entries are not in disk order. Disk /dev/vdb: 366 KiB, 374784 bytes, 732 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk /dev/vdc: 2 GiB, 2147483648 bytes, 4194304 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes
あとはこのデバイスをLinuxにおけるストレージの追加の方法でVMにマウントすればストレージ領域として使えます。
KubeVirt VMにPersistent Volume Claim(PVC)を追加する
次にPVCを使う方法です。VMの終了後にVirtualMachineInstanceのディスクを永続化する必要がある場合に使える方法です。 ただ、実際にデータが永続化されるかは、この永続ボリュームを提供しているストレージのポリシー次第になります。
StorageClass の ReclaimPolicyではPVC が削除された時にPVやPVCによって作成された物理的なストレージを保持する(Retain)か削除する(Delete)か選択できます。
次の例はDelete
が設定されているため、PVCを消すと物理的なデータも削除されます。
$ kubectl get sc NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE local-path rancher.io/local-path Delete WaitForFirstConsumer false 25h
早速、PVCボリュームをVMに割り当てる前に、まずはPVCを作ってみます。 PVCは次のように、KubernetesでPodに対して永続ボリュームを割り当てる際に使うものと同じ書き方でいけるようです。
$ cat testpvc1.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: testpvc1 spec: accessModes: - ReadWriteOnce storageClassName: local-path resources: requests: storage: 2Gi
あとは次の差分にあるように作成したPVCのmetadata nameをclaimNameに記述して、persistentVolumeClaimとして定義し、 domain deviceにdiskを追加するだけです。VMの名前は識別できるように一意の名前を定義します。
$ diff -u vm.yaml vm2.yaml --- vm.yaml 2021-04-15 06:53:46.986242330 +0000 +++ vm2.yaml 2021-04-15 06:06:16.711290998 +0000 @@ -1,14 +1,14 @@ apiVersion: kubevirt.io/v1alpha3 kind: VirtualMachine metadata: - name: testvm + name: vm2 spec: running: false template: metadata: labels: kubevirt.io/size: small - kubevirt.io/domain: testvm + kubevirt.io/domain: vm2 spec: domain: devices: @@ -19,6 +19,9 @@ - name: cloudinitdisk disk: bus: virtio + - name: testpvcdisk + disk: + bus: virtio interfaces: - name: default bridge: {} @@ -35,3 +38,6 @@ - name: cloudinitdisk cloudInitNoCloud: userDataBase64: SGkuXG4= + - name: testpvcdisk + persistentVolumeClaim: + claimName: testpvc1
前のemptyDiskの例と同様、ログインしてデバイスが割り当てられたか確認すると同様にVMにデバイスが追加されているはずです。
$ kubectl create -f vm2.yaml virtualmachine.kubevirt.io/vm2 created $ virtctl start vm2 $ kubectl get vmi -w NAME AGE PHASE IP NODENAME vm2 9s Scheduling vm2 14s Scheduled ml110gen9.maas vm2 18s Running 10.244.224.118 ml110gen9.maas $ virtctl console vm2 Successfully connected to vm2 console. The escape sequence is ^] ... $ sudo fdisk -l ... Disk /dev/vdc: 2 GiB, 2147483648 bytes, 4194304 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes
同様に、このデバイスをLinuxにおけるストレージの追加の方法でVMにマウントすればストレージ領域として使えます。
KubeVirt VMに追加したボリュームを利用してみる
KubeVirt VMに追加したボリュームにデータを書き込んで、データが永続的に使えることを確認してみましょう。
接続したデバイスを確認します。VMなのでvdをキーにgrepします。
$ fdisk -l |grep vd
パーティションを作成します。
$ sudo fdisk /dev/vdc Command (m for help): n
パーティションの作成方法についての詳細は省略します。以下を参考にパーティションを作成します。
パーティションとして/dev/vdc1
ができたことを確認します。
Command (m for help): p Disk /dev/vdc: 2 GiB, 2147483648 bytes, 4194304 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x0b9e402c Device Boot Start End Sectors Size Id Type /dev/vdc1 2048 4194303 4192256 2G 83 Linux
作成したパーティションにmke2fsやmkfsなどを使って、EXT4でボリュームをフォーマットします(フォーマットに使うツールはOSによって異なります)。
$ sudo mkfs.ext4 /dev/vdc1
マウントポイントを作成します。
$ mkdir ~/myvolume
ボリュームをシステムにマウントシアmす。
$ sudo mount /dev/vdc1 ~/myvolume
root権限でボリュームがマウントされるので、権限を修正します(ユーザー、グループはidコマンドなどで確認してから)。
$ sudo chown cirros.cirros ~/myvolume
マウントしたらデータの読み書きができるようになります。
$ touch ~/myvolume/hoge $ echo "hogehuga" > ~/myvolume/hoge $ cat ~/myvolume/hoge hogehuga
ボリュームの再利用を試す
ボリュームのマウントとデータの読み書きが可能であることを確認したら、次にこのボリュームの再利用を試してみます。 一度マウントを解除してみます。
$ cd $ sudo umount ~/myvolume
一度vm2を削除してVMを再作成してみます。
$ virtctl stop vm2 VM vm2 was scheduled to stop $ kubectl delete -f vm2.yaml --wait virtualmachine.kubevirt.io "vm2" deleted $ kubectl create -f vm2.yaml virtualmachine.kubevirt.io/vm2 created $ virtctl start vm2 VM vm2 was scheduled to start
ログインしてfdiskコマンドを実行すると、ファイルシステムが残っていることが確認できます。
$ virtctl console vm2 ... $ sudo fdisk -l ... Disk /dev/vdc: 2 GiB, 2147483648 bytes, 4194304 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x0b9e402c Device Boot Start End Sectors Size Id Type /dev/vdc1 2048 4194303 4192256 2G 83 Linux
マウントポイントを作成してボリュームをマウントしてみましょう。
$ mkdir ~/myvolume $ sudo mount /dev/vdc1 ~/myvolume $ sudo chown cirros.cirros ~/myvolume $ ls ~/myvolume hoge $ cat hoge hogehuga
別のVMでボリュームをマウントしても引き続きデータは利用できることが確認できました。