大家好,我是张晋涛。
上一篇文章 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 的核心优势其实在于它的抽象和封装,它提供了类似 VirtualMachine
和 VirtualMachineInstance
等自定义资源,
用户可以直接通过这些声明式配置就完成对应环境的准备。
但如果是直接使用 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
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】