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.yaml
と cdi-cr.yaml
はそれぞれ kubevirt
と cdi
の実体?というかそれぞれの設定ファイル?っぽいものらしく、これらもデプロイしないと以降のステップがうまく動かなかった。
その他必要なツールのインストール
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を作れば勝手に作られる。この際、accessMode
を ReadWriteMany
にしておくとクローンする際に便利そうと思いきや、
このソースとなる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