1. 程式人生 > >手把手教你在容器服務 TKE 上使用 LB 直通 Pod

手把手教你在容器服務 TKE 上使用 LB 直通 Pod

## 什麼是 LB 直通 Pod ? Kubernetes 官方提供了 NodePort 型別的 Service,即給所有節點開一個相同埠用於暴露這個 Service,大多雲上 LoadBalancer 型別 Service 的傳統實現也都基於 NodePort,即 LB 後端綁各節點的 NodePort,LB 接收外界流量,轉發到其中一個節點的 NodePort 上,再通過 Kubernetes 內部的負載均衡,使用 iptables 或 ipvs 轉發到 Pod: ![](https://img2020.cnblogs.com/other/2041406/202009/2041406-20200924202028386-1542288852.png) TKE 預設的 LoadBalancer 型別 Service 與預設的 Ingress 也都是這樣實現的,但目前也支援了 LB 直通 Pod 的方式,即 LB 後端直接綁 Pod IP+Port,不綁節點的 NodePort: ![](https://img2020.cnblogs.com/other/2041406/202009/2041406-20200924202028603-507874526.png) ## 為什麼需要 LB 直通 Pod ? LB 直接綁 NodePort 來實現雲上的 Ingress 或 LoadBalancer 型別 Service 是最簡單通用的方法,那為什麼有了這種實現還不夠,還要搞個 LB 直通 Pod 的模式? 首先,我們分析下傳統 NodePort 實現方式存在的一些問題: 1. 流量從 LB 轉發到 NodePort 之後還需要進行 SNAT,再轉發到 Pod,會帶來一些額外的效能損耗。 2. 如果流量過於集中到某幾個 NodePort 時(比如使用 nodeSelector 部署閘道器到固定幾臺節點上),可能導致源埠耗盡,或者 conntrack 插入衝突。 3. NodePort 本身也充當負載均衡器,LB 繫結過多節點 NodePort 可能導致負載均衡狀態過於分散,導致全域性負載不均。 如果使用 LB 直通 Pod 的方式,以上問題都將消失,並且還有一些其它好處: 1. 由於沒有 SNAT,獲取源 IP 不再需要 `externalTrafficPolicy: Local` 。 2. 實現會話保持更簡單,只需要讓 CLB 開啟會話保持即可,不需要設定 Service 的 `sessionAffinity`。 所以使用 LB 直通 Pod 的場景通常有: 1. 在四層獲取客戶端真實源 IP,但又不希望通過使用 `externalTrafficPolicy: Local` 的方式。 2. 希望進一步提升網路效能。 3. 讓會話保持更容易。 4. 解決全域性連線排程的負載不均。 ## 需要什麼前提條件 ? 使用 LB 直通 Pod,需要滿足以下前提條件: 1. `Kubernetes`叢集版本需要高於 1.12,因為 LB 直綁 Pod,檢查 Pod 是否 Ready,除了看 Pod 是否 Running、是否通過 readinessProbe 外, 還需要看 LB 對 Pod 的健康探測是否通過,這依賴於 `ReadinessGate` 特性,該特性在 Kubernetes 1.12 才開始支援。 2. 叢集網路模式必須開啟`VPC-CNI`彈性網絡卡模式,因為目前 LB 直通 Pod 的實現是基於彈性網絡卡的,普通的網路模式暫時不支援,這個在未來將會支援。 ## 怎麼用 ? 由於目前 LB 直通 Pod 依賴 VPC-CNI,需要保證 Pod 使用了彈性網絡卡: 1. 如果叢集建立時選擇的是 VPC-CNI 網路外掛,那麼建立的 Pod 預設就使用了彈性網絡卡。 2. 如果叢集建立時選擇的是 Global Router 網路外掛,後來開啟了 VPC-CNI 支援,即兩種模式混用,建立的 Pod 預設不使用彈性網絡卡,需要使用 yaml 建立工作負載,為 Pod 指定 `tke.cloud.tencent.com/networks: tke-route-eni` 這個 annotation 來宣告使用彈性網絡卡,並且為其中一個容器加上 `tke.cloud.tencent.com/eni-ip: "1"` 這樣的 requests 與 limits,示例: ``` apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx-deployment-eni spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: annotations: tke.cloud.tencent.com/networks: tke-route-eni labels: app: nginx spec: containers: - image: nginx name: nginx resources: requests: tke.cloud.tencent.com/eni-ip: "1" limits: tke.cloud.tencent.com/eni-ip: "1" ``` 當你用 LoadBalancer 的 Service 暴露服務時,需要宣告使用直連模式: 1. 如果通過控制檯建立 Service,可以勾選 `採用負載均衡直連Pod模式`: ![](https://img2020.cnblogs.com/other/2041406/202009/2041406-20200924202028936-1381444715.png) 2. 如果通過 yaml 建立 Service,需要為 Service 加上 `service.cloud.tencent.com/direct-access: "true"` 的 annotation: ``` apiVersion: v1 kind: Service metadata: annotations: service.cloud.tencent.com/direct-access: "true" labels: app: nginx name: nginx-service-eni spec: externalTrafficPolicy: Cluster ports: - name: 80-80-no port: 80 protocol: TCP targetPort: 80 selector: app: nginx sessionAffinity: None type: LoadBalancer ``` 當使用 Ingress 暴露服務時,同樣也需要宣告使用直連模式: 1. 如果通過控制檯建立 Ingress,可以勾選 `採用負載均衡直連Pod模式`: ![](https://img2020.cnblogs.com/other/2041406/202009/2041406-20200924202029186-1108692092.png) 2. 如果通過 yaml 建立 Ingress,需要為 Ingress 加上 `ingress.cloud.tencent.com/direct-access: "true"` 的 annotation: ``` apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: annotations: ingress.cloud.tencent.com/direct-access: "true" kubernetes.io/ingress.class: qcloud name: test-ingress namespace: default spec: rules: - http: paths: - backend: serviceName: nginx servicePort: 80 path: / ``` ## 參考資料 - TKE 基於彈性網絡卡直連 Pod 的網路負載均衡: https://mp.weixin.qq.com/s/fJtlm5Qjm2BfzekC4RegCQ - 叢集開啟 VPC-CNI 模式網路: https://cloud.tencent.com/document/product/457/34993 - VPC-CNI 網路模式使用指引: https://cloud.tencent.com/document/product/457/48040 >【騰訊雲原生】雲說新品、雲研新術、雲遊新活、雲賞資訊,掃碼關注同名公眾號,及時獲取更多幹貨!! ![](https://img2020.cnblogs.com/other/2041406/202009/2041406-20200924202029659-889088