阿里雲容器服務Ingress設定原IP透傳

了哥-duff發表於2018-07-10

問題

在很多業務場景裡,我們都需要知道客戶端的真實IP來控制業務邏輯。但是從客戶到真正的服務,中間總會進過多層的SLB(負載均衡),那麼如何才能獲取到客戶的真實IP呢?
在Kubernetes容器的環境下,通常一個客戶端訪問到業務要經過雲的SLB,Ingress才能達到業務的應用。所以我們需要每一層都能夠透傳客戶端的IP才行。

原理

在基於HTTP的協議裡,對於客戶端原IP的透傳,可以參考: RFC7239(Forwarded HTTP Extension, https://tools.ietf.org/html/rfc7239) 標準。沒經過一層鏈路,都會把對應地址加入到X-Forwarded-For這個http的擴充套件頭裡,以逗號隔開,最早的客戶端是第一個地址。

例如:

X-Forwarded-For: 192.0.2.43, 2001:db8:cafe::17

根據RFC7239規範,有個需要注意:如果請求中只有X-Forwarded-For,而沒有其它的X-xxxxx的擴充套件頭,則規範是建議將其轉為

Forwarded: for=192.0.2.43, for="[2001:db8:cafe::17]"

阿里雲Kubernetes Ingress實踐

大家或許知道,在阿里雲的Kubernetes容器服務裡,公有云SLB和Ingress是已經自動在安裝的時候配置好的,但是如果需要透傳客戶端的IP,則必須針對ingress controller的service做些改動,具體如下:

kubectl edit service/nginx-ingress-lb -n kube-system

將下圖對應的紅色框的內容從Cluster改為Local
Snip20180709_162.png

原因是參見Kubernetes官網的文件說明:
Snip20180709_161.png

該引數主要是保護客戶端IP,避免loadbalancer/nodeport的服務的第二跳。這樣nodeport的服務路口只會去找本節點的pod服務。如果本節點沒有對應的pod(部署的deployment的例項數少於節點數),則請求將路由不到服務上。為此阿里雲的Cloud Provider專門做了優化,只會把有pod的節點注!冊到阿里雲的SLB上,避免該問題。

這樣,Ingress controller被rolling update後就可以提供原IP給容器的應用了


相關文章