《kubevirt(一)虚拟化技术》一文中,我们对libevirt+qemu+kvm虚拟化做了一些简单的说明,本文基于这些内容,来看看kubevirt是怎么结合kubernetes平台实现虚拟化的。

kubevirt项目地址:https://github.com/kubevirt/kubevirt,在介绍kubevirt之前,我们先对kubernetes的informerCRD两个概念再做一个简单的说明。

  • informer

informer简单来说是客户端通过list+watch机制,当关注的资源对象有变化时能得到ADD、UPDATE、DELETE三种事件,并且可以注册这三种事件的处理函数。这里说的资源对象可以是kubernetes原生支持的,例如namespace、deployment、node、pod等资源,也可以是用户自定义资源(CRD)。informer完整原理与实现可参考下图:

在这里插入图片描述

  • CRD

CRD的全称是Custom Resource Definition,即用户自定义资源,它是kubernetes可扩展的重要基础,CRD通常和webhook、informer(controller)一起使用来实现用户自定义逻辑。CRD可以理解为一种抽象,例如kubevirt把虚拟机抽象成一个vmi对象,创建一个vmi对象,就会触发informer中的ADD事件处理函数去创建一台真正的虚拟机。

kubevirt

以下内容基于kubevirt@0.49.0

kubevirt是基于CRD、controller等kubernetes特性,与容器并行地表示和管理传统虚拟机,kubevirt核心CRD VMI(Virtual Machine Instance)对应的就是虚拟机实例。

架构

在kubevirt代码仓库的文档中,我们能看到如下信息,从该图示可以看出,kubevirt运行在kubernetes之上,且调度(scheduling)也是由kubernetes负责,底层则是在物理资源的基础上,利用虚拟化技术运行不同的操作系统(operating System)。

  +---------------------+
  | KubeVirt            |
~~+---------------------+~~
  | Orchestration (K8s) |
  +---------------------+
  | Scheduling (K8s)    |
  +---------------------+
  | Container Runtime   |
~~+---------------------+~~
  | Operating System    |
  +---------------------+
  | (Virtual)           |
~~+---------------------+~~
  | Physical            |
  +---------------------+
虚拟机与普通pod container

同一个kubernetes平台可以同时运行kubevirt虚拟机和普通pod container,它们有如下关系:

在这里插入图片描述

VMI

一个VMI对象对应一台虚拟机,实际上这台虚拟机是在一个特殊的kubernetes pod中,该pod里有virt-launcher、libvirtd和qemu进程,其中libvirtd和qemu是上篇文章提到的用于虚拟化的组件,因此也就是可以看作kubevirt把虚拟机运行在了pod中

在这里插入图片描述

kubevirt组件

kubevirt组件包括virt-controllervirt-apivirt-handlervirt-launcher等,整体关系如下:

在这里插入图片描述

其中各个组件大致功能如下:

  • virt-controller

基于informer的list-watch机制,监听VM、VMI等资源的事件,转换成VMI对应的pod,从而达到管理虚拟机的生命周期的功能。

  • virt-api

virt-api以deployment的形式运行,逻辑上主要包含以下功能:

1、提供VM、VMI等CRD资源mutating+validating webhook接口;

2、通过kubernetes的aggregator特性,对外暴露虚拟机操作的相关接口,包括restart、migrate、start、stop、freeze/unfreeze、softReboot、pause/unpause、console、vnc等操作。

  • virt-handler:

virt-handler以deamonSet的形式运行在每个节点上(配置hostNetwork+hostPID),逻辑上包含以下功能:

1、提供rest接口供virt-api调用,接口功能包括console、vnc、pause/unpause、freeze/unfreeze等功能,这些接口最终操作本节点上对应的VMI对应的虚拟机。virt-api通过VMI的status.nodeName+约定好的端口找到VMI对应节点上的virt-handler https服务,这也是为什么virt-handler要配置hostNetwork网络

2、通过list-watch机制确保相应的libvirt domain的启动或停止,但是这个过程并不是virt-handler与对应的libvirtd直接交互,而是virt-handler通过unix sock文件访问virt-launcher,virt-launcher再与libvirtd交互。virt-handler与virt-launcher交互的sock文件为/var/run/kubevirt/sockets/{vmi_uid}_sock。

  • virt-launcher:

每一个VMI对应的pod中都运行着一个virt-launcher进程,该进程逻辑上提供如下功能:

1、以unix sock形式启动一个grpc server,该server负责提供接口供virt-hanlder调用;

2、管理VMI对应的pod内的libvirtd、qemu进程的生命周期,例如qemu进程异常后会自动重启。

流程分析

我们选取两个场景,加深对kubevirt各个组件的理解。

场景一、创建VMI

在这里插入图片描述

  1. 用户执行kubectl apply一个vmi对象的yaml;
  2. apiServer把vmi对象保存到etcd;
  3. virt-controller通过list-watch机制监听到vmi对象的创建事件;
  4. virt-controller根据vmi信息构造一个pod对象,并调apiServer接口进行创建;
  5. apiServer把该pod对象存入etcd;
  6. k8s scheduler通过list-watch机制监听到有pod创建;
  7. k8s scheduler发现pod.spec.nodeName为空,根据调度算法选择一个合适的节点给该pod,把节点名称写到pod.spec.nodeName字段,并调apiServer接口更新pod信息;
  8. apiServer更新etcd中pod对象信息;
  9. 上述节点上的kubelet通过list-watch机制发现有新的pod调度到本节点上;
  10. kubelet在本节点上创建一个pod,该pod中启动virt-launcher、libvirtd、qemu三个进程,此时一个kubevirt虚拟机就创建出来了。
场景二、vnc连接虚拟机

在这里插入图片描述

  1. 用户执行virtctl vnc命令;
  2. 请求到达apiServer后通过aggregator机制转发到virt-api;
  3. virt-api根据vmi中的节点信息找到该节点的ip,并通过约定好的端口请求对应节点上的virt-handler;
  4. virt-handler通过unix sock文件找到虚拟机对应的virt-launcher,发起vnc请求;
  5. virt-launcher调libvirtd的vnc接口。

总结

通过本文的介绍,我们简单地了解了kubevirt原理以及核心CRD vmi,其实kubevirt还有很多CRD来处理多副本、快照、迁移等场景,这些内容有待读者自行探索。

如果用一句话来概述kubevirt,那就是在pod中跑虚拟机,github上还有一个开源的容器项目:kata container,与kubevirt相似的是,底层也用到了qemu虚拟化技术,但是kata container是在虚拟机中跑pod,正如kubevirt FAQ中对两者区别的描述:

Kata containers allow you to run containers inside virtual machines.
KubeVirt allows you to run full virtual machines on Kubernetes alongside regular containers.
One could say they are opposites:
Kata containers are containers inside virtual machines.
KubeVirt is a virtual machine inside a container.

后续会有文章分析docker container、kubevirt和kata container的差异,敬请期待。

微信公众号卡巴斯同步发布,欢迎大家关注。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐