適用范圍:騰訊云容器服務(wù)(Tencent Kubernetes Engine ,TKE), 以下簡稱 TKE。
當(dāng)需要能感知到服務(wù)請求來源去滿足一些業(yè)務(wù)需求時,就需要后端服務(wù)能準(zhǔn)確獲取到請求客戶端的真實源 IP, 比如以下場景:
在TKE中默認(rèn)的外部負(fù)載均衡器是 騰訊云負(fù)載均衡器,作為服務(wù)流量的訪問首入口,騰訊云負(fù)載均衡器會將請求流量負(fù)載轉(zhuǎn)發(fā)到 Kubernetes 工作節(jié)點的 Kubernets Service(默認(rèn)),此負(fù)載均衡過程會保留客戶端真實源 IP(透傳轉(zhuǎn)發(fā)),但在 Kubernetes Service 轉(zhuǎn)發(fā)場景下,無論是使用 iptbales 還是 ipvs 的負(fù)載均衡轉(zhuǎn)發(fā)模式,轉(zhuǎn)發(fā)時都會對數(shù)據(jù)包做 SNAT,即不會保留客戶端真實源 IP,為了能夠準(zhǔn)確的獲取到客戶端的真實源 IP,在 TKE 使用場景下,主要有四種方法獲取客戶端真實源 IP,下面將逐個展開介紹下。
要啟用保留客戶端 IP 功能,可在 Service 資源中配置字段 Service.spec.externalTrafficPolicy
,此字段表示服務(wù)是否希望將外部流量路由到節(jié)點本地或集群范圍的端點。有兩個選項值:Cluster
(默認(rèn))和 Local
方式,如下圖所示:
Cluster
表示隱藏了客戶端源 IP, LoadBalancer
和 NodePort
類型服務(wù)流量可能會被轉(zhuǎn)發(fā)到其他節(jié)點的 Pods; Local
表示保留客戶端源 IP 并避免 LoadBalancer
和 NodePort
類型的服務(wù)流量轉(zhuǎn)發(fā)到其他節(jié)點的 Pods,詳情請參考 kubernets設(shè)置外部負(fù)載均衡器說明。相關(guān) YAML 配置示例如下:
apiVersion: v1
kind: Service
metadata:
name: example-Service
spec:
selector:
app: example-Service
ports:
- port: 8765
targetPort: 9376
externalTrafficPolicy: Local
type: LoadBalancer
優(yōu)點:只需要修改 Kubernets Service 資源配置即可。
缺點:會存在潛在的 Pods(Endpoints)流量負(fù)載不均衡風(fēng)險。
使用TKE原生支持的 CLB 直通 Pod 的轉(zhuǎn)發(fā)功能(CLB 透傳轉(zhuǎn)發(fā),并繞過 Kubernetes Service 流量轉(zhuǎn)發(fā)),后端 Pods 收到的請求的源IP即是客戶端真實源IP,此方式無論是在四層還是七層服務(wù)的轉(zhuǎn)發(fā)場景下都適用,轉(zhuǎn)發(fā)原理如下圖:
詳細(xì)介紹和配置請參考文檔 TKE場景下騰訊云CLB直通Pod使用場景介紹。
優(yōu)點:TKE原生支持的功能特性,只需在控制臺按照文檔配置即可。
缺點:集群需要開啟 VPC-CNI 模式網(wǎng)絡(luò),詳情參考文檔 VPC-CNI 模式說明
在七層(HTTP/HTTPS)服務(wù)轉(zhuǎn)發(fā)場景下,可以通過獲取 Http Header 中 X-Forwarded-For
和 X-Real-IP
字段的值來獲取客戶端真實源 IP, TKE 中有兩種場景使用方式,原理介紹如下:
在場景一中,騰訊云負(fù)載均衡器(CLB 七層) 默認(rèn)會將客戶端真實源IP放到 HTTP Header 的 X-Forwarded-For
和 X-Real-IP
字段,當(dāng)服務(wù)流量在經(jīng)過 Service 四層轉(zhuǎn)發(fā)后會保留上述字段,后端通過WEB服務(wù)器代理配置或應(yīng)用代碼方式獲取到客戶端真實源IP,詳情參考請文檔 負(fù)載均衡如何獲取客戶端真實 IP - 最佳實踐 - 文檔中心 - 騰訊云;
在場景二中, Nginx Ingress 服務(wù)部署需要 Nginx Ingress 能直接感知客戶端真實源 IP,可以采用保留客戶端源IP的配置方式(詳情參考 kubernets設(shè)置外部負(fù)載均衡器說明 ),或通過 CLB 直通 Pod 的方式(詳情參考 TKE場景下騰訊云CLB直通Pod使用場景介紹),當(dāng) Nginx Ingress 在轉(zhuǎn)發(fā)請求時會通過 X-Forwarded-For
和 X-Real-IP
字段來記錄客戶端源 IP,后端可以通過此字段獲得客戶端真實源 IP。
下面詳細(xì)介紹在 TKE 中兩種場景的配置使用方法:
在TKE控制臺先為工作負(fù)載創(chuàng)建一個主機(jī)端口訪問方式的 Service 資源,如下圖:
然后在控制臺為 Service 新建一個對應(yīng)的 Ingress 訪問入口,如下圖:
待配置生效后,在后端通過獲取 HTTP Header 中的 X-Forwarded-For
或 X-Real-IP
字段值得到客戶端真實源 IP。后端抓包測試結(jié)果示例如下:
Nginx Ingress 可以通過 TKE 應(yīng)用商店、自定義 YAML 配置或使用官方(helm 安裝)方式安裝,原理和部署方法可參考文檔 在 TKE 上部署 Nginx Ingress 中的部署方案一或方案三,若選擇方案一部署,則需要修改 Nginx Ingress Controller Service 的 externalTrafficPolicy
字段值為 Local
。安裝完成后,會在TKE控制臺自動為 Nginx Ingress Controller 服務(wù)創(chuàng)建一個 CLB(四層)訪問入口,如下圖所示:
為要轉(zhuǎn)發(fā)的后端服務(wù)創(chuàng)建一個 Ingress 資源并配置轉(zhuǎn)發(fā)規(guī)則, 可以使用以下 YAML 創(chuàng)建:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx # ingressClass類為"nginx"
name: example
namespace: default
spec:
rules: # 配置服務(wù)轉(zhuǎn)發(fā)規(guī)則
- http:
paths:
- backend:
serviceName: nginx
servicePort: 80
path: /
待配置生效后,在后端獲取 Http Header 中的 X-Forwarded-For
或 X-Real-IP
字段值得到客戶端真實源 IP,后端抓包測試結(jié)果示例如下:
以上介紹的兩種場景都可以滿足獲取客戶端真實源 IP 的需求,且具有以下優(yōu)點和缺點:
優(yōu)點:在七層(HTTP/HTTPS)流量轉(zhuǎn)發(fā)場景下比較推薦,可通過WEB服務(wù)代理的配置或后端應(yīng)用代碼直接獲取 Http Header 中的字段即可拿到客戶端真實IP,非常簡單高效。
缺點:僅適用于七層(HTTP/HTTPS)流量轉(zhuǎn)發(fā)場景,不適用于四層轉(zhuǎn)發(fā)場景,如果是四層轉(zhuǎn)發(fā)場景,請使用后面介紹的其他方式。
TOA 內(nèi)核模塊原理和加載方式參考 全球應(yīng)用加速 獲取訪問用戶真實 IP - 操作指南 - 文檔中心 - 騰訊云 文檔。
優(yōu)點:對于 TCP 傳輸方式,在內(nèi)核層面且僅對 TCP 連接的首包進(jìn)行改造,幾乎沒有性能損耗。
缺點:
本文主要介紹了在TKE使用場景下服務(wù)端如何獲取客戶端真實源 IP,以滿足用戶相關(guān)使用場景的需求,用戶可通過對比上述四幾種方式的優(yōu)點和缺點,選擇適合實際需求場景的最佳方案。