隨著Docker和Kubernetes生態圈的發展,云計算領域對容器的興趣達到了狂熱的程度。容器技術為應用程序提供了隔離的運行空間,每個容器內都包含一個獨享的完整用戶環境空間,容器內的變動不會影響其他容器的運行環境。因為容器之間共享同一個系統內核,當同一個庫被多個容器使用時,內存的使用效率會得到提升?;谖锢碇鳈C操作系統內核的,那就意味著對于不同內核或者操作系統需求的應用是不可能部署在一起的。
虛擬化技術則是提供了一個完整的虛擬機,為用戶提供了不依賴于宿主機內核的運行環境。對于從物理服務器過渡到虛擬服務器是一個很自然的過程,從用戶使用上并沒有什么區別。
目前Redhat開源的kubevirt和Mirantis開源的virtlet都提供了以容器方式運行虛擬機的方案。
kubevirt 是 Redhat 開源的以容器方式運行虛擬機的項目,以 k8s add-on方式,利用 k8s CRD 為增加資源類型Virtual Machine Instance(VMI), 使用容器的image registry去創建虛擬機并提供VM生命周期管理。 用pod管理能力,要自主去實現,目前kubevirt實現了類似RS的功能。
那Virtlet是什么呢?
Virtlet 來自于 Mirantis,跟 kubevirt 的不同之處在于它使用 POD 來描述一個 VM(Virtual Machine,虛擬機)。Virtlet 是 Kubernetes 一個運行時服務,能夠根據 QCOW2 映像運行 VM 工作負載。Virtlet是是K8S的一個插件,CRI接口兼容的插件,能夠在 Kubernetes 集群上運行基于虛擬機的 Pods。
Virtlet的架構
CRIProxy作為代理,可以實現在一個節點上支持多種CRI。
kubelet會去調用CRIProxy,由CRIProxy根據pod image前綴(默認virtlet.cloud)決定將請求發給virtlet process 還是dockershim server,從而去創建虛擬機或者容器。
每個節點上會由daemonset負責啟動virtlet pod,該virtlet pod包括三個容器:
vm的確在vms container下,可以看到對應/proc/{id}/ns/下都是一致的,其實其他container ns只有mnt ns是不一樣的。
Virtlet如何管理虛擬機
虛擬機生命周期管理流程
virtlet使用原生的workload(deployment,statefulset)去管理vm pod,vm的生命周期與pod一致。vm隨著pod的創建而創建,隨著pod的銷毀而銷毀。
整體流程:
1. deploy、statefulset等workload創建出對應的pod;
2. kubelet list-watch發現了調度到該節點的pod,根據cri調用criproxy;
3. criproxy會根據pod image前綴判斷是將請求發給virtlet還是docker,比如pod image為virtlet.cloud/library/cirrors, 根據前綴匹配到virtlet.cloud,則將請求轉給virtlet;
4. virtlet process會根據請求去調用libvirt api通過qemu-kvm去創建/輸出虛擬機
虛擬機存儲
virtlet支持原生存儲范疇:
可以通過annotation字段去配置磁盤驅動以及系統磁盤大?。?/p>
metadata:
name: my-vm
annotations:
kubernetes.io/target-runtime: virtlet.cloud
VirtletRootVolumeSize: 4Gi
VirtletDiskDriver: virtio
....
VirtletRootVolumeSize定義了根卷的磁盤大小,VirtletDiskDriver定義了磁盤驅動,常規磁盤驅動默認為virtio-scsi。
其中virtlet也支持cloud-init進行初始化配置,定義ssh密碼以及相關用戶、網絡等初始化:
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-vm
annotations:
kubernetes.io/target-runtime: virtlet.cloud
# override some fields in cloud-init meta-data
VirtletCloudInitMetaData: |
instance-id: foobar
# override some fields in cloud-init user-data
VirtletCloudInitUserData: |
users:
- name: cloudy
gecos: Magic Cloud App Daemon User
inactive: true
system: true
virtlet管理的虛擬機與容器如何實現整體交互
virtlet與常規CRI一樣,也是使用CNI管理虛擬機的網絡。
virtlet去調用cni之前,會創建出新的network namespace,通過tap設備連接虛擬機,veth pair連接主機網絡與cni 網絡模型。
當前連通virtlet管理的虛擬機方式:
虛擬機鏡像
virtlet支持qcow格式的鏡像文件,但需要在pod image定義中指定virtlet.cloud前綴。virtlet會將對鏡像進行名稱轉換, 將名稱轉換成虛擬機鏡像下載地址。
當前virtlet支持兩種鏡像名稱轉換的方式:
translations:
- name: cirros
url: https://github.com/mirantis/virtlet/releases/download/v0.9.3/cirros.img
- name: fedora
url: https://dl.fedoraproject.org/pub/fedora/linux/releases/29/Cloud/x86_64/images/Fedora-Cloud-Base-29-1.2.x86_64.qcow2
舉個例子:
當你將image配置成virtlet.cloud/cirrors, virtlet會將該鏡像轉換成
https://github.com/mirantis/virtlet/releases/download/v0.9.3/cirros.img,virtlet根據該地址去下載,下載完畢后從而去創建虛擬機。
apiVersion: "virtlet.k8s/v1"
kind: VirtletImageMapping
metadata:
name: primary
namespace: kube-system
spec:
prefix: ""
translations:
- ...
- ...
默認的是,virtlet是基于文件系統進行存儲虛擬機鏡像,鏡像存儲地址如下:
/var/lib/virtlet/images
links/
example.com%whatever%etc -> ../data/2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881
example.com%same%image -> ../data/2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881
anotherimg -> ../data/a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa
data/
2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881
a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa
鏡像名稱中/字段轉換成%,并軟連接到匹配的數據文件。
Virtlet優缺點
優點
缺點
整體來說,virtlet是一種接入成本低,能夠快速融入已有云平臺的方式,但由于社區已不維護且本身CRI方式對接的局限性,對后續的可擴展性以及迭代開發來說,其可擴展方式不夠優雅且低,迭代開發難度相對來說大。