環境
- kubernetes 1.20.6
- Spring Boot 2.5.0-M3
目標
Service 的 externalTrafficPolicy 表示外部流量策略,主要的作用是設置是否保留源 IP。
如果是 NodePort 類型的 Service 默認不會保留源 IP,可以通過 externalTrafficPolicy 來設置。
示例
以下的流程基於前一篇的流程繼續進行。
創建 NodePort
kubectl expose deployment source-ip-app --name=nodeport --port=80 --target-port=8080 --type=NodePort
[root@master ~]# kubectl expose deployment source-ip-app --name=nodeport --port=80 --target-port=8080 --type=NodePort
service/nodeport exposed
獲取訪問地址
NODEPORT=$(kubectl get -o jsonpath="{.spec.ports[0].nodePort}" services nodeport)
[root@master ~]# NODEPORT=$(kubectl get -o jsonpath="{.spec.ports[0].nodePort}" services nodeport)
[root@master ~]# echo $NODEPORT
31435
NODES=$(kubectl get nodes -o jsonpath='{ $.items[*].status.addresses[?(@.type=="InternalIP")].address }')
[root@master ~]# NODES=$(kubectl get nodes -o jsonpath='{ $.items[*].status.addresses[?(@.type=="InternalIP")].address }')
[root@master ~]# echo $NODES
192.168.56.101 192.168.56.102 192.168.56.103
第一次訪問測試
for node in $NODES; do curl -s $node:$NODEPORT | grep -i client_address; done
[root@master ~]# for node in $NODES; do curl -s $node:$NODEPORT | grep -i client_address; done
client_address=::ffff:10.244.0.0
client_address=::ffff:10.244.1.0
client_address=::ffff:10.244.2.1
可以這些並不是真正的客戶端 IP 地址,而是集群 IP 地址。
修改 Service
kubectl patch svc nodeport -p '{"spec":{"externalTrafficPolicy":"Local"}}'
[root@master ~]# kubectl patch svc nodeport -p '{"spec":{"externalTrafficPolicy":"Local"}}'
service/nodeport patched
修改后訪問
for node in $NODES; do curl --connect-timeout 1 -s $node:$NODEPORT | grep -i client_address; done
[root@master ~]# for node in $NODES; do curl --connect-timeout 1 -s $node:$NODEPORT | grep -i client_address; done
client_address=::ffff:192.168.56.101
可以看到已經獲取正確的客戶端 IP 了,但是訪問的三個 Node,只有一個 Node 有返回。
總結
設置 service.spec.externalTrafficPolicy 的值為 Local,請求就只會被代理到本地 endpoints 而不會被轉發到其它節點。這樣就保留了最初的源 IP 地址。如果沒有本地 endpoints,發送到這個節點的數據包將會被丟棄。