將 Kubernetes 的 CNI 從其他元件切換為 Cilium, 已經可以有效地提升網路的效能. 但是通過對 Cilium 不同模式的切換/功能的啟用, 可以進一步提升 Cilium 的網路效能. 具體調優項包括不限於:
CONFIG_PREEMPT_NONE=y
tuned-adm profile network-latency
或 network-throughput
irqbalance
,將網路卡中斷引腳指向特定 CPU在網路/網路卡裝置/OS等條件滿足的情況下, 我們儘可能多地啟用這些調優選項, 相關優化項會在後續文章逐一更新. 敬請期待.
上篇文章我們啟用了Cilium本地路由, 啟用後對網路吞吐量提升明顯.
今天我們來使用 Cilium 完全替換 KubeProxy, 建立一個沒有 KubeProxy 的 Kubernetes 叢集, 以此來大幅減少 iptables 規則鏈(還有 netfilter), 從而全方位提升網路效能.
Kubernetes 叢集中, 在 Kube Proxy 裡大量用到了 iptables, 在 Kubernetes 叢集規模較大的情況下, 數以千/萬計的 iptables 規則會極大地拖慢 Kubernetes 網路效能, 導致網路請求響應緩慢.
大量 IPTables 規則鏈的範例如下:
Kube Proxy 的負責以下幾個方面的流量路由:
而 Cilium 完全實現了這些功能, 並做到了效能上的大幅提升, 具體 Cilium 官方測試結果如下:
啟用了 DSR 後效能會更強:
接下來我們開始實施替換, Cilium 的 eBPF kube-proxy 可在直接路由和隧道模式下進行替換。
# 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:
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