本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。

了解 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 组件

Kubevirt Components

自定义资源定义(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/ 获取。