六、KubeVirt网络
KubeVirt网络相关组件
用户在KubeVirt平台创建虚拟机只需创建一个vmi(Virtual Machine Instance)对象,之后virt-controller会根据vmi对象中的信息创建一个Pod,这里把这个Pod叫做vmi pod。Vmi pod中有kubevirt组件virt-launcher,以及虚拟化相关组件libvirtd和qemu。kubevirt虚拟机网络主要与virt-launcher以及daemonset部署的virt-handler有关:
源码分析
假设当前有vmi.yaml示例:
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| apiVersion: kubevirt.io/v1alpha3 kind: VirtualMachineInstance metadata: annotations: name: test spec: domain: devices: interfaces: - masquerade: {} name: default # ... networks: - name: default pod: {} # ... |
vmi对象中与网络关系密切的参数主要有两个:
Spec.domain.devices.interfaces:定义连接guest接口的方法,支持bridge、slirp、masquerade、sriov和macvtap
Spec.networks:定义连接vm虚拟机网络的源,支持Pod和multus两种类型
注:上述两个参数的name字段需要匹配上
基于上述yaml,我们再分别从virt-handler和virt-launcher两个组件源码层面,看看KubeVirt网络的实现
Virt-handler
当创建一个vmi对象后,virt-hanler初始化网络的入口函数在vmUpdateHelperDefault:
KubeVirt 主要支持以下几种网络模式:
Pod 网络(默认模式)
使用 Kubernetes 集群默认的 Pod 网络。
在这种模式下,每个虚拟机(VM)作为一个 Pod 运行,并与 Kubernetes Pod 网络共享 IP 地址。
默认使用 bridge 插入方式,将 VM 接口桥接到 Pod 的虚拟以太网接口上,使其具备 Pod 网络的 IP,且能够与其他 Pod 通信。
多网络模式(Multus CNI 插件)
使用 Multus CNI 插件,可以为每个 VM 配置多个网络接口。
允许 VM 连接到多个网络,实现隔离或独立的网络拓扑。
常用于复杂的网络拓扑设计,比如电信级应用或 NFV(网络功能虚拟化)场景。
SR-IOV 网络
使用 SR-IOV(单根 I/O 虚拟化)直接将物理网卡的虚拟功能分配给 VM,从而实现高性能网络。
适用于对网络性能要求高的场景,如高性能计算、数据密集型应用等。
SR-IOV 需要集群节点和网卡支持 SR-IOV 功能,并使用 SR-IOV CNI 插件。
MACVLAN 网络
MACVLAN 允许多个接口共享一个物理网络接口,但每个接口拥有独立的 MAC 地址和 IP 地址。
在使用 Multus CNI 时,MACVLAN 可以用于将虚拟机直接连接到物理网络。
6.1 KubeVirt插入方式
KubeVirt 支持不同的网络接口插入方式,用于将 VM 的网络接口与 Pod 网络接口连接。主要的插入方式包括:
Bridge(桥接)
将 VM 的网络接口桥接到 Pod 的 veth(虚拟以太网)接口上。
适用于默认的 Pod 网络模式,VM 获得 Pod 的 IP 地址,并通过该 IP 与其他资源通信。
Masquerade(伪装)
使用网络地址转换(NAT)将 VM 的私有 IP 地址隐藏在 Pod 的 IP 地址后。
适合需要隔离 VM 网络的场景,通常用于虚拟机作为客户端访问外部服务,而不需要直接被访问的场景。
SR-IOV
直接将 SR-IOV 网卡功能分配给 VM,提供接近物理网络的性能。
6.2 KubeVirt卷 的类型
cloudInitConfigDrive:在通过给VM挂载一个文件系统,给cloud-init提供meta-data和user-data
cloudInitNoCloud:在通过给VM挂载一个文件系统,给cloud-init提供meta-data和user-data,生成的文件格式与ConfigDrive不同
containerDisk:指定一个包含qcow2或raw格式的Docker镜像,重启VM数据会丢失
dataVolume:动态创建一个PVC,并用指定的磁盘映像填充该PVC,重启vm数据不会丢失。
emptyDisk:从宿主机上分配固定容量的空间,映射到VM中的一块磁盘,与emptyDir一样,emptyDisk的生命周期与VM等同,重启VM数据会丢失。
ephemeral:在VM启动时创建一个临时卷,VM关闭后自动销毁,临时卷在不需要磁盘持久性的任何情况下都很有用。
hostDisk:在宿主机上创建一个img镜像文件给VM使用。重启VM数据不会丢失。
persistentVolumeClaim:指定一个PVC创建一个块设备。重启VM数据不会丢失。
secret:使用Kubernetes的secret来存储和管理一些敏感数据,比如密码,token,密钥等敏感信息,并把这些信息注入给VM,可以动态更新到Pod,但是不能修改Pod中生成的iso文件,更不能更新到VM。要想更新到VM,需重启VM。
configMap:功能类似于secret,把configMap里的信息写入到iso磁盘中,挂给VM。
****serviceAccount:****功能类似为secret,把serviceAccount里的信息写入到iso磁盘中,挂给VM。
sysprep:以secret或configMap的形式,往VM写入sysprep
示例:创建虚拟机并配置网络
创建一个虚拟机配置文件 vmi.yaml
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| apiVersion: kubevirt.io/v1 kind: VirtualMachine metadata: name: test-vm spec: running: false template: spec: domain: resources: requests: memory: 1024M devices: disks: - name: containerdisk disk: bus: virtio interfaces: - name: default masquerade: {} networks: - name: default pod: {} volumes: - name: containerdisk containerDisk: image: kubevirt/cirros-container-disk-demo:latest |
创建虚拟机
|---------------------------------------------------|
| [root@k8s-master ~]# kubectl apply -f vmi-yaml |
启动虚拟机
|----------------------------------------------------------------------------------------------|
| [root@k8s-master ~]# virtctl start testvm [root@k8s-master ~]# kubectl get vmi test-vm |
验证网络配置
|--------------------------------------------------------------------------------------------------|
| [root@k8s-master~]# kubectl get vmi test-vm -o jsonpath='{.status.interfaces[0].ipAddress}' |
进入虚拟机控制台,验证网络连接
|---------------------------------------------------------------------|
| [root@k8s-master ~]# virtctl console test-vm $ ping -c 3 8.8.8.8 |
配置多网络接口
安装Multus CNI
|--------------------------------------------------------------------------------------------------------------------------------------------------|
| [root@k8s-master~]#kubectl apply -f https://raw.githubusercontent.com/k8snetworkplumbingwg/multus-cni/master/deployments/multus-daemonset.yml |
|-----------------------------------------------------------------------|
| [root@k8s-master~]# kubectl get pods -n kube-system | grep multus |
创建一个额外的网络配置文件
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [root@k8s-master ~]# cat additional-network.yaml apiVersion: "k8s.cni.cncf.io/v1" kind: NetworkAttachmentDefinition metadata: name: additional-network spec: config: '{ "cniVersion": "0.3.1", "type": "bridge", "bridge": "br0", "ipam": { "type": "host-local", "subnet": "10.10.0.0/16", "rangeStart": "10.10.1.2", "rangeEnd": "10.10.3.5", "routes": [ { "dst": "0.0.0.0/0" } ], "gateway": "10.10.1.1" } }' |
应用配置
|-------------------------------------------------------------------------------------------------------------------------------------------|
| |------------------------------------------------------------------| | [root@k8s-master ~]# kubectl apply -f additional-network.yaml | |
配置虚拟机使用额外网络
修改虚拟机配置文件 vm.yaml,添加额外网络接口:
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [root@k8s-master ~]# cat vmi.yaml apiVersion: kubevirt.io/v1 kind: VirtualMachine metadata: name: testvm spec: running: false template: spec: domain: resources: requests: memory: 1024M devices: disks: - name: containerdisk disk: bus: virtio interfaces: - name: default masquerade: {} - name: additional bridge: {} networks: - name: default pod: {} - name: additional multus: networkName: additional-network volumes: - name: containerdisk containerDisk: image: kubevirt/cirros-container-disk-demo:latest |
重新创建虚拟机
|-------------------------------------------------------------------------------------------------------------------------------------------------|
| [root@k8s-master ~]# kubectl delete -f vm.yaml [root@k8s-master ~]# kubectl apply -f vm.yaml [root@k8s-master ~]# virtctl start testvm |
查看虚拟机的运行状态
|-------------------------------------------------|
| [root@k8s-master ~]# kubectl get vmi test-vm |
验证额外的网络接口
|---------------------------------------------------------------------------------|
| [root@k8s-master~]#kubectl get vmi testvm -o jsonpath='{.status.interfaces}' |
验证虚拟机网络连接
|------------------------------------------------------------------------------------|
| [root@k8s-master ~]# virtctl console test-vm $ ip addr show $ ping -c 3 8.8.8.8 |