KubeVirt + Astra Trident で Kuberentes上での仮想マシン利用 を 試してみる

# KubeVirt + Astra Trident で Kuberentes上での仮想マシン利用 を 試してみる
2023/07に KuveVirt の v1.0がリリースに関する[アナウンス](https://kubevirt.io/2023/KubeVirt-v1-has-landed.html)がされていました。 KubeVirtは Kubernetes基盤上で コンテナと仮想マシンの両方を 展開できる統合プラットフォームを提供します。

Kubernetes環境を検討しているなかで、簡単にコンテナ化できない既存の仮想マシンがある場合など、コンテナとVMを共存させたいような状況下での選択肢として 検討されることもあるのではないかと思います。 

KubeVirtでは仮想マシンディスク部分を永続ボリュームに保存して利用できますので、KubeVirt + [Astra Trident](https://docs.netapp.com/ja-jp/netapp-solutions/containers/rh-os-n_overview_trident.html) の 組み合わせで この動作を試してみました。また、Astra TridentのClone機能を利用して 仮想マシンの複製も試してみたので その内容を紹介します。


## 前提
以下の環境で試しています

- KuveVirt v1.0.0-beta.0
- Kubernetes 1.26.5
- CentOS 7.7
- Astra Trident 23.04.0
- ONTAP 9.12.1

## やってみること
1. Astra Trident 導入
2. KuveVirt 導入
3. KuveVirt VM Disk作成
4. Astra TrindetのClone機能でKuveVirt VM Diskを複製


## 1. Astra Trident 導入
最初に Astra Tridentを導入します。

Astra Tridentの導入手順は [ドキュメントサイト](https://docs.netapp.com/us-en/trident/trident-get-started/kubernetes-deploy.html)で紹介されているので、その内容を参考に作業を実施します。


なお、今回は 既存のNFS用仮想ストレージ(SVM)を利用する前提での手順となります。
Astra Trident専用のSVMを用意したい場合は、[こちら](https://licensecounter.jp/devops-hub/blog/trident/)のサイトにその手順が紹介されていますので参考にしてください。


### 1-1. Astra Trident デプロイ
```shell:
$ helm repo add netapp-trident https://netapp.github.io/trident-helm-chart
$ helm install trident netapp-trident/trident-operator --version 23.04.0 --create-namespace --namespace trident --create-namespace
$ helm -n trident list
$ kubectl -n trident get pod -w
$ tridentctl version -n trident
+----------------+----------------+
| SERVER VERSION | CLIENT VERSION |
+----------------+----------------+
| 23.04.0        | 23.04.0        |
+----------------+----------------+

```
### 1-2. Backend登録

Astra TridentのPodの起動が完了したら Backendを登録します。

NFS用仮想ストレージの情報(username/password/SVM/LIF)は環境にあわせたものを指定します。

```shell:
$ cat <<EOF >> backend-tbc-ontap-nas-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: backend-tbc-ontap-nas-secret
type: Opaque
stringData:
  username: cluster-admin
  password: t@Ax@7q(>
EOF
$ kubectl -n trident apply -f backend-tbc-ontap-nas-secret.yaml
secret/backend-tbc-ontap-nas-secret created
$ cat <<EOF >> backend-tbc-ontap-nas.yaml
apiVersion: trident.netapp.io/v1
kind: TridentBackendConfig
metadata:
  name: backend-tbc-ontap-nas
spec:
  version: 1
  backendName: ontap-nas
  storageDriverName: ontap-nas
  managementLIF: 10.0.0.1
  dataLIF: 10.0.0.2
  svm: trident_svm
  credentials:
    name: backend-tbc-ontap-nas-secret
EOF
$ kubectl -n trident apply -f backend-tbc-ontap-nas.yaml
tridentbackendconfig.trident.netapp.io/backend-tbc-ontap-nas created
$ kubectl -n trident get tbc backend-tbc-ontap-nas
NAME                    BACKEND NAME           BACKEND UUID                           PHASE   STATUS
backend-tbc-ontap-nas   backend-tbc-ontap-nas  6a900a51-7f68-4a78-af9f-fee03e512e5b   Bound   Success

```
### 1-3. Storage Class作成
Storage Classを作成します。

```shell:
$ cat <<EOF >> sc-ontap-nas.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ontap-nas
provisioner: netapp.io/trident
parameters:
  backendType: "ontap-nas"
EOF
$ kubectl apply -f sc-ontap-nas.yaml
$ kubectl get sc

```


これで作成したAstra Tridentの導入が完了し、storage classを利用してPVCを利用する準備ができました。


## 2. KuveVirt 導入
KuveVirtを導入します。
あわせて、仮想マシン操に利用するために virtctl も導入します。

インストール方法は [KuveVirtのサイト](!https://kubevirt.io/quickstart_cloud/)で紹介されているのでそれに従って実施します。

### 1-1. KuveVirt 導入
KubeVirtを導入します。

```shell:
$ export VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases | grep tag_name | grep -v -- '-rc' | sort -r | head -1 | awk -F': ' '{print $2}' | sed 's/,//' | xargs)
$ echo $VERSION
$ kubectl create -f https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-operator.yaml
namespace/kubevirt created
customresourcedefinition.apiextensions.k8s.io/kubevirts.kubevirt.io created
priorityclass.scheduling.k8s.io/kubevirt-cluster-critical created
clusterrole.rbac.authorization.k8s.io/kubevirt.io:operator created
serviceaccount/kubevirt-operator created
role.rbac.authorization.k8s.io/kubevirt-operator created
rolebinding.rbac.authorization.k8s.io/kubevirt-operator-rolebinding created
clusterrole.rbac.authorization.k8s.io/kubevirt-operator created
clusterrolebinding.rbac.authorization.k8s.io/kubevirt-operator created
deployment.apps/virt-operator created
$  kubectl create -f https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-cr.yaml
kubevirt.kubevirt.io/kubevirt created
$ kubectl get kubevirt.kubevirt.io/kubevirt -n kubevirt 
NAME       AGE   PHASE
kubevirt   78s   Deployed
$ kubectl get pod -n kubevirt 
$ kubectl get all -n kubevirt

```

ネストされた仮想環境上で検証する場合は、KubeVirt エミュレーションを有効にします。

```shell:
$ kubectl -n kubevirt patch kubevirt kubevirt --type=merge --patch '{"spec":{"configuration":{"developerConfiguration":{"useEmulation":true}}}}' 
$ kubectl -n kubevirt get kubevirt -o yaml |grep useEmulation
        useEmulation: true 

```



### 1-2. VirtCtl 導入
VirtCtlを導入します。

```shell:
$ VERSION=$(kubectl get kubevirt.kubevirt.io/kubevirt -n kubevirt -o=jsonpath="{.status.observedKubeVirtVersion}")
ARCH=$(uname -s | tr A-Z a-z)-$(uname -m | sed 's/x86_64/amd64/') || windows-amd64.exe
$ echo ${ARCH}
$ curl -L -o virtctl https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/virtctl-${VERSION}-${ARCH}
$ chmod +x virtctl
$ sudo install virtctl /usr/local/bin
$ which virtctl

```

## 3. KubeVirt VM Disk作成
[CDI](!https://kubevirt.io/labs/kubernetes/lab2.html) (Containerized Data Importer) を導入し、Persistent VolumeClaim (PVC)上に仮想マシンイメージをインポートして KubeVirt VM用の仮想マシンディスクを作成します。

CDI は、Kubevirt がディスク イメージを使用できるように、ディスク イメージを PVC に取得する仕組みを提供します。
CDI は、さまざまなソースから PVC にデータをインポートするプロセスを簡素化します。


仮想マシンディスクを作成するにはPVCを直接利用する方法があります。
CDI用のアノテーション付きのPVC が作成されると、CDIがそれを検出して CDIインポーター を 起動し アノテーション内で指定されたデータソースからディスクイメージを取得して PVに 書き込むことで、仮想マシンディスクを作成します。


また、カスタムリソース "Data Volumes"を利用することも可能で、よりKubeVirtと統合された使い方が可能なこちらの方式が推奨の方法となっています。
"Data Volumes"の詳細は[こちら](!https://github.com/kubevirt/containerized-data-importer)で紹介されています。

今回は仮想マシンディスクの作成について、上記の２パターンを試してみます。


### 3-1. CDI導入
最初にCDIを導入します。

```shell:
$ export VERSION=$(basename $(curl -s -w %{redirect_url} https://github.com/kubevirt/containerized-data-importer/releases/latest))
$ echo $VERSION
$ curl -O -s -L https://github.com/kubevirt/containerized-data-importer/releases/download/$VERSION/cdi-operator.yaml
$ curl -O -s -L https://github.com/kubevirt/containerized-data-importer/releases/download/$VERSION/cdi-cr.yaml
$ kubectl apply -f cdi-operator.yaml
namespace/cdi created
customresourcedefinition.apiextensions.k8s.io/cdis.cdi.kubevirt.io created
clusterrole.rbac.authorization.k8s.io/cdi-operator-cluster created
clusterrolebinding.rbac.authorization.k8s.io/cdi-operator created
serviceaccount/cdi-operator created
role.rbac.authorization.k8s.io/cdi-operator created
rolebinding.rbac.authorization.k8s.io/cdi-operator created
deployment.apps/cdi-operator created
$ kubectl apply -f cdi-cr.yaml
cdi.cdi.kubevirt.io/cdi created
$ kubectl -n cdi get pod -w
$ kubectl -n cdi get pod
NAME                               READY   STATUS    RESTARTS   AGE
cdi-apiserver-5d5697d844-hzk4f     1/1     Running   0          54s
cdi-deployment-88479d9db-xj4fs     1/1     Running   0          44s
cdi-operator-7c4fd45f8d-hjfmq      1/1     Running   0          79s
cdi-uploadproxy-75cd5f9dc6-84r5m   1/1     Running   0          38s

```
CDIのOperatorが展開され、複数のPodが起動していることが確認できます。
これでCDIの導入ができました。

### 3-2. 仮想マシンディスク作成
データのソースにubuntu OSイメージのURLを指定して仮想マシンディスクを作成します。

PVCを直接使用 / Data Volumes使用の２パターンを試します。

#### 3-2-1. 仮想マシンディスク作成 (PVC)
PVCを直接使用して、仮想マシンディスクを作成します。

```shell:
$ cat <<EOF >> 2-cdi-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: cdi-ubuntu-22.10
  labels:
    app: containerized-data-importer
  annotations:
    cdi.kubevirt.io/storage.import.endpoint: "https://cloud-images.ubuntu.com/kinetic/current/kinetic-server-cloudimg-amd64.img"
spec:
  storageClassName: ontap-nas
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 8Gi
EOF
$ kubectl apply -f 2-cdi-pvc.yaml
virtualmachine.kubevirt.io/vm01-ubuntu-22.10 created
$ kubectl get pvc
$ kubectl get pod -w
NAME                        READY   STATUS    RESTARTS   AGE
importer-cdi-ubuntu-22.10   0/1     Pending   0          0s
importer-cdi-ubuntu-22.10   0/1     Pending   0          0s
importer-cdi-ubuntu-22.10   0/1     ContainerCreating   0          0s
importer-cdi-ubuntu-22.10   0/1     ContainerCreating   0          8s
importer-cdi-ubuntu-22.10   1/1     Running             0          10s
$ kubectl logs -f importer-cdi-ubuntu-22.10 
I0830 23:25:29.273773       1 importer.go:103] Starting importer
I0830 23:25:29.274251       1 importer.go:168] begin import process
I0830 23:25:30.371996       1 data-processor.go:379] Calculating available size
I0830 23:25:30.372691       1 data-processor.go:391] Checking out file system volume size.
I0830 23:25:30.372886       1 data-processor.go:399] Request image size not empty.
I0830 23:25:30.372927       1 data-processor.go:404] Target size 8589672448.
I0830 23:25:30.432464       1 nbdkit.go:302] Waiting for nbdkit PID.
I0830 23:25:30.932737       1 nbdkit.go:323] nbdkit ready.
I0830 23:25:30.932767       1 data-processor.go:282] New phase: Convert
I0830 23:25:30.932781       1 data-processor.go:288] Validating image
I0830 23:25:33.404540       1 qemu.go:258] 0.00
I0830 23:26:55.753947       1 qemu.go:258] 1.00
I0830 23:28:10.056465       1 qemu.go:258] 2.00
I0830 23:29:20.150655       1 qemu.go:258] 3.00
 ・
 ・
 ・
$ kubectl get pod -w
NAME                        READY   STATUS    RESTARTS   AGE
importer-cdi-ubuntu-22.10   1/1     Running   0          119m
importer-cdi-ubuntu-22.10   0/1     Completed   0          124m
importer-cdi-ubuntu-22.10   0/1     Terminating   0          124m
importer-cdi-ubuntu-22.10   0/1     Terminating   0          124m
$ 
```
動作として、
マニフェスト上でannotationsに”cdi.kubevirt.io/storage.import.endpoint”が指定されたPVCが作成されたことが検出されて、"importer-cdi-ubuntu-22.10"という名前のPodが自動的に起動し、指定されているデータソース（今回はURL)の情報をもとに データを取得・書き込みを行います。Pod(importer-cdi-ubuntu-22.10)のログを確認することで、処理の進捗を確認できます。

処理が完了するとPod(importer-cdi-ubuntu-22.10)の方は 自動的に削除されます。


#### 3-2-2. 仮想マシンディスク作成 (Data Volumes)
"Data Volumes"を使用して、仮想マシンディスクを作成します。

こちらの方法では、Pod(importer-xxx)のログをみる以外にも、"Data Volumes"の情報から、作成中の進捗を確認することも可能です。

```shell:
$ cat <<EOF > dv_ubuntu.yaml
apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
  name: "dv-ubuntu"
spec:
  source:
    http:
      url: "https://cloud-images.ubuntu.com/kinetic/current/kinetic-server-cloudimg-amd64.img"
  pvc:
    storageClassName: ontap-nas
    accessModes:
      - ReadWriteOnce
    resources:
      requests:
        storage: 8Gi
EOF
$ kubectl apply -f dv_ubuntu.yaml
$ kubectl get pvc
NAME                                                 STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
cdi-ubuntu-22.10                                     Bound     pvc-e160583a-e5df-4ab4-91cf-6341d1bc5503   8Gi        RWO            ontap-nas      8m7s
dv-ubuntu                                            Pending                                                                        ontap-nas      32s
prime-a2089dea-6503-4d11-ae94-b0d1b522e71f-scratch   Bound     pvc-449db7df-0d3f-43a5-b82b-7b916f7b5ed1   8Gi        RWO            ontap-nas      2s
prime-a2089dea-6503-4d11-ae94-b0d1b522e71f           Bound     pvc-efa82ac3-367d-4d51-a58f-86760a4480c2   8Gi        RWO            ontap-nas      32s
$ kubectl get pod
importer-prime-a2089dea-6503-4d11-ae94-b0d1b522e71f   1/1     Running             0          23s
$ kubectl get datavolumes.cdi.kubevirt.io
NAME        PHASE              PROGRESS   RESTARTS   AGE
dv-ubuntu   ImportInProgress   N/A        1          2m46s
$ kubectl get datavolumes.cdi.kubevirt.io
NAME        PHASE              PROGRESS   RESTARTS   AGE
dv-ubuntu   ImportInProgress   10.03%                3m
$ kubectl logs importer-prime-a2089dea-6503-4d11-ae94-b0d1b522e71f  -f
I0904 01:33:23.025752       1 importer.go:103] Starting importer
I0904 01:33:23.026443       1 importer.go:172] begin import process
I0904 01:33:23.910232       1 data-processor.go:356] Calculating available size
I0904 01:33:23.910910       1 data-processor.go:368] Checking out file system volume size.
I0904 01:33:23.911098       1 data-processor.go:376] Request image size not empty.
I0904 01:33:23.911142       1 data-processor.go:381] Target size 8589672448.
I0904 01:33:23.968619       1 data-processor.go:255] New phase: TransferScratch
I0904 01:33:23.976437       1 util.go:194] Writing data...
I0904 01:35:51.674903       1 data-processor.go:255] New phase: Convert
I0904 01:35:51.674947       1 data-processor.go:261] Validating image
E0904 01:35:51.751663       1 prlimit.go:155] failed to kill the process; os: process already finished
I0904 01:35:51.752823       1 qemu.go:126] Running qemu-img with args: [convert -t writeback -p -O raw /scratch/tmpimage /data/disk.img]
I0904 01:35:51.757419       1 qemu.go:258] 0.00
I0904 01:35:51.897748       1 qemu.go:258] 1.00
I0904 01:35:51.924598       1 qemu.go:258] 2.00
I0904 01:35:52.014642       1 qemu.go:258] 3.00
I0904 01:35:52.195618       1 qemu.go:258] 4.00
I0904 01:35:52.297881       1 qemu.go:258] 5.03
 ・
 ・
 ・
I0904 01:36:28.066567       1 qemu.go:258] 96.92
I0904 01:36:28.138219       1 qemu.go:258] 98.03
I0904 01:36:28.268152       1 qemu.go:258] 99.13
E0904 01:36:33.772125       1 prlimit.go:155] failed to kill the process; os: process already finished
I0904 01:36:33.772160       1 data-processor.go:255] New phase: Resize
E0904 01:36:33.846208       1 prlimit.go:155] failed to kill the process; os: process already finished
W0904 01:36:33.846328       1 data-processor.go:338] Available space less than requested size, resizing image to available space 8117026816.
I0904 01:36:33.846343       1 data-processor.go:349] Expanding image size to: 8117026816
E0904 01:36:33.856876       1 prlimit.go:155] failed to kill the process; os: process already finished
I0904 01:36:33.856926       1 data-processor.go:261] Validating image
E0904 01:36:33.866560       1 prlimit.go:155] failed to kill the process; os: process already finished
I0904 01:36:33.867859       1 data-processor.go:255] New phase: Complete
I0904 01:36:33.867972       1 importer.go:216] Import Complete
$ kubectl get pod
No resources found in default namespace.
$ kubectl get pvc
 kubectl get pvc
NAME               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
cdi-ubuntu-22.10   Bound    pvc-e160583a-e5df-4ab4-91cf-6341d1bc5503   8Gi        RWO            ontap-nas      29m
dv-ubuntu          Bound    pvc-efa82ac3-367d-4d51-a58f-86760a4480c2   8Gi        RWO            ontap-nas      21m
$ kubectl get datavolumes.cdi.kubevirt.io
NAME        PHASE       PROGRESS   RESTARTS   AGE
dv-ubuntu   Succeeded   100.0%     1          39m
```
この方式では、仮想マシンディスク用PVC("dv-ubuntu") のStatusが、データの取得・書き込み処理が進んでいる間は "Pending"のままとなっていました。 データ取得・書き込み処理が完了後に PVCのStausが"Bound"になりました。 

これは [こちら](!https://github.com/kubevirt/containerized-data-importer/blob/main/doc/datavolumes.md)で紹介されている"Kubevirt integration"での動作を実装するための実装の一環なのかと思います。

Data Volumesリソースのステータスが成功（データ取得・書き込みが完了して仮想マシンディスク作成処理が完了)となるまで、仮想マシンディスクを利用する仮想マシンの実行をスケジュールしないように制御することが可能になる仕組みを実装しています。 これにより"作成中のPVCにアクセスしてVM起動に失敗する"といった事象の回避ができるため、VM作成＋仮想マシンディスク作成をまとめて実施するときの課題を解決してくれます。


### 3-3. VMを作成して利用してみる
先ほど作成した仮想マシンディスクを使用するVMを作成します。

今回は、3-2-1で作成したPVCを利用しています。
3-2-2の方を利用したい場合は "claimName: cdi-ubuntu-22.10"のところを”claimName: dv-ubuntu”に書き換えれば あとは同じ手順で利用できます。

#### 3-3-1. VM作成
```shell:
$ cat <<EOF >> vm.yaml
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  creationTimestamp: 2018-07-04T15:03:08Z
  generation: 1
  labels:
    kubevirt.io/os: linux
  name: vm01-ubuntu-22.10
spec:
  running: true
  template:
    metadata:
      creationTimestamp: null
      labels:
        kubevirt.io/domain: vm1
    spec:
      domain:
        cpu:
          cores: 2
        devices:
          disks:
          - disk:
              bus: virtio
            name: disk0
          - cdrom:
              bus: sata
              readonly: true
            name: cloudinitdisk
        machine:
          type: q35
        resources:
          requests:
            memory: 1024M
      volumes:
      - name: disk0
        persistentVolumeClaim:
          claimName: cdi-ubuntu-22.10
      - cloudInitNoCloud:
          userData: |
            #cloud-config
            hostname: vm1
            ssh_pwauth: True
            password: password
            chpasswd: { expire: False }
            disable_root: false
        name: cloudinitdisk
EOF
$ kubectl apply -f vm.yaml
$ kubectl get vms
NAME                AGE   STATUS     READY
vm01-ubuntu-22.10   26s   Running    True
$ virtctl console vm01-ubuntu-22.10
→ "ctrl+]"でコンソール画面から抜ける
```

virtctlコマンドでVMのコンソース画面にアクセスできます。

VM作成直後にアクセスすると ubuntuのブートプロセスのログが出力されて、最後にログインプロンプトが表示されます。
コンソール画面から抜けるには "ctrl+]"を入力します。

#### 3-3-2. VMアクセス

起動したVMにログイン(ID="ubuntu"/Password="password")して、データを作成します。

```shell:
$ virtctl console vm01-ubuntu-22.10
Successfully connected to vm01-ubuntu-22.10 console. The escape sequence is ^]

Login timed out after 60 seconds.

Ubuntu 22.10 vm1 ttyS0

vm1 login: ubuntu
Password:
Welcome to Ubuntu 22.10 (GNU/Linux 5.19.0-46-generic x86_64)

Last login: Thu Aug 31 00:45:24 UTC 2023 on ttyS0
ubuntu@vm1:~$ sudo useradd -m user01
ubuntu@vm1:~$ sudo passwd user01
New password:
Retype new password:
passwd: password updated successfully
ubuntu@vm1:~$ exit
logout

Ubuntu 22.10 vm1 ttyS0

vm1 login: user01
Password:
Welcome to Ubuntu 22.10 (GNU/Linux 5.19.0-46-generic x86_64)

Last login: Thu Aug 31 00:52:50 UTC 2023 on ttyS0
$ whoami
user01
$ echo "8/31 is vegetable day" >> vegetable.txt
$ ls
vegetable.txt
$ cat vegetable.txt
8/31 is vegetable day
$ exit
→ "ctrl+]"でコンソール画面から抜ける

```
VMにアクセスしてログインできることを確認できました。
また、確認用のデータとして、一般ユーザuser01を作成し、テキストファイルを生成しました。

#### 3-3-3. VM再作成・確認

VM削除 → 再作成をしてもデータが保持されていることを確認します。

VMを削除します。

```shell:
$ kubectl get vms
NAME                AGE   STATUS     READY
vm01-ubuntu-22.10   57m   Running    True
$ kubectl delete -f vm.yaml
virtualmachine.kubevirt.io "vm01-ubuntu-22.10" deleted
$ kubectl get vms
```
VMを再作成して 削除前に作成していたユーザ及びファイルが保持されていることを確認します。

```shell:
$ kubectl apply -f vm.yaml
virtualmachine.kubevirt.io/vm01-ubuntu-22.10 created
$ kubectl get vms
NAME                AGE   STATUS     READY
vm01-ubuntu-22.10   18s   Running    True
$ virtctl console vm01-ubuntu-22.10
Successfully connected to vm01-ubuntu-22.10 console. The escape sequence is ^]

vm1 login: user01
Password:
Welcome to Ubuntu 22.10 (GNU/Linux 5.19.0-46-generic x86_64)

Last login: Thu Aug 31 01:01:32 UTC 2023 on ttyS0
$ whoami
user01
$ ls
vegetable.txt
$ cat vegetable.txt
8/31 is vegetable day
$
$ exit
→ "ctrl+]"でコンソール画面から抜ける
```
確認用のデータとして3-3-2で準備した 一般ユーザuser01でログインでき 生成しておいたテキストファイルを参照できました。

永続ボリュームにデータが保存されているため、VM削除 → 再作成をしてもデータが保持されます。


## 4. Astra TrindetのClone機能でKuveVirt VM Diskを複製
同じ仮想マシンディスクを複数用意したい場合を想定して、Astra TridentのClone機能を利用して 複製してみます。



この機能はストレージのFlexClone機能と連動しますので 、複製自体の処理は数秒で完了し 素早く ２つ目のVMを起動させられます。


仮想マシンディスクを利用の都度新規に作成しようとすると非常に時間がかるケースがあります。ストレージ機能を活用することでこの処理時間を短縮することが可能なのでそれを試してみます。


```shell:
$ cat <<EOF >> 13-clone.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: clone01
  namespace: default
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: ontap-nas
  resources:
    requests:
      storage: 8Gi
  dataSource:
    name: cdi-ubuntu-22.10
    kind: PersistentVolumeClaim
EOF
$ kubectl apply -f 13-clone.yaml
persistentvolumeclaim/clone01 created
$ kubectl get pvc
NAME                 STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS        AGE
cdi-ubuntu-22.10     Bound    pvc-817bf360-e40b-4514-b7ac-4f91633330b0   8Gi        RWO            ontap-nas           32d
clone01              Bound    pvc-c729efce-bdd8-49c1-8332-821463efbdf6   8Gi        RWO            ontap-nas           11s
$ cat <<EOF >> 13-vm-clone.yaml
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  creationTimestamp: 2018-07-04T15:03:08Z
  generation: 1
  labels:
    kubevirt.io/os: linux
  name: vm-clone01
spec:
  running: true
  template:
    metadata:
      creationTimestamp: null
      labels:
        kubevirt.io/domain: vm1
    spec:
      domain:
        cpu:
          cores: 2
        devices:
          disks:
          - disk:
              bus: virtio
            name: disk0
          - cdrom:
              bus: sata
              readonly: true
            name: cloudinitdisk
        machine:
          type: q35
        resources:
          requests:
            memory: 1024M
      volumes:
      - name: disk0
        persistentVolumeClaim:
          claimName: clone01
      - cloudInitNoCloud:
          userData: |
            #cloud-config
            hostname: vm-clone01
            ssh_pwauth: True
            password: password
            chpasswd: { expire: False }
            disable_root: false
        name: cloudinitdisk
EOF
$ kubectl apply -f 13-vm-clone.yaml
virtualmachine.kubevirt.io/vm-clone01 created
$ kubectl get vms
$ virtctl console vm-clone01
Successfully connected to vm-clone01 console. The escape sequence is ^]

vm-clone01 login: user01
Password:
Welcome to Ubuntu 22.10 (GNU/Linux 5.19.0-46-generic x86_64)

Last login: Thu Aug 31 01:49:15 UTC 2023 on ttyS0
$ whoami
user01
$ ls
vegetable.txt
$ cat vegetable.txt
8/31 is vegetable day
$
```
複製したPVCを利用して、VMを起動して利用できることを確認できました。

仮想マシンディスクの作成を都度実施すると時間がかかるため、多数のVMを用意したい場合などに 有効な手段なのではないかと思います。

また、FlexCloneは複製元と複製先で共通するデータ部分について ストレージのデータブロックを共有するため スペース効率も期待できる機能です。仮想マシンを複数立てる場合に ストレージ容量の消費を軽減する効果も期待できるかと思います。



## まとめ
KuveVirt + NetApp Astra Tridentの組み合わせでの動作を試してみました。
CDIを利用して仮想マシンディスクを作成でき、Trident Clone機能を利用して簡単に 仮想マシンの複製を実施することができました。

CDIではVMware環境の仮想マシンをインポートする機能も提供されています。
例えば、コンテナへの全面切り替えが難しいような場合に 残ってしまう仮想マシンをKubeVirtの環境にインポートし、仮想基盤を残さないで Kubernetes基盤へ移行するなどの使い方もできるのではないかと思います。

また、Astra Tridentでは Snapshot機能や ストレージレプリケーション機能との連携などもできるので、KubeVirt上のVMのデータ保護や DRを構成することなどに それらの機能を活用すれば より運用要件高いシステムでKubeVirtを利用することも可能になっていくかと思います。
そういった機能を試してみるのも面白いのではないかと思います。