簡介
Calico 從 v3.13 開始,集成了 eBPF 資料平面,
關于什么是 eBPF, 以及 Calico 為什么引入了 eBPF , 并不是本篇文章的重點,感興趣的朋友可以自行閱讀相關檔案,
相比于 Calico 的默認基于 iptables 資料平面,eBPF 具有更高的吞吐量以外, 還具有 source IP preservation 這個功能,
在 K8s 中通常都是直接或者間接以 NodePort 方式對外暴露介面的,而對于 K8s 這個分布式集群來講,通常情況下,客戶端連接 Node Port 埠的節點和負責回應請求的后端業務 Pod 所在的節點不是同一個節點,為了打通整個資料鏈路,就不可避免的引入了 SNAT,但是這樣顯然也會帶來一個副作用,即業務 Pod 在收到 Packet 以后,其 SRC IP 已經不再是客戶端的實際 IP(被偽裝成節點的內網 IP ),另一方面,對于一些業務應用來講,獲取客戶端 IP 是一個實實在在的剛需,比如:業務應用需要通過客戶端 IP 來獲取客戶登陸的 geo 資訊,
目前 K8s 主要是通過設定 externaltrafficpolicy 來規避這個問題的,但是這個方案本身并不能完全令人滿意,Calico 從 v3.13 開始通過集成 eBPF 優雅地解決了這個問題,
在本篇文章中,我們將首先演示通過 KubeKey 創建一個標準的 K8s 集群,并切換資料平面到 eBPF,最后基于該資料平面做一個簡單的演示,
前提條件
較新的內核, 一般 v4.18+ 即可,
筆者的測驗集群:

部署 K8s 集群
Kubekey 默認的 CNI 插件為 Calico(ipip模式),這里為了部署方便,直接使用 KubeKey 部署了一個全新的 K8s 集群,版本為 v1.18.6 ,KubeKey 的詳細用法參見檔案,
切換 Calico 資料平面
Calico 支持多種資料平面,通過修改配置可以方便地進行切換,詳細資訊可以參見官方檔案,
主要分為以下幾步:
- 確認 BPF 檔案系統已經掛載:
mount | grep "/sys/fs/bpf"
如果能看到以下資訊,則代表 BPF 檔案系統已經掛載:

- 創建 Calico 組態檔:
- 首先獲取 ks-apiserver endpoints 資訊:
kubectl get endpoints kubernetes -o wide
- 由于 KubeKey 是通過 manifest 方式安裝的 Calico,這里我們只需要創建一個 cm 即可:
kind: ConfigMap
apiVersion: v1
metadata:
name: kubernetes-services-endpoint
namespace: kube-system
data:
KUBERNETES_SERVICE_HOST: "<API server host>"
KUBERNETES_SERVICE_PORT: "<API server port>"
- 重啟 Calico pods,并等待 Calico Pod 重新變為 Running 狀態
kubectl delete pod -n kube-system -l k8s-app=calico-node
kubectl delete pod -n kube-system -l k8s-app=calico-kube-controllers
- 關閉 kube-proxy
kubectl patch ds -n kube-system kube-proxy -p '{"spec":{"template":{"spec":{"nodeSelector":{"non-calico": "true"}}}}}'
- 開啟 eBPF 模式
calicoctl patch felixconfiguration default --patch='{"spec": {"bpfEnabled": true}}'
- 由于我們需要保留客戶端 IP,所以需要開啟
DSR模式,
calicoctl patch felixconfiguration default --patch='{"spec": {"bpfExternalServiceMode": "DSR"}}'
至此,Calico 的整個網路環境已經配置完畢,

體驗
為了驗證 Calico 切換到 eBPF 資料平面以后,后端確實可以拿到客戶端的真實 IP ,下面我們會在集群中部署一個 Nginx 服務,并通過 nodeport 方式暴露介面,
創建 Nginx 實體并暴露外部介面:
master:~$ kubectl apply -f - <<EOF
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 80
nodePort: 30604
EOF
等待 Pod 變為 Running 狀態:

外部呼叫 Nginx 服務:
curl http://<external-ip>:30604
查詢 Nginx 日志,查看 client IP:

注意:如果集群本身部署在云平臺環境中,如果節點位于 VPC 網路當中,需要設定相應的埠轉發規則,并開啟相應的防火墻埠,
本文由博客一文多發平臺 OpenWrite 發布!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/288462.html
標籤:其他
上一篇:美術理論基礎
