☰
KubeVirt Passt 网络绑定插件(Network Passt Binding Plugin)使用与原理指南
2026/9/29 2:48:44 网站建设 项目流程
  • 云原生

【免费下载链接】kubevirt

Kubernetes Virtualization API and runtime in order to define and manage virtual machines.

项目地址:https://gitcode.com/gh_mirrors/ku/kubevirt
点击查看免费下载

导读

KubeVirt 通过 hook sidecar 接口将passt网络绑定插件注册为一种网络绑定机制,在虚拟机(VMI)启动时由 sidecar 把 pod 网络接口改造成基于passt的 vhost-user 后端,从而让非 root 的 virt-launcher 进程也能以无特权方式收发 pod 网络流量。本文以 cmd/sidecars/network-passt-binding/README.md 为主线,结合仓库内 sidecar 服务端、domain 配置器、CNI 辅助插件与网络绑定插件的通用机制源码,完整讲解passt绑定的注册方法、VMI 声明方式、底层工作原理、端口转发与 Istio 兼容行为,以及配套 CNI 的部署方式。读完本文,你将能够在 KubeVirt 集群中注册并使用passt绑定插件,并理解其从 VMI spec 到 libvirt domain XML 的完整改造链路。

注意:passt网络绑定目前仅支持 pod 网络接口(对应 VMI 的pod: {}网络),不适用于 multus 等其他网络类型。


一、Passt 绑定插件的定位与整体架构

1.1 什么是 Passt 绑定

passt(networking/passt)是一个无特权模式的网络地址转换与数据通路工具。KubeVirt 将passt包装为一种网络绑定插件:VMI 不再使用传统的 tap 设备挂接到 bridge,而是通过 libvirt 的vhostuser接口类型把 pod 网络接口直接暴露给passt后端,由passt在宿主命名空间内完成数据包转发。

从源码注释(cmd/sidecars/network-passt-binding/domain/configurator.go)可以看到 sidecar 会把 passt 日志写入/var/run/kubevirt/passt.log,供 KubeVirt 消费和记录:

const ( //nolint:gosec // PasstLogFilePath passt log file path Kubevirt consume and record PasstLogFilePath = "/var/run/kubevirt/passt.log" )

1.2 与 KubeVirt hook sidecar 机制的关系

网络绑定插件属于 KubeVirt 的 hook sidecar 机制。KubeVirt 在定义域(define domain)阶段会调用注册的 sidecar,sidecar 以 gRPC 协议监听 unix socket 并对外暴露OnDefineDomain钩子;virt-launcher 在生成域配置之后、交给 libvirt 之前调用该钩子,让插件有机会修改(mutate)domain XML。

在 docs/network/network-binding-plugin.md 中描述了这一机制:

网络绑定 sidecar 通常会在OnDefineDomain钩子中修改域配置(domain configuration)……sidecar 的实现逻辑需要添加到OnDefineDomain中。

passtsidecar 正是这一机制的典型实现。从 cmd/sidecars/network-passt-binding/main.go 可以看到它的启动流程:

  • 在共享目录hooks.HookSocketsSharedDirectory(即/var/run/kubevirt-hooks)下创建名为passt.sock的 unix socket;
  • 注册InfoServer(对外声明自己支持的 API 版本为v1alpha3)与V1alpha3Server(实现具体的回调);
  • 从环境变量NETWORK_BINDING_PLUGIN_NAME(常量定义见 pkg/hooks/hooks.go)读取绑定的插件名,未设置时默认为passt;
  • 启动 gRPC 服务并等待信号或Shutdown回调触发优雅退出。

二、注册 Passt 绑定插件

在 KubeVirt CR 中通过spec.configuration.network.binding注册passt绑定插件,并指定 sidecar 镜像。以下示例与 cmd/sidecars/network-passt-binding/README.md 中的注册方式一致:

apiVersion: kubevirt.io/v1 kind: KubeVirt metadata: name: kubevirt namespace: kubevirt spec: configuration: network: binding: passt: sidecarImage: registry:5000/kubevirt/network-passt-binding:devel # ...

参数说明:

字段说明
configuration.network.binding.passt以插件名为 key 声明一个网络绑定插件,passt即该插件的注册名
sidecarImage承载 passt sidecar 逻辑的容器镜像,需要在 virt-launcher pod 所在的节点可拉取(私有仓库时需提前配置 imagePullSecret 或节点可访问)

需要注意的是,sidecarImage中的镜像即 cmd/sidecars/network-passt-binding 目录所构建的镜像:它以main.go为入口启动 gRPC 服务,向 KubeVirt 声明自己支持OnDefineDomain与Shutdown两个钩子点(见 cmd/sidecars/network-passt-binding/server/server.go 的Info实现)。


三、在 VMI 中启用 Passt 绑定

注册插件后,在 VMI spec 中把接口的binding.name指向passt,并让该接口挂接 pod 网络:

apiVersion: kubevirt.io/v1 kind: VirtualMachineInstance metadata: name: vmi-passt spec: domain: devices: interfaces: - name: passt binding: name: passt # ... networks: - name: passt-net pod: {} # ...

字段对应关系:

  • interfaces[].binding.name: passt:声明该接口使用已注册的passt绑定插件;
  • networks[].name与接口name一致(示例中passt与passt-net需一一对应,实际使用时接口的name与网络的name必须匹配);
  • networks[].pod: {}:pod 网络,这是 passt 绑定目前唯一支持的网络类型(README 明确强调)。

3.1 sidecar 对绑定声明的校验

从源码看,sidecar 在收到OnDefineDomain调用后会做严格的合法性校验(cmd/sidecars/network-passt-binding/domain/configurator.go):

  1. 在 VMI 的网络列表中查找 pod 网络(LookupPodNetwork),找不到则报pod network not found;
  2. 按网络名查找对应的接口,找不到则报no interface found;
  3. 校验该接口的binding.name是否为passt(即 sidecar 从环境变量读到的绑定插件名),否则报interface %q is not set with Passt network binding plugin;
  4. 从接口状态中查找主网络接口名(PodInterfaceName),后续用它作为 passt 后端的设备名。

这解释了为什么 README 要求 pod 网络接口必须显式设置binding.name: passt:sidecar 只会对满足该条件的接口执行改造。


四、底层工作原理:从 VMI spec 到 domain XML

4.1 调用链

OnDefineDomain钩子的完整调用链如下(对应 cmd/sidecars/network-passt-binding/server/server.go):

  1. KubeVirt virt-launcher 生成原始 domain XML,通过 gRPC 传入;
  2. sidecar 将 VMI 反序列化为VirtualMachineInstance对象,并读取UseVirtioTransitional与 Istio 注入注解;
  3. 调用domain.NewPasstNetworkConfigurator(...)构造配置器;
  4. 调用callback.OnDefineDomain(domainXML, configurator)完成 XML 反序列化、变更与重新序列化(实现见 cmd/sidecars/network-passt-binding/callback/callback.go)——注意这里会显式补回 qemu schema 命名空间,否则部分 domain 参数会因命名空间缺失而失效;
  5. 返回修改后的 domain XML 给 virt-launcher。

4.2 域配置的改造内容

Mutate方法(cmd/sidecars/network-passt-binding/domain/configurator.go)主要做两件事:

(1)替换接口定义:按 VMI 接口的别名(alias)查找 domain XML 中对应的接口并整体替换为生成的 passt 接口;若不存在则追加。generateInterface(同文件 L141-L195)生成的接口具备以下特征:

  • Type: vhostuser,Source.Device指向主 pod 接口名;
  • Backend.Type: passt,并携带日志文件PasstLogFilePath;
  • 模型(model)默认取virtio:当UseVirtioTransitional开启时映射为virtio-transitional,否则为virtio-non-transitional(L151-L168);
  • 继承 VMI 上声明的pciAddress、macAddress、acpiIndex。

(2)强制内存共享:passt 后端要求内存为共享模式。若 domain 已存在非shared的 memory backing access mode,Mutate会直接报错memory backing access mode must be 'shared';否则补齐MemoryBacking.Access.Mode = shared、MemoryBacking.Source.Type = memfd(L116-L125)。这也是使用 passt 绑定时的隐性资源要求:需保证 virt-launcher 能提供 memfd 共享内存。

4.3 端口转发(Port Forward)的生成

generatePortForward(cmd/sidecars/network-passt-binding/domain/configurator.go)根据 VMI 接口声明的ports生成 passt 的端口转发规则:

  • 未声明任何端口时,默认生成tcp与udp两个无范围的转发条目(即全端口转发);
  • 声明了端口时,按协议(默认tcp)分组生成带Start起始端口的 range;
  • 非法端口号或 unsupported 协议会被日志记录并跳过(端口号合法性由 admission webhook 前置校验,因此源码中注释说明非法分支实际不可达);
  • 与 Istio 兼容:当 VMI 带有sidecar.istio.io/inject: "true"注解时,会把istio.ReservedPorts()中的保留端口以Exclude: "yes"的方式排除在 TCP 转发之外,避免与 Istio sidecar 的端口冲突(L200-L204)。

五、配套 CNI:passt-binding-cni

passt 绑定还附带一个 CNI 插件passt-binding-cni,用于在 pod 网络命名空间中调整 sysctl 参数,使非 root 的 virt-launcher(UID 107)也能使用 passt 完成低端口监听与 ping 报文收发。

5.1 CNI 插件行为

从 cmd/cniplugins/passt-binding/pkg/plugin/plugin.go 的实现看,ADD操作会在目标网络命名空间内执行:

  • net.ipv4.ip_unprivileged_port_start = 0:允许非特权进程绑定任意端口(低端口不需要 root 权限);
  • net.ipv4.ping_group_range = 107 107:把 UID 107(virtLauncherUserID)加入 ping 组,允许其发送 ICMP echo。

sysctl 的写入通过 cmd/cniplugins/passt-binding/pkg/plugin/sysctl/sysctl.go 封装,最终落到底层sysctl工具;DEL与CHECK目前为空实现。该 CNI 还支持通过cni-args传入logicNetworkName用于日志标识(config.go)。

5.2 部署方式

仓库提供了安装 CNI 的 DaemonSet 清单 cmd/cniplugins/passt-binding/passt-binding-ds.yaml:

apiVersion: apps/v1 kind: DaemonSet metadata: name: passt-binding-cni namespace: kubevirt spec: # ... template: spec: containers: - name: installer image: registry:5000/kubevirt/network-passt-binding-cni:devel command: [ "/bin/sh", "-ce" ] args: - | ls -la "/cni/kubevirt-passt-binding" cp -f "/cni/kubevirt-passt-binding" "/opt/cni/bin" echo "passt binding CNI plugin installation complete..sleep infinity" sleep 2147483647 securityContext: privileged: true volumeMounts: - name: cnibin mountPath: /opt/cni/bin volumes: - name: cnibin hostPath: path: /opt/cni/bin

该 DaemonSet 以特权容器把编译好的kubevirt-passt-binding二进制拷贝到各节点的/opt/cni/bin,从而让节点上的 CNI 链(如 Multus)能够调用它。这意味着使用 passt 绑定前需要在集群节点上安装该 CNI 二进制,否则 virt-launcher pod 网络命名空间不会获得上述 sysctl 调整,passt 的无特权数据通路可能受限。


六、Hook 点与生命周期

passtsidecar 通过InfoServer.Info声明了两个钩子点(cmd/sidecars/network-passt-binding/server/server.go):

Hook 点优先级作用
OnDefineDomain0在域定义阶段修改 domain XML,注入 vhost-user/passt 接口与共享内存配置
Shutdown0收到 shutdown 通知后向Done通道发送信号,触发 gRPC 服务优雅退出

生命周期行为:

  • OnDefineDomain:解析 VMI → 校验绑定声明 → 构造配置器 → 回调执行 XML 变更(见 callback.go);
  • Shutdown:记录日志Shutdown passt network binding并写入Done通道(server.go L125-L129);
  • 服务退出:waitForShutdown同时监听操作系统信号(SIGHUP/SIGINT/SIGTERM/SIGQUIT)、gRPC 服务错误与 shutdown 通道,任一触发后调用server.GracefulStop()(server.go L131-L161)。

七、使用前提与限制汇总

  1. 仅支持 pod 网络:README 明确指出 passt 绑定只适用于 pod 网络接口(pod: {}),multus 等附加网络不在支持范围;
  2. 需要注册 sidecar 镜像:必须先在 KubeVirt CR 的configuration.network.binding中注册passt并指定可拉取的sidecarImage;
  3. 需要安装 CNI 插件:集群节点需通过 passt-binding-ds.yaml 之类的 DaemonSet 部署kubevirt-passt-bindingCNI 到/opt/cni/bin;
  4. 内存共享要求:domain 必须满足memoryBacking.access.mode = shared且source.type = memfd,若已有冲突配置 sidecar 会拒绝启动(报错并保持原 XML);
  5. Istio 兼容:启用 Istio 注入时 passt 会排除 Istio 保留端口,避免端口冲突;
  6. 接口模型:默认使用 virtio 模型,开启useVirtioTransitional时映射为virtio-transitional。

八、深入阅读

  • 本文主体文档:cmd/sidecars/network-passt-binding/README.md
  • Sidecar 入口与 gRPC 服务:cmd/sidecars/network-passt-binding/main.go、cmd/sidecars/network-passt-binding/server/server.go
  • 域配置改造与端口转发:cmd/sidecars/network-passt-binding/domain/configurator.go
  • XML 回调处理:cmd/sidecars/network-passt-binding/callback/callback.go
  • Sidecar 测试用例:cmd/sidecars/network-passt-binding/domain/configurator_test.go、cmd/sidecars/network-passt-binding/callback/callback_test.go
  • CNI 插件:cmd/cniplugins/passt-binding/pkg/plugin/plugin.go、cmd/cniplugins/passt-binding/pkg/plugin/config.go
  • CNI 安装清单:cmd/cniplugins/passt-binding/passt-binding-ds.yaml
  • 网络绑定插件通用机制:docs/network/network-binding-plugin.md
  • 云原生

【免费下载链接】kubevirt

Kubernetes Virtualization API and runtime in order to define and manage virtual machines.

项目地址:https://gitcode.com/gh_mirrors/ku/kubevirt
点击查看免费下载
上一篇:macOS视频预览终极指南:让Finder完美支持多格式视频
下一篇:Video Analyst:5大核心功能解析视频理解开源利器

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询