随着 Kubernetes 的遍及,越来越多的业务开始运行在容器上,然而仍有局部业务状态更适宜运行在虚拟机,如何同时管控虚拟机和容器逐步成为了云原生时代的支流需要,Kubevirt 给出了完满的解决方案。
- Kubevirt 介绍
- 虚拟机治理
- 总结
在云原生时代,越来越多的业务开始逐渐迁徙到容器上来,容器也成为了一种不可或缺的资源公布和治理模式,容器的轻量性劣势在边缘计算的场景下更加显著,因而,在边缘构建云平台必须思考兼容容器的运行状态。
Kubernetes 目前是容器编排和调度最通用风行的平台,同时越来越多的云厂商抉择应用 Kubernetes 来同时治理容器和虚拟机。在 Kubernetes 之上构建治理虚拟机的平台,业界也呈现了不少优良的我的项目,例如 Kubevirt、Virtlet 等,其中 Kubevirt 以其架构设计和性能劣势成为解决虚机与容器兼容问题的最佳计划之一。本文将以 Kubevirt 为根底,具体分享如何基于 Kubevirt 构建边缘计算实例。
01 Kubevirt 介绍
Kubevirt 是什么
Kubevirt 是 Red Hat 开源的以容器形式运行虚拟机的我的项目,基于 Kubernetes 运行,通过应用自定义资源(CRD)和其它 Kubernetes 性能来无缝扩大现有的集群,以提供一组可用于治理虚拟机的虚拟化的 API。
整体架构
上图形容了 Kubevirt 的整体架构,其中蕴含了次要的四个要害组件:
-
virt-api:
- 为 Kubevirt 提供 API 服务能力,比方许多自定义的 API 申请,如开机、关机、重启等操作,通过 APIService 作为 Kubernetes Apiserver 的插件,业务能够通过 Kubernetes Apiserver 间接申请到 virt-api;
-
virt-controller:
- Kubevirt 的控制器,性能相似于 Kubernetes 的 controller-manager,治理和监控 VMI 对象及其关联的 Pod,对其状态进行更新;
-
virt-handler:
- 以 Daemonset 模式部署,性能相似于 Kubelet,通过 Watch 本机 VMI 和实例资源,治理本宿主机上所有虚机实例;
-
次要执行动作如下:
- 使 VMI 中定义的 Spec 与相应的 libvirt(本地 socket 通信)放弃同步;
- 汇报及管制更新虚拟机状态;
- 调用相干插件初始化节点上网络和存储资源;
- 热迁徙相干操作;
-
virt-launcher:
- Kubevirt 会为每一个 VMI 对象创立一个 Pod,该 Pod 的主过程为 virt-launcher,virt-launcher 的 Pod 提供了 cgroups 和 namespaces 的隔离,virt-launcher 为虚拟机实例的主过程。
- virt-handler 通过将 VMI 的 CRD 对象传递给 virt-launcher 来告诉 virt-launcher 启动 VMI。而后,virt-launcher 在其容器中应用本地 libvirtd 实例来启动 VMI。virt-launcher 托管 VMI 过程,并在 VMI 退出后终止。
- 如果 Kubernetes 运行时在 VMI 退出之前尝试敞开 virt-launcher 容器,virt-launcher 会将信号从 Kubernetes 转发到 VMI 过程,并尝试推延容器的终止,直到 VMI 胜利敞开。
下图为 virt-launcher 与 libvirt 通信概况图:
资源对象
Kubevirt 是 Kubernetes 的虚拟机治理插件,通过自定义控制器和资源实现对虚拟机的治理性能,通过自定义资源 (CRD) 机制,同时 Kubevirt 能够自定义额定的操作,来调整惯例容器中不可用的行为。这里介绍几个要害资源:
- VirtualMachineInstance(VMI):是治理虚拟机的最小资源,一个 VirtualMachineInstance 对象示意一台正在运行的虚拟机实例,蕴含一个虚拟机所须要的各种配置。
- VirtualMachine( VM ):为集群内的 VirtualMachineInstance 提供治理性能,例如开机 / 关机 / 重启虚拟机,确保虚拟机实例的启动状态,与虚拟机实例是 1:1 的关系。
- VirtualMachineInstanceMigrations:虚拟机迁徙须要的资源,一个资源对象示意为一次迁徙工作,并反映出虚拟机迁徙的状态。
- VirtualMachineInstanceReplicaSet:相似 ReplicaSet,能够指定数量,批量创立虚拟机。
- DataVolume: 是对 PVC 之上的形象,通过自定义数据源,由 CDI 控制器主动创立 PVC 并导入数据到 PVC 中供虚拟机应用。
以下为 VM 资源示例:
kind: VirtualMachine
metadata:
labels:
kubevirt.io/vm: vm-cirros
name: vm-cirros
spec:
running: false
template:
metadata:
labels:
kubevirt.io/vm: vm-cirros
spec:
domain:
devices:
disks:
- disk:
bus: virtio
name: containerdisk
- disk:
bus: virtio
name: cloudinitdisk
machine:
type: ""
resources:
requests:
memory: 64M
terminationGracePeriodSeconds: 0
volumes:
- name: containerdisk
containerDisk:
image: kubevirt/cirros-container-disk-demo:latest
- cloudInitNoCloud:
userDataBase64: IyEvYmluL3NoCgplY2hvICdwcmludGVkIGZyb20gY2xvdWQtaW5pdCB1c2VyZGF0YScK
name: cloudinitdisk
02
虚拟机治理
\
在理解了 Kubevirt 是什么,它的次要架构以及比拟要害的资源对象后,咱们来看看如何应用 Kubevirt 进行虚拟机治理。这里次要分为虚拟机创立、存储和网络三个局部。\
虚拟机创立
**\
**
虚拟机创立分为创立 DataVolume(为虚拟机筹备存储)和 VMI 两个局部。简要流程如下:\
- 用户通过 kubectl/api 创立 VM 对象;
- virt-api 通过 webhook 校验 VM 对象;
- virt-controller 监听到 VM 的创立,生成 VMI 对象;
- virt-controller 监听到 VMI 的创立,判断虚拟机 DataVolume 是否被初始化,如果没有被初始化,则创立 DateVolume 初始化筹备虚拟机须要的数据;
- 虚拟机 DataVolume 初始化实现后,virt-controller 创立 virt-launcher Pod 来启动虚机;
- kubernetes 调度虚拟机 Pod 到集群中的一台主机上;
- virt-controller Watch 到 VMI 的容器已启动,更新 VMI 对象中的 nodeName 字段。后续工作由 virt-handler 接管以进行进一步的操作;
- virt-handler(DaemonSet)Watch 到 VMI 已调配给运行它的主机上,通过获取 Domain 与 vmi 状态来决定发送命令启动虚拟机;
- virt-launcher 获取到 virt-handler 命令,与 libvirtd 实例通信来操作虚拟机。
以上,咱们便实现了虚拟机的初步创立。不过在虚拟机创立过程,可能呈现不同的状态提醒,本文列举了常见的几种状态及其示意:
- Pending: 虚拟机实例曾经创立,期待后续管制流程;
- Scheduling: 虚拟机 Pod 曾经创立,正在调度中;
- Scheduled: 虚拟机 Pod 调度实现,并处于 running 状态,此状态后 virt-controller 管制完结,由 virt-handler 接管后续工作;
- Running: 虚拟机失常运行;
- Succeeded: 虚拟机因为收到 sigterm 信号或者外部关机操纵而退出;
- Failed: 因为异常情况导致虚拟机 crash;
虚拟机存储
存储局部 Kubevirt 能够基于 Kubetnetes 运行,因而能够复用 Kubernetes 中的存储设计,如 PVC、PV 等。同时,Kubevirt 在 PVC 之上自定义了 DataVolume 资源。
DataVolume 是由 Kubevirt 团队开发并开源的容器数据导入插件 CDI(containerized-data-importer)所定义的 CRD。
虚机启动之前会创立 DataVolume 对象,由 CDI 控制器主动创立 PVC,并依据反对的数据源下载数据。虚机的 Pod 启动之前 Kubernetes 会调用 CSI 将云盘挂载到宿主机上,表现形式为块设施并挂在设施到 launcher Pod 中,最终虚拟机通过 virtio 驱动拜访磁盘设施。
虚拟机网络
在网络方面,Kubevirt 复用了 Kubernetes 的容器网络,并在此之上提供 4 种虚拟机网络模型。以后 Kubevirt 次要反对四种网络模式:
// +k8s:openapi-gen=true
type InterfaceBindingMethod struct {
Bridge *InterfaceBridge `json:"bridge,omitempty"`
Slirp *InterfaceSlirp `json:"slirp,omitempty"`
Masquerade *InterfaceMasquerade `json:"masquerade,omitempty"`
SRIOV *InterfaceSRIOV `json:"sriov,omitempty"`
}
虚拟机和容器网络是互通的,能够实现虚拟机和容器不同状态的业务之间互联互通。这里介绍下 Bridge 模式,这种形式实现较简略,然而网络损耗也较大:
- Bridge 模式下 pod 的 veth pair 依然由 cni 治理创立,而 virt-launcher 会将 Pod IP 摘掉,pod veth 设施 eth0 仅作为虚拟机的虚构网卡与内部网络通信的桥梁。
- virt-launcher 在 pod 中创立 tap 设施 vnet0 和 bridge 桥设施 br1,同时实现了简略的单 ip dhcp server,虚拟机中启动 dhclient,Virt-launcher 将 IP 调配给虚拟机。
03 总结
以上是基于 Kubevirt 构建边缘计算实例的技术计划,也对 Kubevirt 的架构及次要模块进行了具体阐明。Kubevirt 作为 Kubernetes 的 CRD 插件,不仅为 Kubernetes 补全了调度虚拟机的能力,也为解决容器和虚拟机的交融调度提供了一个较为成熟、可行的解决方案。
参考资料:
[1] https://github.com/kubevirt/k…
[2] https://kubevirt.io/