系列文章

前言

将 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-latencynetwork-throughput
    • CPU 调为性能模式
    • 停止 irqbalance,将网卡中断引脚指向特定 CPU

在网络/网卡设备/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 的负责以下几个方面的流量路由:

  1. ClusterIP: 集群内通过 ClusterIP 的访问
  2. NodePort: 集群内外通过 NodePort 的访问
  3. ExternalIP: 集群外通过 external IP 的访问
  4. 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=servicelb K3s 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=strict Kube 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 驱动程序)

️参考文档

三人行, 必有我师; 知识共享, 天下为公. 本文由东风微鸣技术博客 EWhisper.cn 编写.

Cilium系列-5-Cilium替换KubeProxy的更多相关文章

  1. shell编程系列3--命令替换

    shell编程系列3--命令替换 命令替换 命令替换总结 方法1 `command` 方法2 $(command) 例子1: 获取系统的所有用户并输出 for循环能以空格.换行.tab键作为分隔符 [ ...

  2. 细说ORM之Entity FrameWork系列(被替换)

    一. 谈情怀 从第一次接触开发到现在(2018年),接近五年时间了,最初阶段连接数据库,使用的是[SQL语句+ADO.NET],那时候,什么存储过程.什么事务 统统不理解,生硬的将SQL语句传入SQL ...

  3. Home Assistant系列美化篇——替换天气 UI

    替换天气组件 weather 的默认 UI,生成美观大方的气象卡片. Home Assistant 原生的天气平台不少,国内用户常用的有雅虎天气和 Darksky.其他论坛和社区也有分享自制的和风.彩 ...

  4. 实战c++中的string系列--string的替换、查找(一些与路径相关的操作)

    今天继续写一些string操作. string给我们提供了非常多的方法,可是每在使用的时候,就要费些周折. 场景1: 得到一个std::string full_path = "D:\prog ...

  5. DesignPattern系列__04里氏替换原则

    1.内容引入--继承体系的思考 在继承中,凡是在父类已经实现的方法,其实算是一种契约或者规范,子类不应该在进行更改(重写):但是,由于这一点不是强制要求,所以当子类进行重写的时候,就会对继承体系产生破 ...

  6. Word 查找替换高级玩法系列之 -- 用替换功能删除空白区域

    当你遇到Word文档中时不时的出现一些空白区域的时候会怎么办呢?一个个删除吗?NO!NO!NO!!!那样也太慢了!仅使用替换功能就可以帮你一步搞定它! 下面这篇文档中含有半角空格.全角空格.不间断空格 ...

  7. Cilium使用 (Cilium 3)

    使用k3s测试Cilium,安装步骤可以参见官方文档 Cilium安装使用 docker安装 使用如下命令安装最新版本的docker yum install -y yum-utils \ device ...

  8. Cilium 1.11 发布,带来内核级服务网格、拓扑感知路由....

    原文链接:https://isovalent.com/blog/post/2021-12-release-111 作者:Cilium 母公司 Isovalent 团队 译者:范彬,狄卫华,米开朗基杨 ...

  9. eBPF Cilium实战(1) - 基于团队的网络隔离

    在 Rainbond 集群中,每个团队对应于底层 Kubernetes 的一个 Namespace ,由于之前使用的底层网络无法进行 Namespace 级别的网络管理,所以在 Rainbond 同一 ...

  10. 使用containerlab搭建cilium BGP环境解析

    使用 Containerlab + Kind 快速部署 Cilium BGP 环境一文中使用Containerlab和Cilium实现了模拟环境下的Cilium BGP网络.它使用Containerl ...

随机推荐

  1. 这可能是最全面的MySQL面试八股文了

    什么是MySQL MySQL是一个关系型数据库,它采用表的形式来存储数据.你可以理解成是Excel表格,既然是表的形式存储数据,就有表结构(行和列).行代表每一行数据,列代表该行中的每个值.列上的值是 ...

  2. 新员工入职,前端基础环境变量的配置!node、nvm、vue-cli的安装和下载

    1.安装nvm及配置 首先下载nvm不要下载node,如果电脑已经有node的话需要卸载node,并使用命令提示符来查看node的位置(where node)手动删除 nvm下载链接:https:// ...

  3. Selenium Grid入门详解

    一.简介 Selenium是Selenium套件的一部分,它专门用于并行运行多个测试用例在不同的浏览器.操作系统和机器上 Selenium Grid主要使用 master-slaves或者hub-no ...

  4. Spring Security 报:Encoded password does not look like BCrypt

    SpringBoot 集成 Security 时,报 Encoded password does not look like BCrypt 原因:SecurityConfig 必须 Bean 的形式实 ...

  5. 2022-06-22:golang选择题,以下golang代码输出什么?A:3;B:1;C:4;D:编译失败。 package main import ( “fmt“ ) func mai

    2022-06-22:golang选择题,以下golang代码输出什么?A:3:B:1:C:4:D:编译失败. package main import ( "fmt" ) func ...

  6. Jupyter Notebook (Anaconda3)更改保存文件的默认路径

    打开jupyter 查找路径 1 import os 2 a=os.path.abspath('.') 3 print(a) 创建个人文件夹 E:\pyAPP\JupyterWork 查找修改配置文件 ...

  7. distinct()去重

    distinct()去重 Student.objects.all().distinct()

  8. 浅谈 OI 中各种合并操作

    前言 合并操作一直是 OI 中一大考点,今天请各位跟着笔者来梳理一下各种合并操作. 启发式合并 几乎可以说是最经典的合并了. 假定我们可以在 \(O(k)\) 的时间内往某个集合中插入一个数,那么我们 ...

  9. Cannot read property ‘type‘ of undefined Occurred while linting **\index.jsx:1

    今一个react 中使用mobx 老是提示Cannot read property 'type' of undefined Occurred while linting **\index.jsx:1 ...

  10. mysql_三大范式

    介绍 数据库的三大范式就是数据库的表应该如何设计,应该注意什么. 第一范式 要求每一张表都有一个主键,每一个字段都不可再分. 举例: id username address 1 张三 中国,北京 2 ...