原文連接:https://fuckcloudnative.io/posts/use-kubevirt-to-manage-windows-on-kubernetes/php
最近我發現個人 Kubernetes
集羣資源實在是太多了,有點浪費,不信你看:node
既然閒置資源那麼多,那我何不想辦法利用一下。怎麼用,用來幹什麼又是一個問題,想到我手中只有 MacBook,缺乏 Windows 操做系統,那就先想辦法用 Kubernetes 建立個 Windows 虛擬機用用吧,畢竟不少場景只能用 Windows(好比突破某盤的限速、Xshell 一把梭鏈接全部服務器)。因而我將目光轉向了 Kubevirt。linux
Kubevirt
是 Red Hat 開源的以容器方式運行虛擬機的項目,經過 CRD
的方式來管理虛擬機實例,它的全部概念都和通常的 Kubernetes 容器應用差很少,不須要增長學習成本,對於咱玩爛了容器的 YAML 工程師來講沒有任何壓力,咱們能夠直接用它來建立虛擬機啊。git
Kubevirt 主要實現了下面幾種資源,以實現對虛擬機的管理:github
VirtualMachineInstance(VMI)
: 相似於 kubernetes Pod,是管理虛擬機的最小資源。一個 VirtualMachineInstance
對象即表示一臺正在運行的虛擬機實例,包含一個虛擬機所須要的各類配置。VirtualMachine(VM)
: 爲羣集內的 VirtualMachineInstance
提供管理功能,例如開機/關機/重啓虛擬機,確保虛擬機實例的啓動狀態,與虛擬機實例是 1:1 的關係,相似與 spec.replica
爲 1 的 StatefulSet。VirtualMachineInstanceReplicaSet
: 相似 ReplicaSet
,能夠啓動指定數量的 VirtualMachineInstance
,而且保證指定數量的 VirtualMachineInstance
運行,能夠配置 HPA。Kubevirt 的總體架構如圖:docker
console, vnc, startvm, stopvm
等。libvirtd
,用於啓動和管理虛擬機。若是你嫌上面的架構圖太繁瑣,這裏還有一個簡化版:shell
這個圖裏的 Agent 其實就是 virt-handler。json
虛擬機鏡像(磁盤)是啓動虛擬機必不可少的部分,KubeVirt 中提供多種方式的虛擬機磁盤,虛擬機鏡像(磁盤)使用方式很是靈活。這裏列出幾種比較經常使用的:windows
hostpath
,也能夠在初始化時建立空的鏡像。在安裝 Kubevirt 以前,須要作一些準備工做。先安裝 libvrt 和 qemu 軟件包:後端
# Ubuntu $ apt install -y qemu-kvm libvirt-bin bridge-utils virt-manager # CentOS $ yum install -y qemu-kvm libvirt virt-install bridge-utils
查看節點是否支持 kvm 硬件輔助虛擬化
$ virt-host-validate qemu QEMU: Checking for hardware virtualization : PASS QEMU: Checking if device /dev/kvm exists : PASS QEMU: Checking if device /dev/kvm is accessible : PASS QEMU: Checking if device /dev/vhost-net exists : PASS QEMU: Checking if device /dev/net/tun exists : PASS QEMU: Checking for cgroup 'memory' controller support : PASS QEMU: Checking for cgroup 'memory' controller mount-point : PASS QEMU: Checking for cgroup 'cpu' controller support : PASS QEMU: Checking for cgroup 'cpu' controller mount-point : PASS QEMU: Checking for cgroup 'cpuacct' controller support : PASS QEMU: Checking for cgroup 'cpuacct' controller mount-point : PASS QEMU: Checking for cgroup 'cpuset' controller support : PASS QEMU: Checking for cgroup 'cpuset' controller mount-point : PASS QEMU: Checking for cgroup 'devices' controller support : PASS QEMU: Checking for cgroup 'devices' controller mount-point : PASS QEMU: Checking for cgroup 'blkio' controller support : PASS QEMU: Checking for cgroup 'blkio' controller mount-point : PASS QEMU: Checking for device assignment IOMMU support : PASS QEMU: Checking if IOMMU is enabled by kernel : PASS
若是不支持,則先生成讓 Kubevirt 使用軟件虛擬化的配置:
$ kubectl create namespace kubevirt $ kubectl create configmap -n kubevirt kubevirt-config \ --from-literal debug.useEmulation=true
$ export VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases | grep tag_name | grep -v -- '-rc' | head -1 | awk -F': ' '{print $2}' | sed 's/,//' | xargs) $ kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-operator.yaml $ kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-cr.yaml
查看部署結果:
$ kubectl -n kubevirt get pod NAME READY STATUS RESTARTS AGE virt-api-64999f7bf5-n9kcl 1/1 Running 0 6d virt-api-64999f7bf5-st5qv 1/1 Running 0 6d8h virt-controller-8696ccdf44-v5wnq 1/1 Running 0 6d virt-controller-8696ccdf44-vjvsw 1/1 Running 0 6d8h virt-handler-85rdn 1/1 Running 3 7d19h virt-handler-bpgzp 1/1 Running 21 7d19h virt-handler-d55c7 1/1 Running 1 7d19h virt-operator-78fbcdfdf4-sf5dv 1/1 Running 0 6d8h virt-operator-78fbcdfdf4-zf9qr 1/1 Running 0 6d
Containerized Data Importer
(CDI)項目提供了用於使 PVC 做爲 KubeVirt VM 磁盤的功能。建議同時部署 CDI:
$ 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
Kubevirt 提供了一個命令行工具 virtctl
,能夠直接下載:
$ export VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases | grep tag_name | grep -v -- '-rc' | head -1 | awk -F': ' '{print $2}' | sed 's/,//' | xargs) $ curl -L -o /usr/local/bin/virtctl https://github.com/kubevirt/kubevirt/releases/download/$VERSION/virtctl-$VERSION-linux-amd64 $ chmod +x /usr/local/bin/virtctl
也能夠經過 krew
安裝爲 kubectl 的插件:
$ kubectl krew install virt
這裏推薦兩個 Windows 鏡像下載站:
① MSDN I Tell You。該網站提供的連接是 ed2k
格式,須要經過特殊下載工具進行下載,好比百度網盤離線下載、迅雷、eMule 等,其中百度網盤離線下載最好使,但下載限速又是個大問題,開了超級會員的當我沒說。
② TechBench by WZT。該網站提供的是直鏈下載方式,能夠用任意下載工具進行下載,比上面的網站方便多了,不過資源沒有上面的網站豐富。
我推薦經過第二個網站來下載 Windows 鏡像。
KubeVirt 可使用 PVC 做爲後端磁盤,使用 filesystem
類型的 PVC 時,默認使用的時 /disk.img
這個鏡像,用戶能夠將鏡像上傳到 PVC,在建立 VMI 時使用此 PVC。使用這種方式須要注意下面幾點:
/disk.img
的格式必須是 RAW 格式CDI 提供了使用使用 PVC 做爲虛擬機磁盤的方案,在虛擬機啓動前經過下面方式填充 PVC:
ContainerDisk
使用經過命令行 virtctl
,結合 CDI 項目,能夠上傳本地鏡像到 PVC 上,支持的鏡像格式有:
咱們的目標是安裝 Windows 10 虛擬機,因此須要將上面下載好的 Windows 鏡像上傳到 PVC:
$ virtctl image-upload \ --image-path='Win10_20H2_Chinese(Simplified)_x64.iso' \ --storage-class csi-rbd-sc \ --pvc-name=iso-win10 \ --pvc-size=7G \ --uploadproxy-url=https://<cdi-uploadproxy_svc_ip> \ --insecure \ --wait-secs=240 PersistentVolumeClaim default/iso-win10 created Waiting for PVC iso-win10 upload pod to be ready... Pod now ready Uploading data to https://10.111.29.156 5.63 GiB / 5.63 GiB [======================================================================================================================================================] 100.00% 27s Uploading data completed successfully, waiting for processing to complete, you can hit ctrl-c without interrupting the progress Processing completed successfully Uploading Win10_20H2_Chinese(Simplified)_x64.iso completed successfully
參數解釋:
kubectl -n cdi get svc -l cdi.kubevirt.io=cdi-uploadproxy
來查看。Kubevirt 默認沒有開啓對 hostDisk
的支持,須要手動開啓。步驟也很簡單,只需新建個 ConfigMap,增長 hostDisk
的特性:
kubevet-config.yaml
apiVersion: v1 data: feature-gates: LiveMigration,DataVolumes,HostDisk kind: ConfigMap metadata: labels: kubevirt.io: "" name: kubevirt-config namespace: kubevirt
建立 Windows 虛擬機的模板文件以下:
win10.yaml
apiVersion: kubevirt.io/v1alpha3 kind: VirtualMachine metadata: name: win10 spec: running: false template: metadata: labels: kubevirt.io/domain: win10 spec: domain: cpu: cores: 4 devices: disks: - bootOrder: 1 cdrom: bus: sata name: cdromiso - disk: bus: virtio name: harddrive - cdrom: bus: sata name: virtiocontainerdisk interfaces: - masquerade: {} model: e1000 name: default machine: type: q35 resources: requests: memory: 16G networks: - name: default pod: {} volumes: - name: cdromiso persistentVolumeClaim: claimName: iso-win10 - name: harddrive hostDisk: capacity: 50Gi path: /data/disk.img type: DiskOrCreate - containerDisk: image: kubevirt/virtio-container-disk name: virtiocontainerdisk
這裏用到了 3 個 Volume:
iso-win10
。hostDisk
直接掛載到宿主機以提高性能,若是使用分佈式存儲則體驗很是很差。關於網絡部分,spec.template.spec.networks
定義了一個網絡叫 default
,這裏表示使用 Kubernetes 默認的 CNI。spec.template.spec.domain.devices.interfaces
選擇定義的網絡 default,並開啓 masquerade
,以使用網絡地址轉換 (NAT) 來經過 Linux 網橋將虛擬機鏈接至 Pod 網絡後端。
使用模板文件建立虛擬機:
$ kubectl apply -f win10.yaml
啓動虛擬機實例:
$ virtctl start win10 # 若是 virtctl 安裝爲 kubectl 的插件,命令格式以下: $ kubectl virt start win10
查看實例運行狀態:
$ kubectl get pod NAME READY STATUS RESTARTS AGE virt-launcher-win10-s742j 2/2 Running 0 15s
而後就能夠經過 VNC 工具來訪問 Windows 虛擬機了。首先須要在本地安裝一個 VNC 客戶端,對於 macOS 來講,能夠安裝 Tiger VNC 或者 Real VNC。我選擇安裝 Real VNC:
$ brew cask install vnc-viewer
鏈接到 Windows 虛擬機:
$ virtctl vnc win10 # 若是 virtctl 安裝爲 kubectl 的插件,命令格式以下: $ kubectl virt vnc win10
執行完上面的命令後,就會打開本地的 VNC 客戶端鏈接到虛擬機:
下面就是安裝正常的安裝步驟往下進行,到選擇硬盤那一步的時候,你會發現沒有一個硬盤可供使用,這時就須要安裝 virtio 驅動了。
不過不用擔憂,virtio 驅動已經被掛載進來了,直接點擊加載驅動程序就能夠安裝驅動了:
安裝好驅動後,硬盤就能正確顯示了:
下面就能夠繼續安裝了。
安裝成功後會自動重啓進行初始化設置,那個熟悉的「海內存知己,天涯若比鄰」又回來了:
設置完成後,進入系統,打開設備管理器,能夠看到有幾個未配置的設備。選擇其中一個右鍵單擊,而後選擇「更新驅動程序」。
選擇「瀏覽個人電腦以查找驅動程序」。
選擇「CD 驅動器(E:)virtio-win-0.1.1」,而後點擊肯定。
設備管理器將自動找到正確的驅動程序,不須要指定驅動程序的路徑。
在提示符下,單擊「安裝」。
其餘的設備驅動能夠複製上面的步驟一一安裝。
若是你的 Kubernetes 集羣 CNI 插件用的是 Calico,這裏會遇到虛擬機沒法聯網的問題。由於 Calico 默認禁用了容器的 ip forward 功能,而 masquerade
須要開啓這個功能才能生效。
咱們只須要修改 Calico 的 ConfigMap 就能夠啓用容器的 ip forward 功能了,執行如下命令打開 configmap calico-config
:
$ kubectl -n kube-system edit cm calico-config
在 CNI 配置文件中加上如下的內容:
"container_settings": { "allow_ip_forwarding": true },
修改完的配置文件內容:
cni_network_config: |- { "name": "k8s-pod-network", "cniVersion": "0.3.1", "plugins": [ { "type": "calico", "log_level": "info", "log_file_path": "/var/log/calico/cni/cni.log", "etcd_endpoints": "__ETCD_ENDPOINTS__", "etcd_key_file": "__ETCD_KEY_FILE__", "etcd_cert_file": "__ETCD_CERT_FILE__", "etcd_ca_cert_file": "__ETCD_CA_CERT_FILE__", "mtu": __CNI_MTU__, "ipam": { "type": "calico-ipam" }, "container_settings": { "allow_ip_forwarding": true }, "policy": { "type": "k8s" }, "kubernetes": { "kubeconfig": "__KUBECONFIG_FILEPATH__" } }, { "type": "portmap", "snat": true, "capabilities": {"portMappings": true} }, { "type": "bandwidth", "capabilities": {"bandwidth": true} } ] }
而後重啓 calico-node 容器:
$ kubectl -n kube-system delete pod -l k8s-app=calico-node
在系統未安裝好以前,只能用 VNC 來遠程控制,但 VNC 的體驗實在讓人難受。如今系統裝好了,就可使用 Windows 的遠程鏈接協議 RDP(Remote Desktop Protocol) 了。選擇開始 >設置 >系統>遠程桌面,打開啓用遠程桌面就行了。
如今能夠經過 telnet 來測試一下 RDP 端口(3389
)的連通性:
$ kubectl get pod -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES virt-launcher-win10-s742j 2/2 Running 0 139m 100.92.235.131 k8s03 <none> <none> $ telnet 100.92.235.131 3389 Trying 100.92.235.131... Connected to 100.92.235.131. Escape character is '^]'.
若是你的本地電腦可以直連 Pod IP
和 SVC IP
,如今就能夠直接經過 RDP 客戶端來遠程鏈接 Windows 了。若是你的本地電腦不能直連 Pod IP
和 SVC IP
,但能夠直連 Kubernetes 集羣的 Node IP
,能夠經過 NodePort
來暴露 RDP 端口。具體操做是建立一個 Service,類型爲 NodePort:
$ kubectl virt expose vm win10 --name win10-rdp --port 3389 --target-port 3389 --type NodePort $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17d win10-rdp NodePort 10.98.20.203 <none> 3389:31192/TCP 20m
而後就能夠經過 Node IP
來遠程鏈接 Windows 了。
若是你的本地操做系統是 Windows 10,能夠在任務欄的搜索框中,鍵入「遠程桌面鏈接」,而後選擇「遠程桌面鏈接」。在「遠程桌面鏈接」中,鍵入你想要鏈接的電腦的名稱(從步驟 1),而後選擇「鏈接」。
若是你的本地操做系統是 macOS
,須要在 App Store 中安裝 Microsoft Remote Desktop
。
安裝完以後打開應用,選擇 Add PC:
在 PC name 一欄中輸入 NodeIP+NodePort
,而後點擊 Add。
而後右擊建立好的配置,選擇 Connect:
輸入帳號密碼後就能夠鏈接到 Windows 了。
全屏以後就能夠得到完美的遠程桌面體驗了,盡情玩耍吧!
Kubernetes 1.18.2 1.17.5 1.16.9 1.15.12離線安裝包發佈地址http://store.lameleg.com ,歡迎體驗。 使用了最新的sealos v3.3.6版本。 做了主機名解析配置優化,lvscare 掛載/lib/module解決開機啓動ipvs加載問題, 修復lvscare社區netlink與3.10內核不兼容問題,sealos生成百年證書等特性。更多特性 https://github.com/fanux/sealos 。歡迎掃描下方的二維碼加入釘釘羣 ,釘釘羣已經集成sealos的機器人實時能夠看到sealos的動態。