思路:先說如何操作——再說原理
1、server 配置中加入externalTrafficPolicy:配置
spec: type: NodePort externalTrafficPolicy: Local 只能在服務啟動pod節點 訪問才有反應,其他節點直接丟棄請求
2、對於問題那就直接將pod指定到某個節點
deploy中加入 spec: nodeName: node1 #指定pod節點配置 containers: - name: pod-name
3、訪問的時候就直接 通過nodeip:serveri-port 進行訪問即可獲取真實ip
下面分析原因:
對於Service, 如果指定類型為 NodePort, 那么這個端口會在集群的所有 Node 上打開,即使這個Node 上面沒有這個pod (很好理解,和守護進程集不一樣,對於Deployment 來說,很少會在每個節點上都啟動pod,所以必定有一些節點上沒有這個pod) 引出一個問題,當某個節點上沒有pod的時候,又去訪問ta的這個NodePort,能訪問到嗎? 流程1 答案是可以的,官方文檔 流程大概是這樣的 client \ ^ \ \ v \ node 1 <--- node 2 | ^ SNAT | | ---> v | endpoint Client sends packet to node2:nodePort 客戶端發送 tcp 包 到 node2:nodePort node2 replaces the source IP address (SNAT) in the packet with its own IP address node2 把客戶端源ip地址替換為node2 的ip地址 node2 replaces the destination IP on the packet with the pod IP node2 把請求的目的地ip替換為 pod ip packet is routed to node 1, and then to the endpoint tcp包被路由到 node1, 接着達到 endpoint(如service) the pod’s reply is routed back to node2 pod的響應被路由到 node2 the pod’s reply is sent back to the client node2把pod的響應發送給客戶端 可以發現,在這個過程中,客戶端的源IP地址丟失了(看第二步) 流程2 為了解決這個問題, k8s 提供了一個功能,通過設置 externalTrafficPolicy=Local 可以保留源IP地址 設置完這個參數之后,流程如下 client ^ / \ / / \ / v X node 1 node 2 ^ | | | | v endpoint client sends packet to node2:nodePort, which doesn’t have any endpoints 客戶端發送tcp包到 node2:nodePort, 但是 node2 並沒有 這個pod packet is dropped tcp包被丟棄 client sends packet to node1:nodePort, which does have endpoints 客戶端發送數據包到 node1:nodePort, node1有pod node1 routes packet to endpoint with the correct source IP node1 把包路由到對應的pod,那么pod 就可以拿到正確的客戶端源IP地址
4、如果有多個pod可以使用lb進行負載,lb有服務的活性檢測,把所有node節點都配置上,讓它進行分發請求。