cilium bandwidth-manager qdisc=fq device=wlo1

38 阅读15分钟

# 部署

cilium install \
  --version v1.18.5 \
  --set ipam.mode=kubernetes \
  --set kubeProxyReplacement=true \
  --set k8sServiceHost="debian" \
  --set l2announcements.enabled=true \
  --set k8sServicePort=6443 \
  --set socketLB.hostNamespaceOnly=true \
  --set gatewayAPI.enabled=true \
  --set hubble.relay.enabled=true \
  --set bandwidthManager.enabled=true \
  --set hubble.ui.enabled=true


helm uninstall -n kube-system cilium




环境信息




▶ kgn
NAME     STATUS   ROLES                  AGE   VERSION   INTERNAL-IP       EXTERNAL-IP   OS-IMAGE                         KERNEL-VERSION   CONTAINER-RUNTIME
debian   Ready    control-plane,worker   60m   v1.31.1   192.168.100.100   <none>        Debian GNU/Linux 12 (bookworm)   6.1.0-41-amd64   containerd://1.7.6
(v.v)
root@debian:~
▶ kgp
NAMESPACE     NAME                                          READY   STATUS    RESTARTS   AGE   IP                NODE     NOMINATED NODE   READINESS GATES
kube-system   cilium-bj6hj                                  1/1     Running   0          25m   192.168.100.100   debian   <none>           <none>
kube-system   cilium-envoy-6hc8b                            1/1     Running   0          25m   192.168.100.100   debian   <none>           <none>
kube-system   cilium-operator-6488c548c5-dq8xl              1/1     Running   0          25m   192.168.100.100   debian   <none>           <none>
kube-system   coredns-786bdc6b45-dnshn                      1/1     Running   0          60m   10.233.64.24      debian   <none>           <none>
kube-system   coredns-786bdc6b45-g9r4l                      1/1     Running   0          60m   10.233.64.87      debian   <none>           <none>
kube-system   hubble-relay-68667d879-mpsqb                  1/1     Running   0          25m   10.233.64.93      debian   <none>           <none>
kube-system   hubble-ui-6b65d5f8f5-gljqp                    2/2     Running   0          25m   10.233.64.173     debian   <none>           <none>
kube-system   kube-apiserver-debian                         1/1     Running   0          60m   192.168.100.100   debian   <none>           <none>
kube-system   kube-controller-manager-debian                1/1     Running   0          60m   192.168.100.100   debian   <none>           <none>
kube-system   kube-proxy-56xbl                              1/1     Running   0          60m   192.168.100.100   debian   <none>           <none>
kube-system   kube-scheduler-debian                         1/1     Running   0          60m   192.168.100.100   debian   <none>           <none>
kube-system   nodelocaldns-qqbhc                            1/1     Running   0          60m   192.168.100.100   debian   <none>           <none>
kube-system   openebs-localpv-provisioner-97459bcbc-bspml   1/1     Running   0          60m   10.233.64.189     debian   <none>           <none>
ns7           ns7-netshoot-qos-2sffh                        1/1     Running   0          15m   10.233.64.25      debian   <none>           <none>
ns8           ns8-netshoot-qos-fmv4b                        1/1     Running   0          15m   10.233.64.7       debian   <none>           <none>
(v.v)
root@debian:~
▶



其实单个节点上 pod 之前的 ingress 和 egress 即使配了,也是没有任何作用的,原因相关的 log 如下



root@debian:test/cilium/qos  main ✗                                                                                                                                                 20d9h ◒  ⍉
▶ k logs -f -n kube-system   cilium-bj6hj | grep -i band
time=2025-12-31T11:54:19.05999088Z level=info msg="  --enable-bandwidth-manager='true'"
time=2025-12-31T11:54:19.322425117Z level=info msg="Setting up BPF bandwidth manager" module=agent.datapath.bandwidth-manager
time=2025-12-31T11:54:19.322712424Z level=info msg="Skip setting sysctl as it already meets baseline" module=agent.datapath.bandwidth-manager sysParamName=net.core.netdev_max_backlog sysParamValue=65535 baselineValue=1000
time=2025-12-31T11:54:19.322725382Z level=info msg="Skip setting sysctl as it already meets baseline" module=agent.datapath.bandwidth-manager sysParamName=net.core.somaxconn sysParamValue=32768 baselineValue=4096
time=2025-12-31T11:54:19.322739083Z level=info msg="Skip setting sysctl as it already meets baseline" module=agent.datapath.bandwidth-manager sysParamName=net.ipv4.tcp_max_syn_backlog sysParamValue=1048576 baselineValue=4096
time=2025-12-31T11:54:19.571491965Z level=info msg="Start hook executed" function="*bandwidth.manager.Start (agent.datapath.bandwidth-manager)" duration=249.085208ms
time=2025-12-31T11:54:20.359264644Z level=info msg="Setting qdisc" module=agent.datapath.bandwidth-manager qdisc="mq with fq leaves" device=enp45s0
time=2025-12-31T11:54:20.360229245Z level=info msg="Setting qdisc" module=agent.datapath.bandwidth-manager qdisc=fq device=wlo1
time=2025-12-31T11:56:42.422902794Z level=info msg="Setting qdisc" module=agent.datapath.bandwidth-manager qdisc=fq device=wlo1
time=2025-12-31T12:01:46.323696454Z level=info msg="Setting qdisc" module=agent.datapath.bandwidth-manager qdisc=fq device=wlo1
time=2025-12-31T12:06:50.223046048Z level=info msg="Setting qdisc" module=agent.datapath.bandwidth-manager qdisc=fq device=wlo1
time=2025-12-31T12:11:54.123670679Z level=info msg="Setting qdisc" module=agent.datapath.bandwidth-manager qdisc=fq device=wlo1
time=2025-12-31T12:14:38.623711359Z level=info msg="Setting qdisc" module=agent.datapath.bandwidth-manager qdisc=fq device=wlo1
time=2025-12-31T12:14:38.723781766Z level=info msg="Setting qdisc" module=agent.datapath.bandwidth-manager qdisc=fq device=wlo1
time=2025-12-31T12:14:39.223160653Z level=info msg="Setting qdisc" module=agent.datapath.bandwidth-manager qdisc=fq device=wlo1
time=2025-12-31T12:14:39.323526672Z level=info msg="Setting qdisc" module=agent.datapath.bandwidth-manager qdisc=fq device=wlo1
time=2025-12-31T12:14:39.723796761Z level=info msg="Setting qdisc" module=agent.datapath.bandwidth-manager qdisc=fq device=wlo1
^C
(v.v)
root@debian:test/cilium/qos  main ✗                                                                                                                                                 20d9h ◒  ⍉
▶


日志可以看到 qdisc 只在 物理网卡上,并没有在 容器网卡上


▶ ip a | grep qdisc
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
2: enp44s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
3: enp45s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
4: wlo1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP group default qlen 1000
5: br-1e99749c0b8c: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
6: br-40fa0b13265a: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
7: br-4d4bfedf22e1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
8: br-778a6941e69c: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
9: br-79a7a8f6a36c: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
10: br-c3e3ef694e8c: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
11: br-59744227ec42: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
12: br-286f82f16f30: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
13: br-4b3b98a02fc4: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
14: br-5952fa5a0fb3: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
15: br-ca55a397b3d5: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
16: br-d7aa3305bb0d: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
17: br-796f0856c4c6: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
18: br-aeae2f0a4d77: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
19: br-6dd4c96086ae: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
20: br-84fcbfce58e7: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
21: br-adde10556df8: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
22: br-262cc5160222: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
23: br-76dc15aa5726: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
24: br-93a2d3062da4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
25: br-b54c7524a083: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
26: br-c0633744e9c7: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
27: br-070333275ba3: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
28: br-2e0b401d03d6: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
29: br-2f145767e414: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
30: br-560b87c18eb1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
31: br-8fdb342e3bf4: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
32: br-99f7d8c141d1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
33: br-c8693eaf2c5a: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
34: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
35: veth3eb264a@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
52: veth9d33944@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-93a2d3062da4 state UP group default
53: veth239d783@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-93a2d3062da4 state UP group default
58: nodelocaldns: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default
59: kube-ipvs0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default
60: cilium_net@cilium_host: <BROADCAST,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
61: cilium_host@cilium_net: <BROADCAST,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
62: cilium_vxlan: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
66: lxc0beee4a1d490@if65: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
70: lxcad101d8d2e4f@if69: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
72: lxc961d41c553bb@if71: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
82: lxcd352a614952b@if81: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
84: lxcc64f486f98bd@if83: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
86: lxc_health@if85: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
92: lxc6671a2158cae@if91: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
94: lxc4be81d627498@if93: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
(v.v)
root@debian:test/cilium/qos  main ✗                                                                                                                                                  20d9h ◒
▶
(v.v)
root@debian:test/cilium/qos  main ✗                                                                                                                                                  20d9h ◒
▶
(v.v)
root@debian:test/cilium/qos  main ✗                                                                                                                                                  20d9h ◒
▶ ip a | grep qdisc | grep -v noqueue
2: enp44s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
3: enp45s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
4: wlo1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP group default qlen 1000
58: nodelocaldns: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default
59: kube-ipvs0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default
(v.v)

关于两种 qdisc mq(其实可以忽略我觉得) 和 fq 的使用(k8s 的 node ip 所在的网卡)

从你的 Cilium 日志中可以看到两种 Linux 内核网络队列规则(qdisc,属于 tc 流量控制子系统):mq(Multi-Queue)和 fq(Fair Queueing),两者的定位、核心功能、解决的问题完全不同,且常以「mq 作为顶层容器 + fq 作为叶子调度器」的组合使用(如日志中 mq with fq leaves)。下面逐一拆解差异和使用场景,同时贴合 Cilium 带宽管理的实际上下文。

一、 先明确核心前提

qdisc 是 Linux 内核网络栈中负责数据包排队、调度、转发的核心组件,Cilium 开启带宽管理器(--enable-bandwidth-manager=true)后,会通过配置 qdisc 实现网络 QoS、带宽公平分配、吞吐优化等能力,日志中的 mqfq 是两种常用的高性能 qdisc,但定位截然不同。

二、 mq(Multi-Queue,多队列):核心是「并行化容器,解决吞吐瓶颈」

1. 核心功能与定位

mq 不是独立的数据包调度器,而是一个「队列容器/分发器」,它的核心价值是:

  • 将单个网络设备的流量,按照固定规则(默认是数据包的 hash 值,包含源IP、目的IP、源端口、目的端口等)分发到多个子队列(subqueue) 中;
  • 每个子队列可以绑定独立的内核软中断(ksoftirqd)和网卡硬件队列(RX/TX 队列),实现多核 CPU 并行处理网络流量
  • 本身不负责数据包的转发调度,必须为每个子队列挂载「叶子 qdisc」(如日志中的 fq),才能完成具体的数据包调度工作。

简单说:mq 的作用是「拆分工单,让多个人同时干活,提升整体效率」,不关心「怎么干」,只关心「怎么分」。

2. 关键特性

  • 无独立调度逻辑,仅做流量分发和并行化,依赖叶子 qdisc 实现 QoS;
  • 分发规则保证「同一网络流(如单个 Pod 与服务的 TCP 连接)」的数据包进入同一个子队列,避免数据包乱序;
  • 核心解决「单队列瓶颈」:传统单队列 qdisc 只能由单个 CPU 核心处理,高吞吐场景下会出现 CPU 瓶颈,mq 通过多核并行突破这一限制。

3. 使用场景

  • 高带宽、高吞吐的网络设备(如日志中的 enp45s0,有线千兆/万兆物理网卡、K8s 节点的弹性网卡);
  • 需提升网络吞吐量,解决单 CPU 核心处理瓶颈的场景(如 Cilium 节点转发大量 Pod 间通信、节点对外高流量服务);
  • 必须搭配叶子 qdisc(如 fqfq_codel)使用,形成「并行化 + 精细化调度」的组合(Cilium 日志中 mq with fq leaves 就是最佳实践);
  • 典型场景:云服务器、K8s 工作节点、高流量网关设备、需要线速转发的网络中间件。

三、 fq(Fair Queueing,公平排队):核心是「流公平调度器,解决延迟/公平性问题」

1. 核心功能与定位

fq独立的、基于流的公平调度器,它的核心价值是:

  • 对进入队列的数据包,按照「网络流」(通过 hash 识别,与 mq 分发规则一致)进行分类,每个流对应一个独立的子队列;
  • 采用「加权公平调度策略」,为每个流公平分配带宽和转发机会,避免单个「大流」(如 Pod 大文件下载)占用全部网络带宽,压制「小流」(如 SSH、监控、API 调用等延迟敏感流量);
  • 内置轻量拥塞控制,监控队列长度,避免队列过度积压导致的网络延迟和抖动,性能优于传统的先进先出队列(pfifo_fast)。

简单说:fq 的作用是「合理安排工单顺序,保证每个任务都有公平的执行机会,避免小任务被大任务压制」,关心「怎么干得更合理」。

2. 关键特性

  • 有独立的调度逻辑,可直接挂载在网络设备上独立工作(无需依赖其他 qdisc,如日志中的 wlo1 无线网卡);
  • 核心解决「大流压制小流」问题,保障延迟敏感型流量的转发优先级,降低网络延迟和抖动;
  • 单队列调度模型,无多核并行处理能力,无法解决高吞吐场景下的 CPU 瓶颈;
  • 配置简单,无需手动设置带宽限制,默认即可实现良好的流公平性。

3. 使用场景

  • 中低带宽、对延迟/抖动敏感的设备(如日志中的 wlo1,无线网卡、笔记本有线网卡,吞吐需求低,公平性需求高);
  • 需保障多流公平性,避免大流压制小流的场景(如无线环境下的 Pod 监控、SSH 远程连接、微服务间轻量 API 通信);
  • 作为 mq 的叶子 qdisc,配合 mq 实现「多核并行 + 每队列公平调度」(Cilium 高性能节点的核心配置);
  • 典型场景:桌面端/边缘节点设备、无线网卡、低吞吐 K8s 节点、需要保障公平性的内部服务通信。

四、 mqfq 核心差异对比表

对比维度mq(Multi-Queue)fq(Fair Queueing)
核心定位队列容器/分发器(并行化工具),无独立调度逻辑独立流公平调度器(QoS 工具),负责具体转发调度
核心功能分发流量到多子队列,利用多核并行处理,提升吞吐量按流分类,公平分配带宽,降低延迟/抖动,保障小流
并行处理能力支持(核心价值就是多核并行,解决单核心瓶颈)不支持(单队列调度,无并行化能力)
依赖关系必须挂载叶子 qdisc(如 fq)才能正常工作可独立工作,也可作为 mq 的叶子 qdisc
解决的核心问题单 CPU 核心处理瓶颈,提升网络吞吐上限大流压制小流,优化网络延迟/抖动,保障公平性
适用设备类型高带宽物理网卡(千兆/万兆)、高吞吐设备中低带宽设备(无线网卡)、延迟敏感设备
Cilium 日志对应enp45s0(有线物理网卡,mq with fq leaveswlo1(无线网卡,直接挂载 fq

五、 结合 Cilium 日志的实际场景解读

  1. mq with fq leaves(设备 enp45s0,有线物理网卡)

    • 配置逻辑:Cilium 为高吞吐有线网卡配置「mq 顶层容器 + fq 叶子调度器」的组合,兼顾「吞吐量」和「QoS」;
    • 为什么这么配?:
      • mq 解决有线网卡的高吞吐瓶颈,利用多核 CPU 并行处理不同子队列的流量,满足 K8s 节点内大量 Pod 通信、节点对外服务的吞吐需求;
      • 每个子队列的 fq 保障该队列内的流公平性,避免单个 Pod 大流压制其他 Pod 的延迟敏感小流(如监控、API 调用);
    • 这是 Cilium 高性能节点的最佳实践,适合生产环境 K8s 工作节点。
  2. fq(设备 wlo1,无线网卡)

    • 配置逻辑:Cilium 为无线网卡直接挂载 fq,未使用 mq
    • 为什么这么配?:
      • 无线网卡吞吐相对较低,多核并行需求不高,反而对延迟、抖动和流公平性更敏感;
      • fq 可独立实现流公平调度,避免大流(如 Pod 下载)占用全部无线带宽,同时配置简单,无需额外管理子队列;
    • 适合桌面端、边缘节点等非高吞吐场景。

六、 总结

  1. 核心差异:mq 管「并行化、提吞吐」,fq 管「公平性、降延迟」;
  2. 组合使用:mq + fq 是高性能网络场景的黄金搭档(Cilium 生产环境首选),兼顾吞吐量和 QoS;
  3. 独立使用:fq 适合中低带宽、延迟敏感场景,mq 无法独立使用(必须搭配叶子 qdisc);
  4. Cilium 自动根据设备类型选择合适的 qdisc 配置,体现了其对不同网络场景的适配性,最终实现高效、公平的网络带宽管理。