随着Docker和Kubernetes生态圈的倒退,云计算畛域对容器的趣味达到了狂热的水平。容器技术为应用程序提供了隔离的运行空间,每个容器内都蕴含一个独享的残缺用户环境空间,容器内的变动不会影响其余容器的运行环境。因为容器之间共享同一个零碎内核,当同一个库被多个容器应用时,内存的应用效率会失去晋升。基于物理主机操作系统内核的,那就意味着对于不同内核或者操作系统需要的利用是不可能部署在一起的。
虚拟化技术则是提供了一个残缺的虚拟机,为用户提供了不依赖于宿主机内核的运行环境。对于从物理服务器过渡到虚构服务器是一个很天然的过程,从用户应用上并没有什么区别。
目前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包含三个容器:
virtlet:接管 CRI 调用,治理VM
libvirt:接管 virtlet 的申请创立、进行或销毁VM
VMs:所有 virtlet 治理的VM 都会在这个容器的命名空间里
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反对原生存储领域:
emptydir
hostpath
pvc, 须要mode类型是block
flexvolumes
secret,configmap
能够通过annotation字段去配置磁盘驱动以及零碎磁盘大小:
metadata:
name: my-vm
annotations:
kubernetes.io/target-runtime: virtlet.cloudVirtletRootVolumeSize: 4GiVirtletDiskDriver: 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-dataVirtletCloudInitMetaData: | instance-id: foobar# override some fields in cloud-init user-dataVirtletCloudInitUserData: | 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 pod IP地址,间接ssh模式
kubectl attach命令, virtlet提供attach接口,可能以相似console模式拜访
virtletctl 命令,提供ssh,vps模式
虚拟机镜像
virtlet反对qcow格局的镜像文件,但须要在pod image定义中指定virtlet.cloud前缀。virtlet会将对镜像进行名称转换, 将名称转换成虚拟机镜像下载地址。
以后virtlet反对两种镜像名称转换的形式:
动态配置:默认kube-system会创立名为virtlet-image-translations的configmap
translations:
- name: cirros
url: https://github.com/mirantis/v... name: fedora
url: https://dl.fedoraproject.org/...
举个例子:
当你将image配置成virtlet.cloud/cirrors, virtlet会将该镜像转换成
https://github.com/mirantis/v...,virtlet依据该地址去下载,下载结束后从而去创立虚拟机。
自定义对象配置:virtlet提供VirtletImageMapping资源对象,相对来说,优先级会高于动态配置
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优缺点
长处
沿用原生workload,virtlet可无缝接入已有平台
复用CRI能力,侵入性小
毛病
引入CRIPROXY链路危险
限于CRI的整体框架内,无奈灵便扩大
不反对CSI,仅反对flexvolume存储驱动
不反对备份与迁徙等能力
社区活跃度低,已不再持续保护
整体来说,virtlet是一种接入成本低,可能疾速融入已有云平台的形式,但因为社区已不保护且自身CRI形式对接的局限性,对后续的可扩展性以及迭代开发来说,其可扩大形式不够优雅且低,迭代开发难度相对来说大。