はじめに
Docker、Kubernetesをはじめとするコンテナ技術が普及するにつれ、現行でVirtual Machine(VM)が稼働している環境からコンテナへの移行を、どうやって実現するかが課題になってきました。
例えば、リフト&シフトなどの方法で基盤を移行させることを検討する際、VMとコンテナが共通基盤上にあるほうが、移行はやりやすくなるだろうと考えられました。
Kubevirtはそんなソリューションを提供するツールの一つになります。
今回はKubevirtについて簡単に紹介し、新しくリリースされたv0.21.0で利用可能となったvirtctl migrate
コマンドを試してみました。
結論
- KubevirtはVMとコンテナをKubernetes基盤上で共通管理するツールである。
- v0.21.0より
virtctl migrate
コマンドが利用可能になり、VMのライブマイグレーションがより簡単にできるようになった。
Kubevirtとは
KubevirtはVMとコンテナを共通の基盤で管理できるようなツールです。Kubevirtは例えば以下のような機能を提供します。
- Kubernetes上でVMとコンテナを共通リソースとして管理する
kubectl
コマンドによってVMを管理可能にする
virtctl
コマンドによってVMの起動・停止等の操作を行う- CDI (Containerized Data Importer)にVMイメージをインポートし、保存したイメージを利用してVMを起動することができる
- VMをあるノードから別のノードへとライブマイグレーションを行うことができる
Kubevirtのコンポーネントは、以下の図のようになります。
virt-controller
:クラスターワイドな仮想化機能を提供するKubernetes Operator。新しいVMオブジェクトがKubernetes APIサーバにポストされると、VMを配置するPodを作成します。Podが特定のノードにスケジューリングされると、virt-controller
がVMオブジェクトをアップデートし、virt-handlerに引き渡します。virt-handler
:Kubernetesノードごとに配置されたKubevirtコンポーネント。virt-controller
と同様、VMオブジェクトの変化を検知し、Required StateにVMを変更します。またVMの配置されたPod上にあるlibvirtd
インスタンスによって、VMに対応するdomain(resources, devices等のコンフィグ情報)が作成されます。virt-launcher
:VMをホストするために使用するcgroupsとnamespaceを提供します。virt-handler
はVMのCRDオブジェクトをvirt-launcher
に渡すことでVMの起動を通知し、それを受けてvirt-launcher
はlibvirtd
を用いてVMを起動します。そこからvirt-launcher
はVMプロセスを監視します。libvirtd
:各VM Podに配置されます。virt-launcher
はVMプロセスのライフサイクルを管理するためにlibvirtd
を利用します。
Kubevirtのデプロイ
ここからKubevirtのデプロイを進めます。手順はKubevirtの公式ドキュメントに紹介されいますので、そちらを参照して進めていきます。
※参考ドキュメント:
構築環境
- 環境:VirtualBox
- OS:CentOS 7.6
- Kubernetesバージョン:v1.15.1
- Kubernetesノード数:Masterノード×1、Workerノード×2
Kubevirt Operatorのデプロイ
まずKubevirt Operatorをデプロイします。Kubernetes Operatorについては様々なブログ・ドキュメントで説明されていますが、Kubernetes向けのStatefulアプリケーションを自動で実行・管理するCustom Controllerです。
※参考ドキュメント:
CoreOS: Introducing Operators: Putting Operational Knowledge into Software
# KUBEVIRT_VERSIONの設定 [root@kube-master01 kubevirt]# export KUBEVIRT_VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases|grep tag_name|sort -V | tail -1 | awk -F':' '{print $2}' | sed 's/,//' | xargs | cut -d'-' -f1) [root@kube-master01 kubevirt]# echo $KUBEVIRT_VERSION v0.21.0 [root@kube-master01 kubevirt]# # kubevirt-operatorのデプロイ [root@kube-master01 kubevirt]# kubectl create -f https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-operator.yaml namespace/kubevirt created customresourcedefinition.apiextensions.k8s.io/kubevirts.kubevirt.io created clusterrole.rbac.authorization.k8s.io/kubevirt.io:operator created serviceaccount/kubevirt-operator created clusterrole.rbac.authorization.k8s.io/kubevirt-operator created clusterrolebinding.rbac.authorization.k8s.io/kubevirt-operator created deployment.apps/virt-operator created [root@kube-master01 kubevirt]# # デプロイ後のリソース確認 [root@kube-master01 kubevirt]# kubectl get ns NAME STATUS AGE default Active 43d kube-node-lease Active 43d kube-public Active 43d kube-system Active 43d kubevirt Active 9s metallb-system Active 43d [root@kube-master01 kubevirt]# [root@kube-master01 kubevirt]# kubectl get pods -n kubevirt -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES virt-operator-5757956476-j7nsc 1/1 Running 0 27s 192.168.132.23 kube-worker01 <none> <none> virt-operator-5757956476-zqc77 1/1 Running 0 27s 192.168.247.219 kube-worker02 <none> <none> [root@kube-master01 kubevirt]# kubectl get all -n kubevirt NAME READY STATUS RESTARTS AGE pod/virt-operator-5757956476-j7nsc 1/1 Running 0 61s pod/virt-operator-5757956476-zqc77 1/1 Running 0 61s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/virt-operator 2/2 2 2 61s NAME DESIRED CURRENT READY AGE replicaset.apps/virt-operator-5757956476 2 2 2 61s [root@kube-master01 kubevirt]#
Virtualization Extensionsの確認
次に利用しているマシンのCPUがVirtualization Extensionsに対応しているかを確認します。対応していない場合、kubevirt-config
というConfigMapを作成し、Kubevirtのemulation modeを利用できるようにします。
#Virtualization Extensionsに対応しているかを確認 [root@kube-master01 kubevirt]# egrep 'svm|vmx' /proc/cpuinfo [root@kube-master01 kubevirt]# # 対応していないのでConfigMapを作成 [root@kube-master01 kubevirt]# kubectl create configmap kubevirt-config -n kubevirt --from-literal debug.useEmulation=true configmap/kubevirt-config created [root@kube-master01 kubevirt]# [root@kube-master01 kubevirt]# kubectl get cm -n kubevirt NAME DATA AGE kubevirt-config 1 17s [root@kube-master01 kubevirt]#
Kubevirtのデプロイ
次にKubevirtをデプロイします。ここではCustom ResourceをデプロイすることでKubevirtを利用可能にします。まずvirt-api
がデプロイされ、その後virt-controller
virt-handler
がデプロイされます。
# Kubevirt Custom Resourceをデプロイ [root@kube-master01 kubevirt]# kubectl create -f https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-cr.yaml kubevirt.kubevirt.io/kubevirt created [root@kube-master01 kubevirt]# [root@kube-master01 kubevirt]# kubectl get pods -n kubevirt NAME READY STATUS RESTARTS AGE virt-api-6f88888558-8s5b8 1/1 Running 0 73s virt-api-6f88888558-gqzl9 1/1 Running 0 73s virt-controller-58f4858df6-j4z96 1/1 Running 0 45s virt-controller-58f4858df6-nwkbl 1/1 Running 0 45s virt-handler-ks6ng 1/1 Running 0 45s virt-handler-m7vwv 1/1 Running 0 45s virt-operator-5757956476-j7nsc 1/1 Running 0 3m57s virt-operator-5757956476-zqc77 1/1 Running 0 3m57s [root@kube-master01 kubevirt]#
virtctlのインストール
最後にvirtctl
をインストールします。
# virtctlのインストール [root@kube-master01 kubevirt]# curl -L -o virtctl \ > https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/virtctl-${KUBEVIRT_VERSION}-linux-amd64 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 617 0 617 0 0 1102 0 --:--:-- --:--:-- --:--:-- 1101 100 37.1M 100 37.1M 0 0 7646k 0 0:00:04 0:00:04 --:--:-- 10.8M [root@kube-master01 kubevirt]# chmod +x virtctl [root@kube-master01 kubevirt]# mv virtctl /usr/local/bin/virtctl # インストール後の確認 [root@kube-master01 kubevirt]# virtctl version Client Version: version.Info{GitVersion:"v0.21.0", GitCommit:"e220f16d7a2aae7295199bbbc3594a5b50b7a3f4", GitTreeState:"clean", BuildDate:"2019-09-07T07:33:17Z", GoVersion:"go1.11.5", Compiler:"gc", Platform:"linux/amd64"} Server Version: version.Info{GitVersion:"v0.21.0", GitCommit:"e220f16d7a2aae7295199bbbc3594a5b50b7a3f4", GitTreeState:"clean", BuildDate:"2019-09-09T08:09:15Z", GoVersion:"go1.11.5", Compiler:"gc", Platform:"linux/amd64"} [root@kube-master01 kubevirt]# [root@kube-master01 kubevirt]# virtctl help virtctl controls virtual machine related operations on your kubernetes cluster. Available Commands: console Connect to a console of a virtual machine instance. expose Expose a virtual machine instance, virtual machine, or virtual machine instance replica set as a new service. help Help about any command image-upload Upload a VM image to a PersistentVolumeClaim. migrate Migrate a virtual machine. restart Restart a virtual machine. start Start a virtual machine. stop Stop a virtual machine. version Print the client and server version information. vnc Open a vnc connection to a virtual machine instance. Use "virtctl <command> --help" for more information about a given command. Use "virtctl options" for a list of global command-line options (applies to all commands). [root@kube-master01 kubevirt]#
VMのデプロイ
次にVMをデプロイします。ここでも公式ドキュメントで紹介されたデモ用VMのデプロイをやってみます。
※参考ドキュメント:
Virtual Machineの作成
VMのデプロイでは、デモ用のyamlファイルが用意されているので、それをデプロイします。
デモ用のデータでは、まずVirtualMachineリソースをデプロイします。ここではCirrOSを利用したVirtualMachineをデプロイします。
# wgetでyamlファイルをダウンロード [root@kube-master01 kubevirt]# wget https://raw.githubusercontent.com/kubevirt/kubevirt.github.io/master/labs/manifests/vm.yaml --2019-09-16 02:27:54-- https://raw.githubusercontent.com/kubevirt/kubevirt.github.io/master/labs/manifests/vm.yaml Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.108.133 Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.108.133|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 840 [text/plain] Saving to: ‘vm.yaml’ 100%[==============================================================================>] 840 --.-K/s in 0s 2019-09-16 02:27:54 (159 MB/s) - ‘vm.yaml’ saved [840/840] [root@kube-master01 kubevirt]# [root@kube-master01 kubevirt]# ls -l total 16 -rw-r--r-- 1 root root 10204 Sep 9 08:32 kubevirt-operator.yaml -rw-r--r-- 1 root root 840 Sep 16 02:27 vm.yaml [root@kube-master01 kubevirt]# # VirtualMachineのデプロイ [root@kube-master01 kubevirt]# kubectl apply -f vm.yaml virtualmachine.kubevirt.io/testvm created [root@kube-master01 kubevirt]# # デプロイ後の確認 [root@kube-master01 kubevirt]# kubectl get vms NAME AGE RUNNING VOLUME testvm 7s false [root@kube-master01 kubevirt]#
上記yamlファイルは以下のようになります。
apiVersion: kubevirt.io/v1alpha3 kind: VirtualMachine metadata: name: testvm spec: running: false template: metadata: labels: kubevirt.io/size: small kubevirt.io/domain: testvm spec: domain: devices: disks: - name: containerdisk disk: bus: virtio - name: cloudinitdisk disk: bus: virtio interfaces: - name: default bridge: {} resources: requests: memory: 64M networks: - name: default pod: {} volumes: - name: containerdisk containerDisk: image: kubevirt/cirros-registry-disk-demo - name: cloudinitdisk cloudInitNoCloud: userDataBase64: SGkuXG4=
なお、デプロイしたVirtualMachine
をkubectl get vm -o yaml
kubectl describe
で表示した結果も、併せて載せておきます。
kubectl get vms testvm -o yaml
apiVersion: kubevirt.io/v1alpha3 kind: VirtualMachine metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"kubevirt.io/v1alpha3","kind":"VirtualMachine","metadata":{"annotations":{},"name":"testvm","namespace":"default"},"spec":{"running":false,"template":{"metadata":{"labels":{"kubevirt.io/domain":"testvm","kubevirt.io/size":"small"}},"spec":{"domain":{"devices":{"disks":[{"disk":{"bus":"virtio"},"name":"containerdisk"},{"disk":{"bus":"virtio"},"name":"cloudinitdisk"}],"interfaces":[{"bridge":{},"name":"default"}]},"resources":{"requests":{"memory":"64M"}}},"networks":[{"name":"default","pod":{}}],"volumes":[{"containerDisk":{"image":"kubevirt/cirros-registry-disk-demo"},"name":"containerdisk"},{"cloudInitNoCloud":{"userDataBase64":"SGkuXG4="},"name":"cloudinitdisk"}]}}}} kubevirt.io/latest-observed-api-version: v1alpha3 kubevirt.io/storage-observed-api-version: v1alpha3 creationTimestamp: "2019-09-16T02:28:42Z" generation: 2 name: testvm namespace: default resourceVersion: "755876" selfLink: /apis/kubevirt.io/v1alpha3/namespaces/default/virtualmachines/testvm uid: af647f7a-b860-4390-85a3-ae1255a1ec14 spec: running: false template: metadata: creationTimestamp: null labels: kubevirt.io/domain: testvm kubevirt.io/size: small spec: domain: devices: disks: - disk: bus: virtio name: containerdisk - disk: bus: virtio name: cloudinitdisk interfaces: - bridge: {} name: default machine: type: "" resources: requests: memory: 64M networks: - name: default pod: {} volumes: - containerDisk: image: kubevirt/cirros-registry-disk-demo name: containerdisk - cloudInitNoCloud: userDataBase64: SGkuXG4= name: cloudinitdisk status: {}
kubectl describe vms testvm
Name: testvm Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"kubevirt.io/v1alpha3","kind":"VirtualMachine","metadata":{"annotations":{},"name":"testvm","namespace":"default"},"spec":{"... kubevirt.io/latest-observed-api-version: v1alpha3 kubevirt.io/storage-observed-api-version: v1alpha3 API Version: kubevirt.io/v1alpha3 Kind: VirtualMachine Metadata: Creation Timestamp: 2019-09-16T02:28:42Z Generation: 2 Resource Version: 755876 Self Link: /apis/kubevirt.io/v1alpha3/namespaces/default/virtualmachines/testvm UID: af647f7a-b860-4390-85a3-ae1255a1ec14 Spec: Running: false Template: Metadata: Creation Timestamp: <nil> Labels: kubevirt.io/domain: testvm kubevirt.io/size: small Spec: Domain: Devices: Disks: Disk: Bus: virtio Name: containerdisk Disk: Bus: virtio Name: cloudinitdisk Interfaces: Bridge: Name: default Machine: Type: Resources: Requests: Memory: 64M Networks: Name: default Pod: Volumes: Container Disk: Image: kubevirt/cirros-registry-disk-demo Name: containerdisk Cloud Init No Cloud: userDataBase64: SGkuXG4= Name: cloudinitdisk Status: Events: <none>
VirtualMachineの管理
次にデプロイしたVirtualMachine
を起動します。VirtualMachine
の起動にはvirtctl
コマンドを利用するか、kubectl patch
でリソースの編集を行います。
# virtctlコマンドで起動 [root@kube-master01 kubevirt]# virtctl start testvm VM testvm was scheduled to start # VirtualMachineの状態確認 [root@kube-master01 kubevirt]# kubectl get vms NAME AGE RUNNING VOLUME testvm 3m22s true [root@kube-master01 kubevirt]#
VirtualMachine
を起動すると、VirtualMachineInstance
というリソースが作成されます。次にVirtualMachineInstance
リソースを確認します。
# VirtualMachineInstanceの確認 [root@kube-master01 kubevirt]# kubectl get vmis NAME AGE PHASE IP NODENAME testvm 16s Running 192.168.247.212 kube-worker02 [root@kube-master01 kubevirt]#
上記のようにPHASE
がRunning
になっていれば起動しているので、VMにログインします。ログインにはSSHも利用可能ですが、virtctl console
コマンドも用意されています。
# VMにログイン [root@kube-master01 kubevirt]# virtctl console testvm Successfully connected to testvm console. The escape sequence is ^] [中略] # コンソールの出力が停止したらEnterボタンを押すと、ログインIDを入力できる login as 'cirros' user. default password: 'gocubsgo'. use 'sudo' for root. testvm login:
上記VirtualMachine
へのログインは、初期IDであるcirros
と初期PWであるgocubsgo
を入力します。
# CirrOSにログイン testvm login: cirros Password: $ $ pwd /home/cirros $
VirtualMachine
から抜けるには、Ctrl + ]
ボタンを入力します。
次にVirtualMachine
を停止します。停止にはvirtctl stop
コマンドを入力します。VirtualMachine
を停止するとVirtualMachineInstance
リソースが削除されます。
# VirtualMachineの停止 [root@kube-master01 kubevirt]# virtctl stop testvm VM testvm was scheduled to stop [root@kube-master01 kubevirt]# kubectl get vm NAME AGE RUNNING VOLUME testvm 6m24s false [root@kube-master01 kubevirt]# # VirtualMachineInstanceの確認 [root@kube-master01 kubevirt]# kubectl get vmi No resources found. [root@kube-master01 kubevirt]#
最後にVirtualMachine
リソースを削除します。
[root@kube-master01 kubevirt]# kubectl delete -f vm.yaml virtualmachine.kubevirt.io "testvm" deleted [root@kube-master01 kubevirt]# [root@kube-master01 kubevirt]# kubectl get vm No resources found. [root@kube-master01 kubevirt]#
こちらもkubectl get vmi -o yaml
kubectl describe
の結果を載せておきます。
kubectl get vmi testvm -o yaml
apiVersion: kubevirt.io/v1alpha3 kind: VirtualMachineInstance metadata: annotations: kubevirt.io/latest-observed-api-version: v1alpha3 kubevirt.io/storage-observed-api-version: v1alpha3 creationTimestamp: "2019-09-16T02:35:49Z" finalizers: - foregroundDeleteVirtualMachine generateName: testvm generation: 8 labels: kubevirt.io/domain: testvm kubevirt.io/nodeName: kube-worker02 kubevirt.io/size: small name: testvm namespace: default ownerReferences: - apiVersion: kubevirt.io/v1alpha3 blockOwnerDeletion: true controller: true kind: VirtualMachine name: testvm uid: af647f7a-b860-4390-85a3-ae1255a1ec14 resourceVersion: "757035" selfLink: /apis/kubevirt.io/v1alpha3/namespaces/default/virtualmachineinstances/testvm uid: c28c1261-fcfd-4be6-9425-28a323d2924d spec: domain: devices: disks: - disk: bus: virtio name: containerdisk - disk: bus: virtio name: cloudinitdisk interfaces: - bridge: {} name: default features: acpi: enabled: true firmware: uuid: 5a9fc181-957e-5c32-9e5a-2de5e9673531 machine: type: q35 resources: requests: cpu: 100m memory: 64M networks: - name: default pod: {} volumes: - containerDisk: image: kubevirt/cirros-registry-disk-demo imagePullPolicy: Always name: containerdisk - cloudInitNoCloud: userDataBase64: SGkuXG4= name: cloudinitdisk status: conditions: - lastProbeTime: null lastTransitionTime: null message: cannot migrate VMI with a bridge interface connected to a pod network reason: InterfaceNotLiveMigratable status: "False" type: LiveMigratable - lastProbeTime: null lastTransitionTime: "2019-09-16T02:35:56Z" status: "True" type: Ready interfaces: - ipAddress: 192.168.247.208 mac: e6:78:21:db:1c:bc name: default migrationMethod: BlockMigration nodeName: kube-worker02 phase: Running qosClass: Burstable
kubectl describe vmi testvm
Name: testvm Namespace: default Labels: kubevirt.io/domain=testvm kubevirt.io/nodeName=kube-worker02 kubevirt.io/size=small Annotations: kubevirt.io/latest-observed-api-version: v1alpha3 kubevirt.io/storage-observed-api-version: v1alpha3 API Version: kubevirt.io/v1alpha3 Kind: VirtualMachineInstance Metadata: Creation Timestamp: 2019-09-16T02:35:49Z Finalizers: foregroundDeleteVirtualMachine Generate Name: testvm Generation: 8 Owner References: API Version: kubevirt.io/v1alpha3 Block Owner Deletion: true Controller: true Kind: VirtualMachine Name: testvm UID: af647f7a-b860-4390-85a3-ae1255a1ec14 Resource Version: 757035 Self Link: /apis/kubevirt.io/v1alpha3/namespaces/default/virtualmachineinstances/testvm UID: c28c1261-fcfd-4be6-9425-28a323d2924d Spec: Domain: Devices: Disks: Disk: Bus: virtio Name: containerdisk Disk: Bus: virtio Name: cloudinitdisk Interfaces: Bridge: Name: default Features: Acpi: Enabled: true Firmware: Uuid: 5a9fc181-957e-5c32-9e5a-2de5e9673531 Machine: Type: q35 Resources: Requests: Cpu: 100m Memory: 64M Networks: Name: default Pod: Volumes: Container Disk: Image: kubevirt/cirros-registry-disk-demo Image Pull Policy: Always Name: containerdisk Cloud Init No Cloud: userDataBase64: SGkuXG4= Name: cloudinitdisk Status: Conditions: Last Probe Time: <nil> Last Transition Time: <nil> Message: cannot migrate VMI with a bridge interface connected to a pod network Reason: InterfaceNotLiveMigratable Status: False Type: LiveMigratable Last Probe Time: <nil> Last Transition Time: 2019-09-16T02:35:56Z Status: True Type: Ready Interfaces: Ip Address: 192.168.247.208 Mac: e6:78:21:db:1c:bc Name: default Migration Method: BlockMigration Node Name: kube-worker02 Phase: Running Qos Class: Burstable Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SuccessfulCreate 2m8s virtualmachine-controller Created virtual machine pod virt-launcher-testvm-4x4xf Normal Created 2m1s (x3 over 2m1s) virt-handler, kube-worker02 VirtualMachineInstance defined. Normal Started 2m1s virt-handler, kube-worker02 VirtualMachineInstance started.
マイグレーション
ここからKubevirt v0.21.0から利用できるようになったvirtctl migrate
コマンドを試してみます。これは、あるVMリソースを別のノードに移動させるコマンドです。これまではマイグレーション用のリソースであるVirtualMachineInstanceMigration
を毎回デプロイする必要がありましたが、virtctl migrate
コマンドによりその手間を軽減することができます。
※参考ドキュメント:
Kubevirt - Interfaces and Networks
LiveMigrationの有効化
まずLiveMigrationを有効にするため、kubevirt-config
にfeature-gates
という項目を追加します。
feature-gates
でLiveMigrationを有効にしていない場合、以下のようなメッセージが出力されます。なお、ここでは前章で利用したvm.yaml
をデプロイし、VMを起動済みの状態です。
[root@kube-master01 kubevirt]# virtctl migrate testvm Error migrating VirtualMachine an error on the server ("admission webhook \"migration-create-validator.kubevirt.io\" denied the request: LiveMigration feature gate is not enabled in kubevirt-config") has prevented the request from succeeding [root@kube-master01 kubevirt]#
LiveMigrationを有効にするため、kubectl edit
コマンドでkubevirt-config
を編集します。
# kubevirt-configの内容確認 [root@kube-master01 kubevirt]# kubectl get cm kubevirt-config -n kubevirt -o yaml apiVersion: v1 data: debug.useEmulation: "true" kind: ConfigMap metadata: creationTimestamp: "2019-09-16T02:19:25Z" name: kubevirt-config namespace: kubevirt resourceVersion: "754300" selfLink: /api/v1/namespaces/kubevirt/configmaps/kubevirt-config uid: f504ca79-d38d-496e-b66f-67e7dc01af15 [root@kube-master01 kubevirt]# # 編集 [root@kube-master01 kubevirt]# kubectl edit cm kubevirt-config -n kubevirt configmap/kubevirt-config edited [root@kube-master01 kubevirt]# # 結果確認 [root@kube-master01 kubevirt]# kubectl get cm kubevirt-config -n kubevirt -o yaml apiVersion: v1 data: debug.useEmulation: "true" feature-gates: LiveMigration kind: ConfigMap metadata: creationTimestamp: "2019-09-16T02:19:25Z" name: kubevirt-config namespace: kubevirt resourceVersion: "759389" selfLink: /api/v1/namespaces/kubevirt/configmaps/kubevirt-config uid: f504ca79-d38d-496e-b66f-67e7dc01af15 [root@kube-master01 kubevirt]#
マイグレーションできるVMの条件
上記の通りLiveMigrationを有効化したので、改めてvirtctl migrate
コマンドを実行してみます。すると、別のエラーメッセージが出力されます。
[root@kube-master01 kubevirt]# virtctl migrate testvm Error migrating VirtualMachine an error on the server ("admission webhook \"migration-create-validator.kubevirt.io\" denied the request: Cannot migrate VMI, Reason: InterfaceNotLiveMigratable, Message: cannot migrate VMI with a bridge interface connected to a pod network") has prevented the request from succeeding [root@kube-master01 kubevirt]#
上記メッセージより、Podネットワークと接続されたbridgeインターフェイスに紐づけられたVMはマイグレーションできないことがわかります。
※また、VirtualMachineInstance
のみで動いている場合も、マイグレーションは実行できず、以下のようなメッセージが出力されます。
[root@kube-master01 kubevirt]# virtctl migrate help Error migrating VirtualMachine the server could not find the requested resource [root@kube-master01 kubevirt]#
ここでは以下のようなyamlファイルを作成し、VirtualMachine
リソースをデプロイします。ポイントはinterfaces
の部分で、何も指定しない場合はデフォルトでbridge
インターフェイスが利用されます。
※下記リソースはあくまでvirtctl migrate
コマンドでマイグレーションをするためだけに作ったものであり、VMへのログインはできません。
apiVersion: kubevirt.io/v1alpha3 kind: VirtualMachine metadata: name: testvm-nocloud spec: running: false template: metadata: labels: kubevirt.io/domain: testvm-nocloud spec: terminationGracePeriodSeconds: 30 domain: resources: requests: memory: 1024M devices: disks: - name: containerdisk disk: bus: virtio - name: emptydisk disk: bus: virtio - disk: bus: virtio name: cloudinitdisk interfaces: # ここからInterfaceの設定 - name: default model: e1000 masquerade: {} ports: - name: http port: 80 networks: - name: default pod: {} volumes: - name: containerdisk containerDisk: image: kubevirt/fedora-cloud-container-disk-demo:latest - name: emptydisk emptyDisk: capacity: "2Gi" - name: cloudinitdisk cloudInitNoCloud: userData: |- #cloud-config password: fedora chpasswd: { expire: False }
KubevirtでデプロイするVMのInterfaceにはFrontend
とBackend
の2種類があり、ここではFrontend
側を明示的にmasquerade
を指定しています。
Backend
- pod:デフォルトのKubernetesネットワーク
- multus:Multusを利用した場合のネットワーク
- genie:Genieを利用した場合のネットワーク
Frontend
なお、Interfaceについてはこちらに記載されています。
上記yamlファイルをデプロイし、virtctl migrate
コマンドも実行してみます。ここでVirtualMachineInstance
の存在するノードがkube-worker02
であることに注目しておきます。
# VirtualMachineデプロイ [root@kube-master01 kubevirt]# kubectl apply -f testvm-nocloud.yaml virtualmachine.kubevirt.io/testvm-nocloud created [root@kube-master01 kubevirt]# kubectl get vm NAME AGE RUNNING VOLUME testvm-nocloud 4s false [root@kube-master01 kubevirt]# # VirtualMachineの起動 [root@kube-master01 kubevirt]# virtctl start testvm-nocloud VM testvm-nocloud was scheduled to start [root@kube-master01 kubevirt]# kubectl get vmi NAME AGE PHASE IP NODENAME testvm-nocloud 22s Running 192.168.247.225 kube-worker02 [root@kube-master01 kubevirt]# # virtctl migrate [root@kube-master01 kubevirt]# virtctl migrate testvm-nocloud VM testvm-nocloud was scheduled to migrate [root@kube-master01 kubevirt]#
virtctl migrate
コマンドを実行すると、VirtualMachineInstanceMigration
リソースが作成されます。
[root@kube-master01 kubevirt]# kubectl get vmim NAME AGE kubevirt-migrate-vm-z74pf 42s [root@kube-master01 kubevirt]# kubectl get vmim kubevirt-migrate-vm-z74pf -o yaml apiVersion: kubevirt.io/v1alpha3 kind: VirtualMachineInstanceMigration metadata: annotations: kubevirt.io/latest-observed-api-version: v1alpha3 kubevirt.io/storage-observed-api-version: v1alpha3 creationTimestamp: "2019-09-16T08:42:12Z" generateName: kubevirt-migrate-vm- generation: 8 name: kubevirt-migrate-vm-z74pf namespace: default resourceVersion: "811626" selfLink: /apis/kubevirt.io/v1alpha3/namespaces/default/virtualmachineinstancemigrations/kubevirt-migrate-vm-z74pf uid: 357ae1ad-afa3-4566-9672-cb83eb1b45d2 spec: vmiName: testvm-nocloud status: phase: Succeeded [root@kube-master01 kubevirt]#
上記出力結果のうちstatus.phase
がSucceeded
になっていればマイグレーションは完了しています。もう一度VirtualMachineInstance
を確認してみると、ノードが変化しkube-worker01
となっているのがわかります。
[root@kube-master01 kubevirt]# kubectl get vmi NAME AGE PHASE IP NODENAME testvm-nocloud 2m35s Running 192.168.247.225 kube-worker01 [root@kube-master01 kubevirt]#
またマイグレーション実行後にVirtualMachineInstance
をyaml形式で出力すると、status.migrationState
が追加され、マイグレーションに関する情報が確認できます。
kubectl get vmi testvm-nocloud -o yaml
apiVersion: v1 items: - apiVersion: kubevirt.io/v1alpha3 kind: VirtualMachineInstance metadata: annotations: kubevirt.io/latest-observed-api-version: v1alpha3 kubevirt.io/storage-observed-api-version: v1alpha3 creationTimestamp: "2019-09-16T08:41:14Z" finalizers: - foregroundDeleteVirtualMachine generateName: testvm-nocloud generation: 14 labels: kubevirt.io/domain: testvm-nocloud kubevirt.io/migrationTargetNodeName: kube-worker01 kubevirt.io/nodeName: kube-worker01 name: testvm-nocloud namespace: default ownerReferences: - apiVersion: kubevirt.io/v1alpha3 blockOwnerDeletion: true controller: true kind: VirtualMachine name: testvm-nocloud uid: 8e6456b2-680f-4a32-bdfe-ae854c00d303 resourceVersion: "811625" selfLink: /apis/kubevirt.io/v1alpha3/namespaces/default/virtualmachineinstances/testvm-nocloud uid: aaa2d6eb-0792-43e8-a60e-90cb6611154e spec: domain: devices: disks: - disk: bus: virtio name: containerdisk - disk: bus: virtio name: emptydisk - disk: bus: virtio name: cloudinitdisk interfaces: - masquerade: {} model: e1000 name: default ports: - name: http port: 80 features: acpi: enabled: true firmware: uuid: 2ce78280-4328-516d-b2db-3fac09b758d4 machine: type: q35 resources: requests: cpu: 100m memory: 1024M networks: - name: default pod: {} terminationGracePeriodSeconds: 30 volumes: - containerDisk: image: kubevirt/fedora-cloud-container-disk-demo:latest imagePullPolicy: Always name: containerdisk - emptyDisk: capacity: 2Gi name: emptydisk - cloudInitNoCloud: userData: |- #cloud-config password: fedora chpasswd: { expire: False } name: cloudinitdisk status: conditions: - lastProbeTime: null lastTransitionTime: null status: "True" type: LiveMigratable - lastProbeTime: null lastTransitionTime: "2019-09-16T08:42:53Z" status: "True" type: Ready interfaces: - ipAddress: 192.168.247.225 mac: 02:00:00:4c:c8:23 name: default migrationMethod: BlockMigration migrationState: completed: true endTimestamp: "2019-09-16T08:42:59Z" migrationUid: 357ae1ad-afa3-4566-9672-cb83eb1b45d2 sourceNode: kube-worker02 startTimestamp: "2019-09-16T08:42:53Z" targetDirectMigrationNodePorts: "34438": 49152 "35614": 0 "38218": 49153 targetNode: kube-worker01 targetNodeAddress: 192.168.132.22 targetNodeDomainDetected: true targetPod: virt-launcher-testvm-nocloud-887f9 nodeName: kube-worker01 phase: Running qosClass: Burstable kind: List metadata: resourceVersion: "" selfLink: ""
なお、マイグレーションに関する設定を変更するにはkubevirt-config
を変更すればよいようです。
apiVersion: v1 kind: ConfigMap metadata: name: kubevirt-config namespace: kubevirt labels: kubevirt.io: "" data: feature-gates: "LiveMigration" migrations: |- parallelMigrationsPerCluster: 5 parallelOutboundMigrationsPerNode: 2 bandwidthPerMigration: 64Mi completionTimeoutPerGiB: 800 progressTimeout: 150
最後に
今回はKubevirt v0.21.0について、少しだけ紹介しました。ここで紹介しただけでなく、CDI (Containerized Data Importer)を利用してVMイメージを管理したりもできます。
まだ検証が進められていないので何とも言えませんが、VMとコンテナを共通基盤・共通コマンドで管理することができる、というコンセプトは、やはり一定の需要があると思われます。本番環境で利用するにはまだ不安定な部分があるようですが、今後開発が進めば本番環境での利用もあり得るのでは、と考えています。今後もKubevirtについてはウォッチしていこうと思います。