2020年CNCF中国云原生考察邀你一起来参加!
问卷链接(https://www.wjx.cn/jq/9714648...)
廖旋威:目前就任于新华三云计算,次要从事云原生行业,对k8s和拟化相干有深入研究,善于Go/Java语言。
曾小波:一个十年一线架构研发工作的技术人员,目前在新华云计算从事云原生产品及社区相干工作。
kubevirt 简介
kubevirt 是一个围绕kubernetes构建的虚拟机治理架构,次要用于技术起因无奈将虚拟机利用迁徙到容器平台的场景,它提供了欠缺的虚拟机生命周期治理、在kubernetes上虚拟机调度等能力。
。新华三云原生团队在kubevirt我的项目成立初期就进行了钻研,并对kubevirt进行了革新实际,同时鉴于目前kubevirt深度剖析材料较为不足,因而咱们决定对kubevirt源码进行分析,以飨读者。本文是系列的第一篇:virt-controller源码剖析。
kubevirt 部署架构介绍
由virt-controller,virt-api,virt-handler,virt-launcher四大组件组成,其核心思想是在通过kubernetes原生来治理虚拟机,为开发团队解决只能应用虚拟机的应用程序提供了可能。为了让读者可能更好了解virt-controller,咱们首先介绍一下kubevirt的部署架构,如图:
从架构图中能够看出:
- virt-controller,virt-api:集群层面上全局惟一,次要作用是通过与k8s api server 通信实现vmi资源创立、virt-lanucher pod 的创立及状态更新等。
- virt-handler:节点层面上惟一,负责与k8s api server、virt-lanucher通信来实现虚拟机的生命周期治理。
- virt-launcher:依据vmi 定义生成虚拟机模板,通过与libvirt api 通信提供虚拟机生命周期治理。
上面咱们对virt-controller的源码进行剖析,加深大家对实现细节的了解。
kubevirt 资源类型
VirtualMachineInstance
- 简称VMI,能够简略与理论虚拟机一一对应。
- 会创立一个蕴含virt-launcher的Pod,该Pod外面通过libvirt创立实在虚拟机。
- VMI的Spec字段指定虚拟机运行参数,Status字段记录虚拟机运行状况。
VirtualMachine
- 简称VM,能够治理和操作VMI对象。
- 一个VM对象只能治理一个VMI对象
VirtualMachineInstanceReplicaSet
简称replicaset或rs,一个replicaset能够治理多个VMI对象,即一个ReplicaSet能够创立、批改、删除多个虚拟机。
VirtualMachineInstanceMigration
简称Migration,在Migration对象的Spec字段外面指定要迁徙的VMI,而后kubevirt主动对该VMI实现迁徙。
virt-controller 源码剖析
启动流程
入口在kubevirt/cmd/virt-controller/virt-controller.go
func main() { watch.Execute()}
间接调用kubevirt/pkg/virt-controller/watch/application.go中的Execute函数启动virt-controller。上面次要剖析Execute函数中的内容。
- 获取leaderElectionConfiguration
- 获取KubevirtClient
- 获取informerFactory,并实例化一系列具体资源类型的Informer,例如crdInformer、kubeVirtInformer、vmiInformer、kvPodInformer、nodeInformer、vmInformer、migrationInformer等
- 初始化一系列controller,包含vmiController、nodeController、migrationController、vmController、evacuationController、snapshotController、restoreController、replicaSetController、disruptionBudgetController
- 通过leaderElector来启动virt-controller,并在leaderElector中启动各个controller的Run函数。
VMController剖析
代码位于kubevirt/pkg/virt-controller/watch/vm.go文件中。
- 监听VM对象、VMI对象、DataVolume对象并增加对应的EventHandler。
收到Event事件之后退出到workQueue。
- VM对象的Event事件间接退出workQueue。
- VMI对象的Event事件先判断是否由VM对象所管制,如果是则将该VM对象退出workQueue,否则找到匹配的VM,将匹配的VM退出到workQueue,尝试收养孤儿的VMI对象。
- DataVolume对象的Event事件先判断是否由VM对象所管制,如果是则将该VM对象退出workQueue,否则不解决。
- 通过Run()->runWorker()->Execute()->execute(),从workQueue中取出对象的key,而后在execute中解决。
execute()函数的解决逻辑
- 依据key,从Informer的本地缓存中获取VM对象。
- 创立VirtualMachineControllerRefManager。
- 依据key,从Informer的本地缓存中获取VMI对象
- 如果获取VMI对象胜利,则VirtualMachineControllerRefManager尝试收养或遗弃VMI。
- 依据Spec.DataVolumeTemplates,从Informer的本地缓存中获取dataVolumes。
查看dataVolumes是否曾经ready,若曾经ready则调用startStop()
- RunStrategy==Always:虚拟机实例VMI应该总是存在,如果虚拟机实例VMI crash,会创立一个新的虚拟机。等同于spec.running:true。
- RunStrategy==RerunOnFailure:如果虚拟机实例VMI运行失败,会创立一个新的虚拟机。如果是由客户端被动胜利敞开,则不会再从新创立。
- RunStrategy==Manual:虚拟机实例VMI运行状况通过start/stop/restart手工来管制。
- RunStrategy==Halted:虚拟机实例VMI应该总是挂起。等同于spec.running:false。
更新VMStatus
- 批改vm.Status.Created,vm.Status.Ready
- 批改vm.Status.StateChangeRequests
- 批改vm.Status.Conditions
- 更新VMStatus
VMIController剖析
代码位于kubevirt/pkg/virt-controller/watch/vmi.go文件中。
- 监听VMI对象、Pod对象、DataVolume对象并增加对应的EventHandler。
收到Event事件之后退出到workQueue。
- VMI对象的Event事件间接退出workQueue。
- Pod对象的Event事件先判断是否由VM对象所管制,如果是则将该VM对象退出workQueue,否则不解决。
- DataVolume对象的Event事件,依据DataVolume的Namespace和Name获取匹配的vmis,而后将vmis对象顺次退出到workQueue。
- 通过Run()->runWorker()->Execute()->execute(),从workQueue中取出对象的key,而后在execute中解决。
execute()函数的解决逻辑
- 依据key,从Informer的本地缓存中获取VM对象。
- 获取和以后vmi对象匹配的Pod。
- 依据vmi.Spec.Volumes,获取匹配的DataVolumes对象。
- 同步sync,若Pod不存在,则创立lanucher所在的Pod。
- 更新vmi对象的status。
MigrationController剖析
代码位于kubevirt/pkg/virt-controller/watch/migration.go文件中。
- 监听Migration对象、VMI对象、Pod对象并增加对应的EventHandler。
收到Event事件之后退出到workQueue。
- VMI对象的Event事件间接退出workQueue。
- Pod对象的Event事件,依据Pod的Annotation中的migrationJonName来找到对应的migration对象,而后退出workQueue。
- VMI对象的Event事件,依据vmi的Namespace和Name获取匹配的Migration对象,而后退出到workQueue。
- 通过Run()->runWorker()->Execute()->execute(),从workQueue中取出对象的key,而后在execute中解决。
execute()函数的解决逻辑
- 依据key,从Informer的本地缓存中获取Migration对象。
- 依据Migration.namespace和Migration对象.Spec.VMIName来获取VMI对象。
- 获取迁徙指标Pod。
- 同步sync。
- 更新Migration对象的status,Migration.Status.Phase状态转换为:

ReplicaSetController剖析
代码位于kubevirt/pkg/virt-controller/watch/replicaset.go文件中。
- 监听replicaSet对象、VMI对象并增加对应的EventHandler。
收到Event事件之后退出到workQueue。
- VMI对象的Event事件间接退出workQueue。。
- VMI对象的Event事件,先判断是否由replicaSet对象管制,如果是则将该replicaSet退出到workQueue,否则找到与该VMI对象匹配的replicaSets,而后将replicaSets顺次退出workQueue,尝试将该VMI对象收养。
- 通过Run()->runWorker()->Execute()->execute(),从workQueue中取出对象的key,而后在execute中解决。
execute()函数的解决逻辑
- 依据key,从Informer的本地缓存中获取Migration对象。
- 依据namespaces获取vmis。
- 依据获取replicaSet对象,创立VMControllerRefManager,而后尝试收养或遗弃vmis。
- 将vmis分成两组finishedVmis和activeVmis。
- 依据Spec.Replicas以及以后replicaset治理的activeVmis,对vmis进行扩容或者缩容。
- 更新replicaSet的Status。
总结
本文章基于kubevirt 0.35版本,重点解说了kubevirt架构及对virt-controller源码设计进行剖析。因为篇幅无限,本文次要帮忙读者理清virt-controller的次要设计思路,起到穿针引线成果,下一篇咱们将对handler组件进行剖析。
点击达到KubeVirt网站。
CNCF (Cloud Native Computing Foundation)成立于2015年12月,隶属于Linux Foundation,是非营利性组织。
CNCF(云原生计算基金会)致力于培养和保护一个厂商中立的开源生态系统,来推广云原生技术。咱们通过将最前沿的模式民主化,让这些翻新为公众所用。扫描二维码关注CNCF微信公众号。