KubeVirt 探秘:一些核心问题解答

大家好,我是张晋涛。

上一篇文章 KubeVirt: 耗时 7 年终将虚拟机带入 Kubernetes 世界 | MoeLove 发布后,我收到了很多留言和讨论。 限于篇幅,很多回答都比较简短,我想着还是写篇文章来详细聊聊关于 KubeVirt 的一些问题好了。

为什么要用 KubeVirt

有小伙伴问到 KubeVirt 的使用场景是什么?

按照官方文档的描述是:Building a virtualization API for Kubernetes,为 Kubernetes 构建一个虚拟化 API 扩展。 这隐含的其实就是 KubeVirt 带来了一层抽象,一层基于 API 的抽象。

我们知道 Kubernetes 中提供了 CRD 的模式允许对 Kubernetes 进行扩展,也有很多的项目通过这种模式进行扩展,开发了对应的 Operator 之类的。 为的就是能利用更多 Kubernetes 提供的能力。对于 KubeVirt 而言,它也是利用了 CRD 的这种模式,所以这方面它也一样。这些好处具体而言就是:

  • 声明式配置:通过使用声明式配置的方式创建 VirtualMachine 类型的自定义资源来创建 VM,创建 VirtualMachineInstance 类型的资源来描述虚拟机实例。这与我们在使用 Deployment 和 Pod 描述工作负载时的逻辑和体验基本类似,而且基本的一些操作经验等都是可以复用的;
  • 调度能力:Kubernetes 默认提供了对于工作负载的调度能力,并且还可以通过其他的方式对其进行扩展。利用 KubeVirt 部署时,同样的就获得了这些能力,由 Kubernetes 辅助我们进行虚拟机的调度,而不需要用户自行去进行管理和干预(除非有特殊的情况,可以进行声明);
  • 资源请求和限制:Kubernetes 为我们提供了资源请求和限制的能力,通过 requests 和 limits 进行控制,对于通过 KubeVirt 部署的虚拟机也同样,可以通过这种方式来控制虚拟机可用的资源;
  • 网络:在很多公司,有一些通过虚拟机运行的一些相对较旧的服务,在企业的云源生改造过程中,有时候可能发现这些服务很难和 Kubernetes 集群中的网络打通,或者是不易打通。这时候,通过 KubeVirt 部署在 Kubernetes 后,就直接拥有了与 Kubernetes 集群相同的网络,也就没有之前的烦恼了;
  • 存储:可以通过 PVC 来声明虚拟机可以使用的磁盘;
  • 可观测性:可以使用和容器工作负载相同的可观测性堆栈来对虚拟机进行处理;

此外,它还有一些其他的优势:

  • 统一基础设施:使用 KubeVirt 后,可以将虚拟机使用 Kubernetes 进行管理,这样也就不需要单独维护管理虚拟机的技术设施了;
  • 统一的 pipeline:由于可以使用 Kubernetes 的强大能力,可以在 pipeline 中,处理对应的逻辑;
  • 更快的完成企业云原生化的迁移 :多数公司或多或少存在一些想停又不敢停,只能一直保持运行的服务。这种服务其实就可以直接以虚拟机的方式运行,并且纳入 Kubernetes 的管理中。这样在企业进行云原生化改造的过程中,也可以更多的进行推进,然后再逐步的进行分解。

直接用 KVM 不好吗?

还有小伙伴问到,直接用 KVM 不就可以了?

按照前面的介绍,KubeVirt 的核心优势其实在于它的抽象和封装,它提供了类似 VirtualMachineVirtualMachineInstance 等自定义资源, 用户可以直接通过这些声明式配置就完成对应环境的准备。

但如果是直接使用 KVM 的话,则还需要使用 virsh 之类的命令进行操作,会比较麻烦。

而且最为重要的一点,KubeVirt 底层实际上也使用了 QEMU/KVM 等技术,只是它将这些技术带入了 Kubernetes 世界,以一种更加 Kubernetes 原生的方式提供给用户使用。

KubeVirt 有什么劣势?

KubeVirt 作为一项并没有那么广泛使用的技术,引入它除去有上文中提到的优势外,它自然也有一些劣势,或者说不适用的场景。

  • 由于 KubeVirt 实际是使用虚拟化技术,所以相比于直接用容器化技术,它带来的开销自然也更多,启动时间变长等。这也是为什么会有一些轻量级虚拟化技术 MicroVM 存在的原因;
  • 同样的,由于是用了虚拟化技术,它通常适用于物理机节点,或者支持嵌套虚拟化的节点。可以看看这个配置 /etc/modprobe.d/kvm.conf
➜  ~ cat /etc/modprobe.d/kvm.conf 
# Setting modprobe kvm_intel/kvm_amd nested = 1
# only enables Nested Virtualization until the next reboot or
# module reload. Uncomment the option applicable
# to your system below to enable the feature permanently.
#
# User changes in this file are preserved across upgrades.
#
# For Intel
#options kvm_intel nested=1
#
# For AMD
#options kvm_amd nested=1
  • 引入 KubeVirt 自然也会带来一定的学习成本和复杂度,并非所有的 Kubernetes 生态的组件都支持 KubeVirt;
  • 并且由于 KubeVirt 并不像容器化技术那么“原生”,所以难免存在一些兼容问题,这个就需要 case by case 的解决了;

KubeVirt 有哪些用例?

有小伙伴问到真的有人在用 KubeVirt 吗?在 KubeVirt 仓库中有一个文件,是对应厂商自己登记的,当然,这应该也不是全部的用例,可能还有一些未进行登记。 https://github.com/kubevirt/kubevirt/blob/main/ADOPTERS.md

2023-09-03 08-51-07屏幕截图.png

2023-09-03 08-50-54屏幕截图.png

2023-09-03 08-50-35屏幕截图.png

KubeVirt 的网络是如何管理的?

KubeVirt 的网络管理主要依赖于 Kubernetes 的网络模型和扩展。KubeVirt 使用多种网络插件和技术来支持虚拟机(VM)之间以及 VM 与容器之间的网络通信。

在虚拟机的 spec.networks 中可以配置虚拟机可以使用的网络后端(backend),目前有两个选项:

  • pod :KubeVirt 使用 Kubernetes 的 Pod 网络来实现虚拟机与容器之间的通信。虚拟机作为一个 Pod 被部署在集群中,它们共享相同的网络命名空间。这意味着虚拟机可以像容器一样访问集群中的其他资源,反之亦然。
kind: VM
spec:
  domain:
    devices:
      interfaces:
        - name: default
          masquerade: {}
  networks:
  - name: default
    pod: {} # Stock pod network
  • multus:使用 Multus 提供的辅助网络,KubeVirt 支持将多个网络接口附加到虚拟机上,这使得虚拟机可以连接到多个网络。为了实现这一点,KubeVirt 使用了 Multus,这是一个 Kubernetes 的 CNI(容器网络接口)插件,它允许将多个网络接口附加到 Pod 上。

先创建一个 NetworkAttachmentDefinition 的资源,以 ovs 为例:

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: ovs-vlan-100
spec:
  config: '{
      "cniVersion": "0.3.1",
      "type": "ovs",
      "bridge": "br1",
      "vlan": 100
    }'

然后使用它

kind: VM
spec:
  domain:
    devices:
      interfaces:
        - name: default
          masquerade: {}
          bootOrder: 1   # attempt to boot from an external tftp server
          dhcpOptions:
            bootFileName: default_image.bin
            tftpServerName: tftp.example.com
        - name: ovs-net
          bridge: {}
          bootOrder: 2   # if first attempt failed, try to PXE-boot from this L2 networks
  networks:
  - name: default
    pod: {} # Stock pod network
  - name: ovs-net
    multus: # Secondary multus network
      networkName: ovs-vlan-100

它还支持通过 spec.domain.devices.interfaces 配置多种网络接口(前端),例如:

  • bridge: 使用 Linux 网桥进行连接
  • slirp: 使用 QEMU 用户网络模式进行连接
  • sriov: 通过 vfio 透传到 SR-IOV PCI 设备
  • masquerade: 使用 Iptables 规则进行连接以 nat 流量
kind: VM
spec:
  domain:
    devices:
      interfaces:
        - name: default
          model: e1000 # expose e1000 NIC to the guest
          masquerade: {} # connect through a masquerade
          ports:
           - name: http
             port: 80
  networks:
  - name: default
    pod: {}

更多关于 KubeVirt 网络配置相关的内容可以参考其官方文档,还是很详细的:https://kubevirt.io/user-guide/virtual_machines/interfaces_and_networks/#frontend

好了,以上就是最近看到比较频繁问到的一些问题,欢迎大家继续留言讨论。


欢迎订阅我的文章公众号【MoeLove】

TheMoeLove

加载评论