このブログではKubeVirtについて何度か取り上げていました。 主にkubeadmでクラスターを作って、KubeVirtを導入する手順もご紹介しています。
ちなみになぜKubeVirtを頻繁に取り上げるかというと、筆者がKubeVirtに個人的に興味があるからです。
さて今回はMinikubeを使って、KubeVirtの評価ができる環境づくりを試してみようと思います。 Minikubeを利用することにより、KubernetesでKVM VMを利用できるKubeVirtを手軽に試すことができます。
Minikubeで手軽にKubeVirtを利用できるようになることで、コンテナーとVMでアプリケーションを実行して色々なテストをしたり、 コンテナーとVMでアプリケーションをそれぞれ動かして、連携のテストをしたりなどできるようになるので、おそらく便利だと思います。
KubeVirtの公式ドキュメントに「Labs - KubeVirt quickstart with Minikube」がありますが、前提環境について詳しく書かれていないため、Ubuntuをセットアップした後から順を追って説明する形でこの記事を書いています。
KubeVirtについておさらい
KubeVirtは、Kubernetesで仮想マシン利用が可能になるソリューションです。 コンテナ利用の需要の高まりによってKubernetesが使われることが多くなりましたが、 その一方で、コンテナ化はしたいがコンテナ化が難しいアプリケーションは少なからずあるのが現状です。
KubeVirtは、KubernetesクラスターにVM管理という追加機能を提供するソフトウェアです。
一般のコンテナアプリケーションの実行と同じようにkubectl
コマンドラインなどを使ってVMの作成を依頼すると、KubeVirtのコントローラーがVMIが指定したホストにスケジュールされるように命令します。
デーモン(virt-handler)はkubeletと一緒にホストを処理してVMIを起動し、「環境」をセットアップします。
Kubernetesのノードではvirt-handlerというプロセスが動作しており、VMIの作成が実行されるとPodが作られてvirt-lancherというプロセスがまず実行されます。 このプロセスがその環境にQEMUとLibVirtのプロセスを実行します。そして最終的にマニフェスト要求に従ってVMにOSやリモートアクセスのための設定をセットアップします。
KubeVirtの良いところはVMとコンテナーで動くアプリケーションを共存できるという点です。KubeVirtで作成したVMは単独でも利用できますが、一つのVMIにコンテナとVMで動くアプリケーションを共存させたり、別のPodで動くコンテナ内のアプリケーションとVMで動くアプリケーションを連携させて一つのシステムを稼働させるといったことが可能にあります。
もうちょっと詳しく知りたい場合はこちらをご覧ください。
KubeVirt環境のセットアップ概要
今回は次のような流れでセットアップしておきます。
- OSをインストール
- Minikubeをインストール
- Linux KVM環境をセットアップ
- Minikubeを「kvm2」ドライバーでクラスター起動
- MinikubeのKubevirtアドオンを有効
OSをインストール
ベースOSとして、今回はUbuntu Server 20.04をインストールしました。
Minikubeをインストール
minikube startを開いて、OSなどをポチポチ設定して表示された方法で導入。 今回はUbuntuをベースOSとしてインストールしたので、次のようにMinikubeをインストールします。
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube_latest_amd64.deb sudo dpkg -i minikube_latest_amd64.deb
Linux KVM環境をセットアップ
次に、Minikubeをどの環境上で動かすか「Driver」を選択します。 OSによって使えるDriverは異なっており、実装仕様も異なります。「preferred」と表記されているものを選べばたいてい問題ないようですが、 何か作業をしてみてうまくいかない場合は他のDriverに変更した方が良いかもしれません(経験上)。
今回はLinuxでMinikubeを使うときにはスタンダートなKVM2 Driverを使います。 KVM2 Driverは名前の通り、Linux KVM環境をホストに導入する必要があります。
あくまでMinikubeがVMの中で動作するだけで、コンテナは後述の「minikube start」で指定(--container-runtime)したランタイムを介して実行されます。 指定できるランタイムはhelpを確認すると確認できます。
まずはOSにLinux KVMをインストールする。Ubuntuの場合は...
$ sudo apt-get install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils $ sudo adduser `id -un` libvirt && sudo adduser `id -un` kvm
これについての詳細は、KVM/Installationを参照してください。
Minikubeを「kvm2」ドライバーでクラスター起動
次のように実行してKVM VMでminikubeを動かし、その中でKubernetesクラスターとして稼働させます。
今回はコンテナランタイムとしてcontainerd
、ネットワークインターフェイスとしてflannel
を使う場合の例です。
$ minikube config set driver kvm2 $ minikube start --container-runtime=containerd --cni=flannel
virshコマンドを実行すると、KVM VMとしてMinikubeが動いていることがわかります。「minikube ssh」でこのVMの中に入れます。
$ virsh list Id Name State -------------------------- 2 minikube running $ minikube ssh sudo crictl pods POD ID CREATED STATE NAME NAMESPACE ATTEMPT RUNTIME 4f34dddc45fe5 6 days ago NotReady hello-node-6b89d599b9-st5v2 default 0 (default) e4893ab6d4e9d 6 days ago NotReady virt-launcher-vm1-x928v default 0 (default) 799ff1520788d 6 days ago Ready cdi-uploadproxy-668fd6f45-nxqkv cdi 0 (default) 3a37ef5de5c65 6 days ago Ready cdi-deployment-7f984664d4-n2d9d cdi 0 (default) a199c366627fe 6 days ago Ready cdi-apiserver-69467b7bc-74jzc cdi 0 (default) dcc5a052caa96 6 days ago Ready cdi-operator-556d7499d5-w4qj2 cdi 0 (default) ef4540cef599d 6 days ago NotReady virt-launcher-testvmi-nocloud-khjqj default 0 (default) 21517d7be5dd7 6 days ago Ready virt-controller-75fd85c84b-7vnmj kubevirt 0 (default) 9475b307b6870 6 days ago Ready virt-controller-75fd85c84b-ppdbl kubevirt 0 (default) 122a06662baea 6 days ago Ready virt-handler-vhmzh kubevirt 0 (default) 0bd9149f4692f 6 days ago Ready virt-api-667fb5b669-955ln kubevirt 0 (default) 930676ce916bc 6 days ago Ready virt-operator-97778fbf8-m4lct kubevirt 0 (default) 571e6832904c4 6 days ago Ready virt-operator-97778fbf8-ktrsz kubevirt 0 (default) 39a41e6855e8b 6 days ago Ready kubevirt-install-manager kube-system 0 (default) 1fc97cea4b4bf 6 days ago Ready coredns-64897985d-j9zdh kube-system 0 (default) 69abc84a9e23c 6 days ago Ready kube-flannel-ds-amd64-mzkbw kube-system 0 (default) a2d2b2f1dfeb7 6 days ago Ready kube-proxy-hjjbr kube-system 0 (default) 32bcdac176a91 6 days ago Ready storage-provisioner kube-system 0 (default) c3c740c09b293 6 days ago Ready etcd-minikube kube-system 0 (default) 21c7ab0322258 6 days ago Ready kube-scheduler-minikube kube-system 0 (default) 8668461751341 6 days ago Ready kube-controller-manager-minikube kube-system 0 (default) 5d29fddbd62df 6 days ago Ready kube-apiserver-minikube kube-system 0 (default)
MinikubeでデプロイしたKubernetesを使う
次のコマンドを実行して、kubectlコマンドを実行したときにminikube kubectl
が実行されるようにエイリアスを張ります。
これを行うことで、デプロイしたKubernetesクラスターのバージョンに合わせたCLIバイナリーをダウンロードしてくれるようになります。
Minikubeバイナリーでは色々なバージョンのKubernetesを実行できます。
Kubernetes APIとアクセスするインターフェイスとしてkubectlがありますが、一定の互換性は持っているもののあまりバージョンが離れたクラスターへのアクセスは問題が発生する場合があります。Minikubeを使う場合は特定のバージョンのkubectlをセットアップするよりもminikube kubectl
のエイリアスを貼っておいた方が便利です。
エイリアスを永続的に設定するには、.bashrc
のaliasのあたりに追記もしておくと良さそうです。
$ alias kubectl='minikube kubectl --'
この設定をしておくと、Kubernetes APIにアクセスしたときに適切なバージョンのkubectlが${HOME}/.minikube/cache
にインストールされます。
コマンドを実行して、普通のコンテナを実行できることを確認します。
$ kubectl create deployment hello-node --image=k8s.gcr.io/echoserver:1.4 $ kubectl get deployment $ kubectl delete deployment hello-node
MinikubeのKubevirtアドオンを有効
次に、このMinikubeで構築したK8sでKubeVirtを使えるようにします。 詳細やマニュアルインストール方法はLabs - KubeVirt quickstart with Minikubeに書かれていますが、 以下のコマンドでアドオンを有効化できます。
$ minikube addons enable kubevirt $ kubectl get all -n kubevirt # 有効化されたか確認
インストールされたKuberVirtのバージョンは kubectl describe kubevirt -n kubevirt
の実行結果から確認できます。
次のコマンドを使ってvirtctl
CLIをインストールします。
VM作成などはkubectl
を利用しますが、VMのアクセスや制御にはvirtctl
を利用するためです。
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
KubeVirt環境のテスト
ここまででKubeVirtの実行環境は整っていますので、次にKubeVirtを使ってみたいと思います。 KubeVirtではコンテナーイメージを使ってVMを動かす方法もあるのですが、好きなLinux OSを動かしたいと思いますので 今回はContainerized Data Importer (CDI)を使って、イメージとVMの作成を試してみたいと思います。
まずはCDI機能をクラスターに追加するため、次のようなコマンドを実行します(この記事を書いた時点で最新であったCDIのv1.50.0をインストールする例)。 システムコンテナーはcdiという名前空間で動くので、そのように指定してステータスを確認しましょう。
$ export VERSION=v1.50.0 $ kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/$VERSION/cdi-operator.yaml $ kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/$VERSION/cdi-cr.yaml $ kubectl get cdi cdi -n cdi -w NAME AGE PHASE cdi 2s cdi 13s Deploying cdi 66s Deployed $ kubectl get pods -n cdi cdi-apiserver-69467b7bc-wvzrx 1/1 Running 0 81s cdi-deployment-7f984664d4-6kdxj 1/1 Running 0 75s cdi-operator-556d7499d5-h2w7b 1/1 Running 0 102s cdi-uploadproxy-668fd6f45-mcx4k 1/1 Running 0 70s
Minikubeでクラスターを構築するとローカルストレージが利用可能なストレージクラスが定義されているはずです。 CDIではVMを作る毎にストレージボリュームイメージをこのストレージに作成して、VMを作成する際にマニフェストにイメージボリュームを指定することで VMにOSイメージを流し込むようなイメージになります。
まずはストレージクラスターを確認しましょう。
$ kubectl get sc NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE standard (default) k8s.io/minikube-hostpath Delete Immediate false 34m
次にVMイメージを作成してみます。 VMイメージはストレージクラスを通じてVMに割り当てるストレージを要求し、VMと紐付けます。
先ほどざっくり説明したように、一度起動するとデータがストレージに書き込まれます。そのため、動かすVM毎にこの作業が必要です。
$ cat <<EOF > pvc_fedora.yml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: "fedora" labels: app: containerized-data-importer annotations: cdi.kubevirt.io/storage.import.endpoint: "https://download.fedoraproject.org/pub/fedora/linux/releases/36/Cloud/x86_64/images/Fedora-Cloud-Base-36-1.5.x86_64.raw.xz" spec: accessModes: - ReadWriteOnce storageClassName: standard #ストレージクラスを指定します resources: requests: storage: 5Gi #適切なボリュームサイズを指定します EOF
イメージソースURLに作成ごとに取りに行くと非効率なので、イメージをローカルネットワーク上のWebサーバーなどで公開しておき、それを使うと良いと思います。 ローカルネットワーク内にNGINXやApacheといったようなWebサーバーをセットアップして、公開ディレクトリーにイメージを置いておけば良いでしょう。
OSイメージはOpenStackなどで利用するイメージと同じものを使います。本例はFedoraの例なので、ここを別のクラウドイメージに置き換えれば他のOSを動かすこともできます。 イメージとして最低限必要なのは、cloud-initが入っていることでしょうか。
マニフェストファイルの準備が終わったら、通常のようにkubectl create
してください。処理が開始されます。
Import Complete
と出力されれば、イメージ作成は完了です。
$ kubectl create -f pvc_fedora.yml $ kubectl get pod NAME READY STATUS RESTARTS AGE importer-fedora 1/1 Running 0 45s $ kubectl logs -f importer-fedora I0609 02:42:58.381176 1 importer.go:83] Starting importer I0609 02:42:58.382145 1 importer.go:150] begin import process ... I0608 08:32:19.667671 1 data-processor.go:288] Validating image I0608 08:32:19.674689 1 data-processor.go:282] New phase: Complete I0608 08:32:19.674907 1 importer.go:194] Import Complete
さて、KubeVirtではVMに対してシリアルコンソールやVNC、SSHでアクセスできます。 今回はSSHでアクセスしてみたいと思います。
SSHでVMにアクセスする場合、一般的にオフィシャルに用意されているクラウドイメージは公開鍵認証を許可していることが多いため、 ホストからVMにSSHできるようにするため、事前にキーペアを作ってVM作成時に指定することにします。
キーペアは今回は次のように作成しました。
$ ssh-keygen -t ed25519 $ cat ~/.ssh/id_ed25519.pub ssh-ed25519 AAAAHogeeeHugaaa ubuntu@bay10-gen9 #みたいな感じで公開鍵が出力される
VM作成テンプレートを使ってVMを作成してみます。公開鍵をcatで出力して、内容をYAMLファイル内に書き込みます。
$ wget https://kubevirt.io/labs/manifests/vm1_pvc.yml $ vi vm1_pvc.yml ... volumes: - name: disk0 persistentVolumeClaim: claimName: fedora #PVC名を確認 ... ssh_authorized_keys: - ssh-ed25519 AAAAHogeeeHugaaa ubuntu@bay10-gen9 #こんな感じでペースト
先ほど編集したマニフェストファイルを使って、VMを作成します。
$ kubectl create -f vm1_pvc.yml $ kubectl get pods NAME READY STATUS RESTARTS AGE virt-launcher-vm1-pl4hr 1/1 Running 0 14s $ kubectl get vm NAME AGE STATUS READY vm1 3m45s Running True $ kubectl get vmi NAME AGE PHASE IP NODENAME READY vm1 3m49s Running 10.244.0.25 bay10-gen9 True
VMにアクセスします。指定するのはPod名ではなくVM名なので注意。
$ virtctl ssh fedora@vm1 -i ~/.ssh/id_ed25519 The authenticity of host 'vmi/vm1.default:22 (172.17.28.62:6443)' can't be established. ECDSA key fingerprint is SHA256:qc5I4Q1GOHu/dYotwJvZxZwJD2oqJ5huWp7qH8ZmMjE. Are you sure you want to continue connecting (yes/no)? yes [fedora@vm1 ~]$ sudo yum check-update Fedora 36 - x86_64 18 MB/s | 81 MB 00:04 Fedora 36 openh264 (From Cisco) - x86_64 1.6 kB/s | 2.5 kB 00:01 Fedora Modular 36 - x86_64 4.5 MB/s | 2.4 MB 00:00 Fedora 36 - x86_64 - Updates 9.4 MB/s | 17 MB 00:01 Fedora Modular 36 - x86_64 - Updates 1.4 MB/s | 2.2 MB 00:01 ...
SSHでVMにアクセス、VM内でyumコマンドを実行してもちゃんとリポジトリと繋がるのでネットワーク的にも問題ありませんでした。 これで、KubernetesでVMの作成ができるKubeVirtを動かせる環境ができたわけです。