# 部署
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、带宽公平分配、吞吐优化等能力,日志中的 mq 和 fq 是两种常用的高性能 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(如
fq、fq_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 节点、需要保障公平性的内部服务通信。
四、 mq 与 fq 核心差异对比表
| 对比维度 | mq(Multi-Queue) | fq(Fair Queueing) |
|---|---|---|
| 核心定位 | 队列容器/分发器(并行化工具),无独立调度逻辑 | 独立流公平调度器(QoS 工具),负责具体转发调度 |
| 核心功能 | 分发流量到多子队列,利用多核并行处理,提升吞吐量 | 按流分类,公平分配带宽,降低延迟/抖动,保障小流 |
| 并行处理能力 | 支持(核心价值就是多核并行,解决单核心瓶颈) | 不支持(单队列调度,无并行化能力) |
| 依赖关系 | 必须挂载叶子 qdisc(如 fq)才能正常工作 | 可独立工作,也可作为 mq 的叶子 qdisc |
| 解决的核心问题 | 单 CPU 核心处理瓶颈,提升网络吞吐上限 | 大流压制小流,优化网络延迟/抖动,保障公平性 |
| 适用设备类型 | 高带宽物理网卡(千兆/万兆)、高吞吐设备 | 中低带宽设备(无线网卡)、延迟敏感设备 |
| Cilium 日志对应 | enp45s0(有线物理网卡,mq with fq leaves) | wlo1(无线网卡,直接挂载 fq) |
五、 结合 Cilium 日志的实际场景解读
-
mq with fq leaves(设备enp45s0,有线物理网卡):- 配置逻辑:Cilium 为高吞吐有线网卡配置「
mq顶层容器 +fq叶子调度器」的组合,兼顾「吞吐量」和「QoS」; - 为什么这么配?:
mq解决有线网卡的高吞吐瓶颈,利用多核 CPU 并行处理不同子队列的流量,满足 K8s 节点内大量 Pod 通信、节点对外服务的吞吐需求;- 每个子队列的
fq保障该队列内的流公平性,避免单个 Pod 大流压制其他 Pod 的延迟敏感小流(如监控、API 调用);
- 这是 Cilium 高性能节点的最佳实践,适合生产环境 K8s 工作节点。
- 配置逻辑:Cilium 为高吞吐有线网卡配置「
-
fq(设备wlo1,无线网卡):- 配置逻辑:Cilium 为无线网卡直接挂载
fq,未使用mq; - 为什么这么配?:
- 无线网卡吞吐相对较低,多核并行需求不高,反而对延迟、抖动和流公平性更敏感;
fq可独立实现流公平调度,避免大流(如 Pod 下载)占用全部无线带宽,同时配置简单,无需额外管理子队列;
- 适合桌面端、边缘节点等非高吞吐场景。
- 配置逻辑:Cilium 为无线网卡直接挂载
六、 总结
- 核心差异:
mq管「并行化、提吞吐」,fq管「公平性、降延迟」; - 组合使用:
mq + fq是高性能网络场景的黄金搭档(Cilium 生产环境首选),兼顾吞吐量和 QoS; - 独立使用:
fq适合中低带宽、延迟敏感场景,mq无法独立使用(必须搭配叶子 qdisc); - Cilium 自动根据设备类型选择合适的
qdisc配置,体现了其对不同网络场景的适配性,最终实现高效、公平的网络带宽管理。