: O. Yuanying

kubevirt を試す

インストール

kubevirt 本体と cdi (containerized data importer) をインストール。

KUBEVIRT_VER := v0.57.1
curl -Lo kubevirt/operator.yaml https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VER}/kubevirt-operator.yaml
curl -Lo kubevirt/cr.yaml https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VER}/kubevirt-cr.yaml

CDI_VER := v1.55.0
curl -Lo cdi/operator.yaml https://github.com/kubevirt/containerized-data-importer/releases/download/${CDI_VER}/cdi-operator.yaml
curl -Lo cdi/cr.yaml https://github.com/kubevirt/containerized-data-importer/releases/download/${CDI_VER}/cdi-cr.yaml

kubectl apply -f kubevirt
kubectl apply -f cdi

kubevirt-cr.yamlcdi-cr.yaml はそれぞれ kubevirtcdi の実体?というかそれぞれの設定ファイル?っぽいものらしく、これらもデプロイしないと以降のステップがうまく動かなかった。

その他必要なツールのインストール

virtctl

kubevirt をいい感じに操作するためのCLIツール。krew でインストールする。

kubectl krew install virt

VM起動

起動するVMのディスクをどう用意するのかいくつか方法があるようだ。3通りほど試してみる。

  • VM起動 (1)
    • VMイメージを手元に置き、VM起動のたびVMイメージをアップロードする方法。
  • VM起動 (2)
    • VMイメージを適当なWebサーバに置き、それを参照する方法。
  • VM起動 (3)
    • VMイメージをPVCに置き、VM起動のたびPVC上のディスクデータをクローンして利用する方法。

VM起動 (1)

VMイメージを手元に置いて起動のたび VM イメージをアップロードして起動する方法。

VMイメージの用意

なんとなくUbuntuを使いたかったので、Exampleなどにあるfedoraではなく、適当なUbuntu 22.04のイメージをダウンロード。 ここで jammy-server-cloudimg-amd64-disk-kvm.img とかを選択すると起動しなかったりするので注意。

curl -LO https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img

kubectl virt image-upload コマンドを使って DataVolumes 形式でイメージをアップロード。 PVC として扱うよりいろいろ便利らしいが、まだ調べてないのでよくわからない。

kubectl virt -n staging image-upload dv jammy-01 \
    --size=10Gi \
    --uploadproxy-url=https://cdi-uploadproxy.cdi.svc.fraction.cluster \
    --insecure \
    --block-volume \
    --storage-class bronze \
    --access-mode ReadWriteOnce \
    --image-path=jammy-server-cloudimg-amd64.img

最終的にPVCにVMイメージを保存するので、デフォルトのStorageClassとかを指定してない場合は指定が必要。

--uploadproxy-url は、cdi をインストールしたときにデプロイされる VM イメージをアップロードするための proxy のアドレス。 コマンドを実行するワークスペースからアクセス可能なURLでなければならないのだけど、うちの環境は fraction.cluster と言うドメインを使うことで Service に直接アクセス可能なためこんな感じのURLに。

VMを起動するディスクを作成する方法はいくつかあるらしいが、手元からVMイメージをアップロードするこの方法が自宅クラスタでは簡便。

VM作成

以下のようにマニフェストを適用すると、VMが起動する。

cat <<EOF | k apply -f -
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  generation: 1
  labels:
    kubevirt.io/os: linux
  name: ubuntu-01
spec:
  running: true
  template:
    metadata:
      labels:
        kubevirt.io/domain: ubuntu-01
    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:
      - dataVolume:
          name: jammy-01
        name: disk0
      - cloudInitNoCloud:
          userData: |
            #cloud-config
            hostname: ubuntu-01
            ssh_pwauth: True
            disable_root: false
            ssh_authorized_keys:
            - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCS7YoDiqntTeWKAKCyfa8yylcMc3W7PN7wYEC1mkHEzDMVQzKSObVGiiIDfYfd50o37pptQ0PjAo2LaXTJLQseFfrwEZW8Jifv/8qDu75ef/jau9q3po7ReQebhQTNtgT2SQ1PTa5s0yEcbP1M1Eyp+lqj+TnYuLuqq5AG9UBizPCbO+dnvW8gRvZ0TuX+f2+DzbYkRnL/SHvQ9hxkO4X7mJslw6DIWQJHM4xFZBN6y+7nntpYwxy1S7kfx38S7I9OLVWP+4a39R6x5QVULLM/n1a+aR4R3KhiA/XVoJheTyJY/fe5qVJuFYcwJIxo4Vj51tyiQ8T8PPePgqIYATI5
        name: cloudinitdisk
EOF

VM起動 (2)

先述の jammy-server-cloudimg-amd64.img を適当なWebサーバに置く。

今回は https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img をそのまま指定する。

VM作成

以下のようにマニフェストを適用すると、VMが起動する。

cat <<EOF | k apply -f -
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  generation: 1
  labels:
    kubevirt.io/os: linux
  name: ubuntu-02
spec:
  dataVolumeTemplates:
  - metadata:
      name: jammy-02
    spec:
      pvc:
        accessModes:
        - ReadWriteOnce
        volumeMode: Block
        resources:
          requests:
            storage: 10Gi
        storageClassName: bronze
      source:
        http:
          url: https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
  running: true
  template:
    metadata:
      labels:
        kubevirt.io/domain: ubuntu-02
    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:
      - dataVolume:
          name: jammy-02
        name: disk0
      - cloudInitNoCloud:
          userData: |
            #cloud-config
            hostname: ubuntu-02
            ssh_pwauth: True
            disable_root: false
            ssh_authorized_keys:
            - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCS7YoDiqntTeWKAKCyfa8yylcMc3W7PN7wYEC1mkHEzDMVQzKSObVGiiIDfYfd50o37pptQ0PjAo2LaXTJLQseFfrwEZW8Jifv/8qDu75ef/jau9q3po7ReQebhQTNtgT2SQ1PTa5s0yEcbP1M1Eyp+lqj+TnYuLuqq5AG9UBizPCbO+dnvW8gRvZ0TuX+f2+DzbYkRnL/SHvQ9hxkO4X7mJslw6DIWQJHM4xFZBN6y+7nntpYwxy1S7kfx38S7I9OLVWP+4a39R6x5QVULLM/n1a+aR4R3KhiA/XVoJheTyJY/fe5qVJuFYcwJIxo4Vj51tyiQ8T8PPePgqIYATI5
        name: cloudinitdisk
EOF

VM起動 (3)

VMイメージをPVCに置き、VM起動のたびPVC上のディスクデータをクローンして利用する方法。

VMイメージの用意

まず、コピー元となる PVC を作成する。 DataVolumeを作れば勝手に作られる。この際、accessModeReadWriteMany にしておくとクローンする際に便利そうと思いきや、 このソースとなるPVCはVMイメージそのままじゃないとダメっぽそう。

kubectl virt -n staging image-upload dv jammy-03 \
    --size=3Gi \
    --uploadproxy-url=https://cdi-uploadproxy.cdi.svc.fraction.cluster \
    --insecure \
    --block-volume \
    --storage-class bronze \
    --access-mode ReadWriteOnce \
    --image-path=jammy-server-cloudimg-amd64.img

VM作成

先ほど作ったPVCをソースとして DataVolume を作成するように指定して VM を作成する。

cat <<EOF | k apply -f -
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  generation: 1
  labels:
    kubevirt.io/os: linux
  name: ubuntu-03
spec:
  dataVolumeTemplates:
  - metadata:
      name: jammy-03-clone
    spec:
      pvc:
        accessModes:
        - ReadWriteOnce
        volumeMode: Block
        resources:
          requests:
            storage: 10Gi
        storageClassName: bronze
      source:
        pvc:
          namespace: staging
          name: jammy-03
  running: true
  template:
    metadata:
      labels:
        kubevirt.io/domain: ubuntu-03
    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:
      - dataVolume:
          name: jammy-03-clone
        name: disk0
      - cloudInitNoCloud:
          userData: |
            #cloud-config
            hostname: ubuntu-03
            ssh_pwauth: True
            disable_root: false
            ssh_authorized_keys:
            - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCS7YoDiqntTeWKAKCyfa8yylcMc3W7PN7wYEC1mkHEzDMVQzKSObVGiiIDfYfd50o37pptQ0PjAo2LaXTJLQseFfrwEZW8Jifv/8qDu75ef/jau9q3po7ReQebhQTNtgT2SQ1PTa5s0yEcbP1M1Eyp+lqj+TnYuLuqq5AG9UBizPCbO+dnvW8gRvZ0TuX+f2+DzbYkRnL/SHvQ9hxkO4X7mJslw6DIWQJHM4xFZBN6y+7nntpYwxy1S7kfx38S7I9OLVWP+4a39R6x5QVULLM/n1a+aR4R3KhiA/XVoJheTyJY/fe5qVJuFYcwJIxo4Vj51tyiQ8T8PPePgqIYATI5
        name: cloudinitdisk
EOF

上記のマニフェストをデプロイすると、まずプロビジョニングのフェーズが始まり、PVCの内容をCDIにアップロードするPodが起動する。

➜ k get pod
NAME                                              READY   STATUS    RESTARTS   AGE
1ad4d7aa-055a-4aa3-9664-7ae90a6462ef-source-pod   1/1     Running   0          101s
cdi-upload-jammy-03-clone                         1/1     Running   0          2m6s

クローン元のPVCとクローン先のPVCを両方マウントしたPodが作られるのかなと思いきや、クローン元のPVCをマウントしたPodが作られ、内部で cdi のアップロードURLにイメージをhttpでアップロードしていた。 VM起動 (2) の方法よりも起動速くなるかと期待したがそうでもなさそう。

自前でVMイメージを保持したWebサーバを建てる必要がないくらいがメリットかな。

デバッグ

結構試行錯誤しないと動かない。最低でも VirtualMachineInstance (VMI) が作成されていれば、コンソールを確認することで処理が最低でもどこまで進んでることが確認できる。

kubectl virt console ubuntu-01

ちなみに、ssh 接続は以下のコマンドでできたが、自分の環境だと Pod の IP Address に直接アクセスできるので、もしかしたら普通の環境では簡単に ssh できないかもしれない。

kubectl virt ssh ubuntu@ubuntu-01 -i ~/.ssh/id_rsa

感想

起動自体は早いのだが、VMイメージを用意するのが意外と時間がかかるのでそこをどうにかしたい。

追記 2022-09-29

結局上記の方法を使うのをやめて、OSイメージが入ったPVCを用意した後は、それをクローンして使うことにしました。

こんな感じ。

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: node-root-disk
spec:
  storageClassName: "bronze"
  dataSource:
    name: jammy-server
    kind: PersistentVolumeClaim
  accessModes:
  - ReadWriteOnce
  volumeMode: Block
  resources:
    requests:
      storage: 10Gi