Cilium系列-5-Cilium替换KubeProxy
系列文章
前言
将 Kubernetes 的 CNI 从其他组件切换为 Cilium, 已经可以有效地提升网络的性能. 但是通过对 Cilium 不同模式的切换/功能的启用, 可以进一步提升 Cilium 的网络性能. 具体调优项包括不限于:
- 启用本地路由(Native Routing)
- 完全替换 KubeProxy
- IP 地址伪装(Masquerading)切换为基于 eBPF 的模式
- Kubernetes NodePort 实现在 DSR(Direct Server Return) 模式下运行
- 绕过 iptables 连接跟踪(Bypass iptables Connection Tracking)
- 主机路由(Host Routing)切换为给予 BPF 的模式 (需要 Linux Kernel >= 5.10)
- 启用 IPv6 BIG TCP (需要 Linux Kernel >= 5.19)
- 禁用 Hubble(但是不建议, 可观察性比一点点的性能提升更重要)
- 修改 MTU 为巨型帧(jumbo frames) (需要网络条件允许)
- 启用带宽管理器(Bandwidth Manager) (需要 Kernel >= 5.1)
- 启用 Pod 的 BBR 拥塞控制 (需要 Kernel >= 5.18)
- 启用 XDP 加速 (需要 支持本地 XDP 驱动程序)
- (高级用户可选)调整 eBPF Map Size
- Linux Kernel 优化和升级
CONFIG_PREEMPT_NONE=y
- 其他:
- tuned network-* profiles, 如:
tuned-adm profile network-latency或network-throughput - CPU 调为性能模式
- 停止
irqbalance,将网卡中断引脚指向特定 CPU
- tuned network-* profiles, 如:
在网络/网卡设备/OS等条件满足的情况下, 我们尽可能多地启用这些调优选项, 相关优化项会在后续文章逐一更新. 敬请期待.
上篇文章我们启用了Cilium本地路由, 启用后对网络吞吐量提升明显.
今天我们来使用 Cilium 完全替换 KubeProxy, 创建一个没有 KubeProxy 的 Kubernetes 集群, 以此来大幅减少 iptables 规则链(还有 netfilter), 从而全方位提升网络性能.
测试环境
- Cilium 1.13.4
- K3s v1.26.6+k3s1
- OS
- 3台 Ubuntu 23.04 VM, Kernel 6.2, x86
背景
Kubernetes 集群中, 在 Kube Proxy 里大量用到了 iptables, 在 Kubernetes 集群规模较大的情况下, 数以千/万计的 iptables 规则会极大地拖慢 Kubernetes 网络性能, 导致网络请求响应缓慢.
大量 IPTables 规则链的示例如下:

Kube Proxy 的用途
Kube Proxy 的负责以下几个方面的流量路由:
- ClusterIP: 集群内通过 ClusterIP 的访问
- NodePort: 集群内外通过 NodePort 的访问
- ExternalIP: 集群外通过 external IP 的访问
- LoadBalancer: 集群外通过 LoadBalancer 的访问.
而 Cilium 完全实现了这些功能, 并做到了性能上的大幅提升, 具体 Cilium 官方测试结果如下:

启用了 DSR 后性能会更强:

实施步骤
接下来我们开始实施替换, Cilium 的 eBPF kube-proxy 可在直接路由和隧道模式下进行替换。
重新安装 K3s
# Server Node
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn INSTALL_K3S_EXEC='--write-kubeconfig-mode=644 --flannel-backend=none --disable-network-policy --disable=servicelb --prefer-bundled-bin --disable-kube-proxy' INSTALL_K3S_VERSION=v1.26.6+k3s1 sh -
说明如下:
--disable=servicelbK3s servicelb 不是 Kubernetes 的标准组件, 为了减少干扰, 先去掉它.--disable-kube-proxy禁用 Kube Proxy
重新安装 Cilium
视情况不同, 可能需要卸载 Cilium:
helm uninstall cilium -n kube-system
重新安装, 重新安装时直接加上 kubeProxyReplacement 参数:
helm install cilium cilium/cilium --version 1.13.4 \
--namespace kube-system \
--set operator.replicas=1 \
--set k8sServiceHost=192.168.2.43 \
--set k8sServicePort=6443 \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true \
--set tunnel=disabled \
--set autoDirectNodeRoutes=true \
--set ipv4NativeRoutingCIDR=10.0.0.0/22 \
--set kubeProxyReplacement=strict
说明如下:
kubeProxyReplacement=strictKube Proxy 替换使用严格模式. 而在默认情况下, Helm 会设置kubeProxyReplacement=disabled,这只会启用 ClusterIP 服务的群集内负载平衡。
基本信息验证
执行完成后进行验证:
$ kubectl -n kube-system exec ds/cilium -- cilium status | grep KubeProxyReplacement
KubeProxyReplacement: Strict [eth0 192.168.2.3 (Direct Routing)]
使用 --verbose 查看全部细节:
$ kubectl -n kube-system exec ds/cilium -- cilium status --verbose
...
KubeProxyReplacement Details:
Status: Strict
Socket LB: Enabled
Socket LB Tracing: Enabled
Socket LB Coverage: Full
Devices: eth0 192.168.2.3 (Direct Routing)
Mode: SNAT
Backend Selection: Random
Session Affinity: Enabled
Graceful Termination: Enabled
NAT46/64 Support: Disabled
XDP Acceleration: Disabled
Services:
- ClusterIP: Enabled
- NodePort: Enabled (Range: 30000-32767)
- LoadBalancer: Enabled
- externalIPs: Enabled
- HostPort: Enabled
实战验证
接下来, 我们可以创建一个 Nginx 部署。然后,创建一个新的 NodePort 服务,并验证 Cilium 是否正确安装了该服务。
创建 Nginx Deploy:
cat << EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
EOF
下一步,为这两个实例创建一个 NodePort 服务:
$ kubectl expose deployment my-nginx --type=NodePort --port=80
service/my-nginx exposed
查看 NodePort 服务端口等信息:
$ kubectl get svc my-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx NodePort 10.43.204.231 <none> 80:32727/TCP 96s
借助 cilium service list 命令,我们可以验证 Cilium 的 eBPF kube-proxy 替代程序是否创建了新的 NodePort 服务。在本例中,创建了端口号为 32727 的服务(位于网卡设备 eth0):
$ kubectl -n kube-system exec ds/cilium -- cilium service list
ID Frontend Service Type Backend
...
32 192.168.2.3:32727 NodePort 1 => 10.0.0.70:80 (active)
2 => 10.0.2.96:80 (active)
33 0.0.0.0:32727 NodePort 1 => 10.0.0.70:0 (active)
2 => 10.0.2.96:80 (active)
同时,我们还可以使用主机名空间中的 iptables 验证是否存在针对该服务的 iptables 规则:
casey@cilium-62-1:~$ sudo iptables-save | grep KUBE-SVC
[sudo] casey 的密码:
casey@cilium-62-1:~$
上方结果为空, 证明已经没有了 KUBE-SVC 相关的 IPTables 规则.
我们可以使用 curl 对 NodePort ClusterIP PodIP 等进行测试:
node_port=$(kubectl get svc my-nginx -o=jsonpath='{@.spec.ports[0].nodePort}')
# localhost+NodePort
curl 127.0.0.1:$node_port
# eth0+NodePort
curl 192.168.2.3:$node_port
# ClusterIP
curl 10.43.204.231:80
# 本机PodIP
curl 10.0.0.70:80
# 其他Node PodIP
curl 10.0.2.96:80
Note
最后 2 条能访问到也是因为之前启用了本地路由(Native Routing)的原因
都可以成功访问:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
总结
Kube Proxy 对 iptables 的大量使用给大规模 Kubernetes 集群的网络性能带来了负面影响, 通过利用 Cilium 完全替换 Kube Proxy, 可以大幅提升 Kubernetes 处理 ClusterIP/NodePort/LoadBalancer/externalIPs 等的网络性能表现.
至此, 性能调优已完成:
- ️ 启用本地路由(Native Routing)
- ️ 完全替换 KubeProxy
- IP 地址伪装(Masquerading)切换为基于 eBPF 的模式
- Kubernetes NodePort 实现在 DSR(Direct Server Return) 模式下运行
- 绕过 iptables 连接跟踪(Bypass iptables Connection Tracking)
- 主机路由(Host Routing)切换为给予 BPF 的模式 (需要 Linux Kernel >= 5.10)
- 启用 IPv6 BIG TCP (需要 Linux Kernel >= 5.19)
- 修改 MTU 为巨型帧(jumbo frames) (需要网络条件允许)
- 启用带宽管理器(Bandwidth Manager) (需要 Kernel >= 5.1)
- 启用 Pod 的 BBR 拥塞控制 (需要 Kernel >= 5.18)
- 启用 XDP 加速 (需要 支持本地 XDP 驱动程序)
️参考文档
- Kubernetes Without kube-proxy — Cilium 1.13.4 documentation
- Liberating k8s from kube-proxy and iptables - Google 幻灯片
三人行, 必有我师; 知识共享, 天下为公. 本文由东风微鸣技术博客 EWhisper.cn 编写.
Cilium系列-5-Cilium替换KubeProxy的更多相关文章
- shell编程系列3--命令替换
shell编程系列3--命令替换 命令替换 命令替换总结 方法1 `command` 方法2 $(command) 例子1: 获取系统的所有用户并输出 for循环能以空格.换行.tab键作为分隔符 [ ...
- 细说ORM之Entity FrameWork系列(被替换)
一. 谈情怀 从第一次接触开发到现在(2018年),接近五年时间了,最初阶段连接数据库,使用的是[SQL语句+ADO.NET],那时候,什么存储过程.什么事务 统统不理解,生硬的将SQL语句传入SQL ...
- Home Assistant系列美化篇——替换天气 UI
替换天气组件 weather 的默认 UI,生成美观大方的气象卡片. Home Assistant 原生的天气平台不少,国内用户常用的有雅虎天气和 Darksky.其他论坛和社区也有分享自制的和风.彩 ...
- 实战c++中的string系列--string的替换、查找(一些与路径相关的操作)
今天继续写一些string操作. string给我们提供了非常多的方法,可是每在使用的时候,就要费些周折. 场景1: 得到一个std::string full_path = "D:\prog ...
- DesignPattern系列__04里氏替换原则
1.内容引入--继承体系的思考 在继承中,凡是在父类已经实现的方法,其实算是一种契约或者规范,子类不应该在进行更改(重写):但是,由于这一点不是强制要求,所以当子类进行重写的时候,就会对继承体系产生破 ...
- Word 查找替换高级玩法系列之 -- 用替换功能删除空白区域
当你遇到Word文档中时不时的出现一些空白区域的时候会怎么办呢?一个个删除吗?NO!NO!NO!!!那样也太慢了!仅使用替换功能就可以帮你一步搞定它! 下面这篇文档中含有半角空格.全角空格.不间断空格 ...
- Cilium使用 (Cilium 3)
使用k3s测试Cilium,安装步骤可以参见官方文档 Cilium安装使用 docker安装 使用如下命令安装最新版本的docker yum install -y yum-utils \ device ...
- Cilium 1.11 发布,带来内核级服务网格、拓扑感知路由....
原文链接:https://isovalent.com/blog/post/2021-12-release-111 作者:Cilium 母公司 Isovalent 团队 译者:范彬,狄卫华,米开朗基杨 ...
- eBPF Cilium实战(1) - 基于团队的网络隔离
在 Rainbond 集群中,每个团队对应于底层 Kubernetes 的一个 Namespace ,由于之前使用的底层网络无法进行 Namespace 级别的网络管理,所以在 Rainbond 同一 ...
- 使用containerlab搭建cilium BGP环境解析
使用 Containerlab + Kind 快速部署 Cilium BGP 环境一文中使用Containerlab和Cilium实现了模拟环境下的Cilium BGP网络.它使用Containerl ...
随机推荐
- java-io FileInputStream文件拷贝
1.编写代码 main方法: public static void main(String[] args) throws IOException { String pathFileUrl =" ...
- 海思码率控制相关参数调优(CBR/VBR)
1.CBR 海思相关参数调整(在Hisi板,cat /proc/umap/rc 可查看相关参数变化) 1.1 RC参数 1.2 VENC参数 VENC_PARAM_H264_CBR_S/VENC_PA ...
- 小知识:使用errorstack定位特定问题
有客户遇到ORA-2289的报错,同事协助去现场排查,我帮着远程共同check下. 客户只是应用端报出的错误,为了进一步定位,服务端需要开errorstack协助定位具体问题. 下面就以这个ORA-2 ...
- 《HelloGitHub》第 85 期
兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣.入门级的开源项目. https://github.com/521xueweiha ...
- 深度学习-08(PaddlePaddle文本分类)
深度学习-08(PaddlePaddle文本分类) 文章目录 深度学习-08(PaddlePaddle文本分类) NLP概述 NLP基本概念 什么是NLP NLP的主要任务 传统NLP方法 传统NLP ...
- 2022-05-14:语法补全功能,比如“as soon as possible“, 当我们识别到“as soon as“时, 基本即可判定用户需要键入“possible“。 设计一个统计词频的模型,
2022-05-14:语法补全功能,比如"as soon as possible", 当我们识别到"as soon as"时, 基本即可判定用户需要键入&quo ...
- 2021-05-13:数组中所有数都异或起来的结果,叫做异或和。给定一个数组arr,返回arr的最大子数组异或和。
2021-05-13:数组中所有数都异或起来的结果,叫做异或和.给定一个数组arr,返回arr的最大子数组异或和. 前缀树.一个数,用二进制表示,0走左边分支,1走右边分支. 时间复杂度:O(N). ...
- 2021-08-13:给定一个每一行有序、每一列也有序,整体可能无序的二维数组 ,在给定一个正数k,返回二维数组中,最小的第k个数。
2021-08-13:给定一个每一行有序.每一列也有序,整体可能无序的二维数组 ,在给定一个正数k,返回二维数组中,最小的第k个数. 福大大 答案2021-08-13: 二分法. 代码用golang编 ...
- [AGC055A] ABC Identity 题解
[AGC055A] ABC Identity 题解 题目描述 给定长度为 \(3n (1 \le n \le 2e5)\) 的序列,其中字母 A,B,C 各有 \(n\) 个. 一个合法序列 \(T\ ...
- JUC同步锁原理
JUC同步锁原理 1.锁的本质 1.什么是锁? 通俗来讲,锁要保证的就是原子性,就是一个代码块不允许多线程同时执行,就是锁.从生活的角度上来说,就比如你要去上厕所,当你在上厕所期间,你会把门锁上, ...