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 的核心优势其实在于它的抽象和封装,它提供了类似 VirtualMachine
和 VirtualMachineInstance
等自定义资源,
用户可以直接通过这些声明式配置就完成对应环境的准备。
但如果是直接使用 KVM 的话,则还需要使用 virsh
之类的命令进行操作,会比较麻烦。
而且最为重要的一点,KubeVirt 底层实际上也使用了 QEMU/KVM 等技术,只是它将这些技术带入了 Kubernetes 世界,以一种更加 Kubernetes 原生的方式提供给用户使用。
KubeVirt 有什么劣势?
KubeVirt 作为一项并没有那么广泛使用的技术,引入它除去有上文中提到的优势外,它自然也有一些劣势,或者说不适用的场景。
- 由于 KubeVirt 实际是使用虚拟化技术,所以相比于直接用容器化技术,它带来的开销自然也更多,启动时间变长等。这也是为什么会有一些轻量级虚拟化技术 MicroVM 存在的原因;
- 同样的,由于是用了虚拟化技术,它通常适用于物理机节点,或者支持嵌套虚拟化的节点。可以看看这个配置
/etc/modprobe.d/kvm.conf
➜ ~ cat /etc/modprobe.d/kvm.conf
1. Setting modprobe kvm_intel/kvm_amd nested = 1
1. only enables Nested Virtualization until the next reboot or
1. module reload. Uncomment the option applicable
1. to your system below to enable the feature permanently.
1. 1. User changes in this file are preserved across upgrades.
1. 1. For Intel
#options kvm_intel nested=1
1. 1. For AMD
#options kvm_amd nested=1
- 引入 KubeVirt 自然也会带来一定的学习成本和复杂度,并非所有的 Kubernetes 生态的组件都支持 KubeVirt;
- 并且由于 KubeVirt 并不像容器化技术那么“原生”,所以难免存在一些兼容问题,这个就需要 case by case 的解决了;
KubeVirt 有哪些用例?
有小伙伴问到真的有人在用 KubeVirt 吗?在 KubeVirt 仓库中有一个文件,是对应厂商自己登记的,当然,这应该也不是全部的用例,可能还有一些未进行登记。 github.com/kubevirt/ku…
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 网络配置相关的内容可以参考其官方文档,还是很详细的:kubevirt.io/user-guide/…
好了,以上就是最近看到比较频繁问到的一些问题,欢迎大家继续留言讨论。
欢迎订阅我的文章公众号【MoeLove】