KubeVirt介紹與初步教學使用
Tags: kubernetes, devops
Published: 2020-06-18 08:24:59


# KubeVirt介紹與初步教學使用
##### tags:`Kubernetes`、`KubeVirt`、`Minikube`、`Openshift`、`DevOps`

![](https://i.imgur.com/EEDLGjf.png)

## 官方介紹

先來看看官方介紹 :)

**KubeVirt** is a virtual machine management add-on for Kubernetes. The aim is to provide a common ground for virtualization solutions on top of Kubernetes.

**Note**: KubeVirt is a heavy work in progress.

David introduces the talk showing what KubeVirt is and what is not:
* KubeVirt is not involved with managing AWS or GCP instances
* KubeVirt is not a competitor to Firecracker or Kata containers
* KubeVirt is not a container runtime replacement

**He likes to define KubeVirt as:**
KubeVirt is a Kubernetes extension that allows running traditional VM workloads natively side by side with Container workloads.


## 介紹

KubeVirt 是基於 Kubernetes ，在2017由RedHat發起。

主要目標是讓一些Legacy與Monolith的服務不相容容器化時，可以運用KubeVirt來達成目的。

或是在Deep learning需要使用GPU、vGPU時，可以調用。
NVIDIA 有[Plugin](https://github.com/NVIDIA/kubevirt-gpu-device-plugin)。

### 運行模式

![](https://cdn-images-1.medium.com/max/1600/1*cVoRd4SuwPwnUjhIeUVl1Q.png)

由上圖可以得知，KubeVirt運作原理與Kubernetes相似，因為是基於K8s XD

那最末端都是Pods，一邊是Pod 包 VM ，一邊是 Pod 包 Container。

上層也是透過API Server -> kubelet 來去溝通，所以KubeVirt 遵照[Custom Resource Definition](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) (CRD) 來制定Type。

而Cluster的Controller會與Node的Daemons遵照KubeVirt的邏輯去啟用運行或移除運行。

而VM的volume則是透過Kubernetes的PVC來去達成。

那VM是如何跑在Pod？

![](https://cdn-images-1.medium.com/max/1600/1*vwX_8e5K6tXdKaSQEX5Qfg.png)

透過上圖可以看出是透過KVM + Qemu來達成。

更細節可以去看[Github](https://github.com/kubevirt/kubevirt) XD

因為說那麼多，還是先來個實作吧！更好去理解如何運行囉:)

GO!

## 實作1

這邊使用Minikube實作，請先去官網安裝 :) 。

P.S. 筆者偷懶使用MAC，記得要裝KVM & Qemu。

### 啟用minikube

```
$ minikube start --memory=4096 --cpus=2 --network-plugin cni
```
P.S. vm-driver kvm2

這邊會使用KubeVirt的版本為v0.30.0，那也可以使用最新的。

```
# On other OS you might need to define it like
$ export KUBEVIRT_VERSION="v0.30.0"
# On Linux you can obtain it using 'curl' via:
$ export KUBEVIRT_VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases | grep tag_name | grep -v -- - | sort -V | tail -1 | awk -F':' '{print $2}' | sed 's/,//' | xargs)
```

版本確認後，直接使用github上的yaml。

```
$ kubectl create -f https://github.com/kubevirt/kubevirt/releases/download/$KUBEVIRT_VERSION/kubevirt-operator.yaml
```
![](https://cdn-images-1.medium.com/max/2400/1*hl2EBSyj0f2FaswOnSPDMw.png)

有Custom Resource Definition、RBAC以及deployment等等。
看一下建立了什麼。

```
$ kubectl get all -n kubevirt
```
![](https://cdn-images-1.medium.com/max/2400/1*lYvtNT0h1sxF72_9nDR2Fw.png)

查看Virtualization Extensions

```
# To check if your VM's CPU supports virtualization extensions execute the following command:
$ minikube ssh -p kubevirt "egrep 'svm|vmx' /proc/cpuinfo"
# If the command doesn't generate any output, create the following ConfigMap so that KubeVirt uses emulation mode, otherwise skip to the next section
$ kubectl create configmap kubevirt-config -n kubevirt --from-literal debug.useEmulation=true
```

確認好之後，來到最重要的時刻 - > **Deploy KubeVirt**。
專屬的**custom resource**。

```
$ kubectl create -f https://github.com/kubevirt/kubevirt/releases/download/$KUBEVIRT_VERSION/kubevirt-cr.yaml
```
查看部署了什麼！
```
$ kubectl get all -n kubevirt
```
![](https://cdn-images-1.medium.com/max/2400/1*8tTTTOmIGUgZCouexUuLRg.png)

那有了這些，才可以透過`virtctl` or `kubectl virt` 來呼叫API Server並且正確運行。

這裡使用Krew來快速安裝kubectl plugins，如沒使用過請參考此篇。
kubectl krew install virt


事前準備都好了！這裡就直接使用官方的VM！官方的registry disk。

有 alpine, cirros and fedora，這邊使用kubevirt/cirros-registry-disk-demo。

```
# 載下來查
$ curl -L -o vm.yaml https://raw.githubusercontent.com/kubevirt/kubevirt.github.io/master/labs/manifests/vm.yaml
$ less vm.yaml
# 直接使用
$ kubectl apply -f https://raw.githubusercontent.com/kubevirt/kubevirt.github.io/master/labs/manifests/vm.yaml
# 查看
$ kubectl get vms
```
![](https://cdn-images-1.medium.com/max/2400/1*qrTaMRu9ronizeyQOMBCUQ.png)


OK! 建立完成，到這裡就可以直接啟用VM囉，透過kubectl virt來啟用。

P.S. 要啟用原因是vm.yaml第六行 running: false 。

```
# 啟用
$ kubectl virt start testvm
# 查看
$ kubectl get vmis
```

![](https://cdn-images-1.medium.com/max/1600/1*4s-X8UBN6qSP1-NxLainlg.png)

![](https://cdn-images-1.medium.com/max/1600/1*SdzgUEYv1WzKvpzxL3lpVg.png)



這裡連進去試試看有沒有成功。
```
$ kubectl virt console testvm
```
P.S. Disconnect from the virtual machine console by typing:`ctrl+]`.

![](https://cdn-images-1.medium.com/max/1600/1*dwbpjNqN79DsCysZJfm4sw.png)

### Cleanup
```
$ kubectl virt stop testvm
$ kubectl delete vm testvm
$ minikube stop
$ minikube delete
```

## 實作2

### 啟用Minikube
一樣使用minikube，此次是使用
 Ubuntu 18.04.4 LTS (GNU/Linux 5.0.0–1032-azure x86_64)
 
這裡要注意KVM有沒有已經啟用。

```
$ cat /sys/module/kvm_intel/parameters/nested
```

要回Y，如果不是要去啟用:)

```
$ minikube config -p kubevirt set memory 8192
$ minikube config -p kubevirt set cpus 4
$ minikube config -p kubevirt set vm-driver kvm2
$ minikube config -p kubevirt set disk-size 50g
$ minikube start -p kubevirt --network-plugin cni
```

那這裡的實作是！！！
使用Windows server 2012 ISO！！！

> 注意

這裡要多裝一個「CDI」
KubeVirt and CDI are already installed.

P.S. 實作1的還是要再重裝唷:)

這裡使用的版本為v1.18.0

```
$ export VERSION=$(curl -s https://github.com/kubevirt/containerized-data-importer/releases/latest | grep -o "v[0-9]\.[0-9]*\.[0-9]*")
$ 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
```

什麼是CDI?
Containerized-Data-Importer (CDI)，也就是除了從url來以外，也可以從PVC或是上傳檔案。

那這裡create後，來看看svc。

```
$ kubectl get services -n cdi
```

![](https://cdn-images-1.medium.com/max/1600/1*XCBgVZErknAKdnCCBn-6_w.png)

OK！那這裡的題目是使用Windows Server2012 64bit，所以到[Microsoft Evaluation Center](https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2012-r2)下載ISO file。

那下載完後，就要使用kubectl virt上傳，這裡介紹等等有使用的參數。

* `image-upload`: Upload a VM image to a PersistentVolumeClaim
* `--image-path`: The path of the ISO file
* `--pvc-nam`e: The name of the PVC to store the ISO file, in this example is iso-win2k12
* `--access-mode`: the access mode for the PVC, in the example ReadOnlyMany has been used.
* `--pvc-size`: The size of the PVC, is where the ISO will be stored, in this case, the ISO is 4.3G so a PVC OS 5G should be enough
* `--uploadproxy-url`: The URL of the cdi-upload proxy service

那會看到svc是ClusterIP，為了方便，額外再創一個NodePort！

```
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
 name: cdi-uploadproxy-nodeport
 namespace: cdi
 labels:
   cdi.kubevirt.io: "cdi-uploadproxy"
spec:
 type: NodePort
 ports:
   - port: 443
     targetPort: 8443
     nodePort: 31001
     protocol: TCP
 selector:
   cdi.kubevirt.io: cdi-uploadproxy
EOF
```

建立完成後，使用minikube參數來看url。

```
minikube service cdi-uploadproxy-nodeport --url -n cdi -p kubevirt
```

請記得替換 `--uploadproxy-url`

```
$ kubectl virt image-upload \
   --image-path=9600.17050.WINBLUE_REFRESH.140317-1640_X64FRE_SERVER_EVAL_EN-US-IR3_SSS_X64FREE_EN-US_DV9.ISO \
   --pvc-name=iso-win2k12 \
   --access-mode=ReadOnlyMany \
   --pvc-size=5G \
   --uploadproxy-url=https://192.168.39.45:31001 \
   --insecure \
   --wait-secs=240
```

* `--insecure`: Allow insecure server connections when using HTTPS
* `--wait-secs`: The time in seconds to wait for upload pod to start. (default 60)

![](https://cdn-images-1.medium.com/max/2400/1*dimYiGkD3AUQv4_IeJK6uw.png)

上傳成功！

P.S. 這裡要注意，image-upload 會創建一個DataVolume，會有一個Pod與PVC做連接，如果失敗要查看一下是否為PVC問題~

接下來先準備被掛載的PVC以及主要運行的VirtualMachine。

{%gist https://gist.github.com/tass-lin/120f7df15d95fc11ec85ac3865165938 %}


然後先把`virtio` 的 image載到本機端。

P.S.  A container with the virtio drivers attached as a CD-ROM to the VM. The container image has to be pulled to have it available in the local registry.

```
docker pull kubevirt/virtio-container-disk
```

創建[win2k12.yml](https://gist.github.com/tass-lin/4710df0a48f057d93570046ea302f144)並啟用。

P.S. 這邊也要注意PVC掛載情況。

```
kubectl apply -f win2k12.yml
kubectl virt start win2k12-iso
```

看看有沒有成功

```
kubectl get vmi
```

成功了！！

![](https://cdn-images-1.medium.com/max/1600/1*tNSMVdj8D5MxJEN7Gb2TTA.png)

到這裡成功Run起一台VM了！來連線進去吧！

```
kubectl virt vnc win2k12-iso
```

![](https://cdn-images-1.medium.com/max/1600/1*elmOhrLtQNfNDHWO99nnYw.png)

詳細安裝就直接來看官方的[影片](https://kubevirt.io/assets/2020-02-14-KubeVirt-installing_Microsoft_Windows_from_an_iso/kubevirt_install_windows.mp4)吧！

### Cleanup

```
$ minikube delete -p kubevirt
```

## 結論

那Kubevirt也解決了Container不方便或是無法解決的事情，VM統包XDD
所有服務都是慢慢變成熟的XD，那Kubevirt也是，如果現在要拿來用於Production，就是要慢慢踩坑囉~。其實也蠻多前輩及大神在踩，更新及維護也是Github上飄來飄去的大神，更版與回覆速度並不慢。
在此介紹及試用:)


## 參考

[https://github.com/kubevirt/kubevirt](https://github.com/kubevirt/kubevirt)

[https://kubevirt.io/](https://kubevirt.io/)

[https://kubevirt.io/2020/KubeVirt_deep_dive-virtualized_gpu_workloads.html](https://kubevirt.io/2020/KubeVirt_deep_dive-virtualized_gpu_workloads.html)

[https://kubevirt.io/2020/Live-migration.html](https://kubevirt.io/2020/Live-migration.html)