本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
了解 Kubevirt
一旦您习惯了在 Kubernetes 上运行 Linux 容器工作负载,您可能会发现自己希望能够在 Kubernetes 集群上运行其他类型的工作负载。也许您需要运行一个并非为容器设计的应用程序,或者需要与容器主机上可用的 Linux 内核版本不同(甚至完全不同的操作系统)的应用程序。
这些类型的工作负载通常非常适合在虚拟机 (VM) 中运行,而 KubeVirt 是 Kubernetes 的一个虚拟机管理插件,旨在允许用户在 Kubernetes 或 OpenShift 集群中将虚拟机与容器并行运行。
KubeVirt 通过 Kubernetes 的 自定义资源定义 API (CRD) 增加了虚拟机和虚拟机集资源类型,从而扩展了 Kubernetes。KubeVirt 虚拟机在常规的 Kubernetes Pod 中运行,它们可以访问标准的 Pod 网络和存储,并且可以使用 kubectl 等标准 Kubernetes 工具进行管理。
与使用 oVirt 或 OpenStack 等工具相比,在 Kubernetes 中运行虚拟机需要一些调整,了解 KubeVirt 的基本架构是一个很好的起点。
在这篇文章中,我们将简要介绍 KubeVirt 中涉及的一些高级组件。我们将要探讨的组件包括 CRD、KubeVirt 的 virt-controller、virt-handler 和 virt-launcher 组件、libvirt、存储和网络。
KubeVirt 组件

自定义资源定义(Custom Resource Definitions)
Kubernetes 资源是 Kubernetes API 中的端点,用于存储相关 API 对象的集合。例如,内置的 Pod 资源包含 Pod 对象的集合。Kubernetes 自定义资源定义 API 允许用户通过定义具有给定名称和 schema 的新对象来扩展 Kubernetes,添加额外的资源。一旦您将自定义资源应用到您的集群,Kubernetes API 服务器就会提供并处理您的自定义资源的存储。
KubeVirt 的主要 CRD 是 VirtualMachine (VM) 资源,它包含 Kubernetes API 服务器中的 VM 对象集合。VM 资源定义了虚拟机本身的所有属性,例如机器和 CPU 类型、RAM 和 vCPU 的数量,以及虚拟机中可用网卡的数量和类型。
virt-controller
virt-controller 是一个 Kubernetes Operator,负责集群范围的虚拟化功能。当新的 VM 对象发布到 Kubernetes API 服务器时,virt-controller 会注意到并创建虚拟机将运行的 Pod。当 Pod 被调度到特定节点时,virt-controller 会使用节点名称更新 VM 对象,并将进一步的职责交给节点特定的 KubeVirt 组件 virt-handler,该组件的实例在集群中的每个节点上运行。
virt-handler
与 virt-controller 一样,virt-handler 也是反应式的,它会监视 VM 对象的变化,并执行所有必要的操作来更改 VM 以满足所需状态。virt-handler 引用 VM 规范,并使用 VM Pod 中的 libvirtd 实例发出创建相应域的信号。当 VM 对象被删除时,virt-handler 会观察到删除并关闭该域。
virt-launcher
每个 VM 对象都会创建一个 Pod。这个 Pod 的主容器运行 virt-launcher KubeVirt 组件。virt-launcher Pod 的主要目的是提供用于托管 VM 进程的 cgroup 和命名空间。
virt-handler 通过将 VM 的 CRD 对象传递给 virt-launcher 来向 virt-launcher 发送启动 VM 的信号。然后 virt-launcher 使用其容器内的本地 libvirtd 实例来启动 VM。之后,virt-launcher 监控 VM 进程,并在 VM 退出后终止。
如果 Kubernetes 运行时尝试在虚拟机退出之前关闭 virt-launcher Pod,virt-launcher 会将来自 Kubernetes 的信号转发给虚拟机进程,并尝试推迟 Pod 的终止,直到虚拟机成功关闭。
# kubectl get pods
NAME READY STATUS RESTARTS AGE
virt-controller-7888c64d66-dzc9p 1/1 Running 0 2h
virt-controller-7888c64d66-wm66x 0/1 Running 0 2h
virt-handler-l2xkt 1/1 Running 0 2h
virt-handler-sztsw 1/1 Running 0 2h
virt-launcher-testvm-ephemeral-dph94 2/2 Running 0 2h
libvirtd
每个 VM Pod 中都存在一个 libvirtd 实例。virt-launcher 使用 libvirtd 来管理 VM 进程的生命周期。
存储和网络
KubeVirt 虚拟机可以配置为带卷的磁盘。
持久卷声明卷使 Kubernetes 持久卷作为直接连接到虚拟机的磁盘可用。这是为 KubeVirt 虚拟机提供持久存储的主要方式。目前,持久卷必须是 iscsi 块设备,尽管正在努力启用基于文件的 PV 磁盘。
临时卷是写时复制的本地映像,使用网络卷作为只读后端存储。KubeVirt 在虚拟机启动时动态生成与虚拟机关联的临时映像,并在虚拟机停止时丢弃临时映像。目前,临时卷必须由 PVC 卷支持。
Registry Disk 卷引用了嵌入 qcow 或 raw 磁盘的 Docker 镜像。顾名思义,这些卷是从容器注册表拉取的。与常规的临时容器镜像一样,这些卷中的数据仅在 Pod 存活时才保留。
CloudInit NoCloud 卷为虚拟机提供了一个 cloud-init NoCloud 用户数据源,该源作为磁盘添加到虚拟机中,可用于向安装了 cloud-init 的访客提供配置详细信息。Cloud-init 详细信息可以以明文形式提供,也可以作为 base64 编码的 UserData 文件提供,或者通过 Kubernetes secrets 提供。
在下面的示例中,配置了一个注册表磁盘以提供用于启动虚拟机的镜像。提供了一个 cloudInit NoCloud 卷,与存储在 userData 字段中的明文 ssh 密钥配对,用于与虚拟机进行身份验证
apiVersion: kubevirt.io/v1alpha1
kind: VirtualMachine
metadata:
name: myvm
spec:
terminationGracePeriodSeconds: 5
domain:
resources:
requests:
memory: 64M
devices:
disks:
- name: registrydisk
volumeName: registryvolume
disk:
bus: virtio
- name: cloudinitdisk
volumeName: cloudinitvolume
disk:
bus: virtio
volumes:
- name: registryvolume
registryDisk:
image: kubevirt/cirros-registry-disk-demo:devel
- name: cloudinitvolume
cloudInitNoCloud:
userData: |
ssh-authorized-keys:
- ssh-rsa AAAAB3NzaK8L93bWxnyp test@test.com
与常规 Kubernetes Pod 一样,每个 KubeVirt VM 都会自动提供基本的网络功能,并且可以使用常规的 Kubernetes 服务将特定的 TCP 或 UDP 端口暴露给外部世界。无需特殊的网络配置。
参与其中
KubeVirt 的开发正在加速,项目渴望新的贡献者。如果您有兴趣参与,请查看项目的开放问题并查看项目日历。
如果您需要帮助或想聊天,可以通过 freenode IRC 的 #kubevirt 或 KubeVirt 邮件列表联系团队。用户文档可在 https://kubevirt.gitbooks.io/user-guide/ 获取。