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

什麼是 LB 直通 Pod ?

Kubernetes 官方提供了 NodePort 類型的 Service,即給全部節點開一個相同端口用於暴露這個 Service,大多雲上 LoadBalancer 類型 Service 的傳統實現也都基於 NodePort,即 LB 後端綁各節點的 NodePort,LB 接收外界流量,轉發到其中一個節點的 NodePort 上,再經過 Kubernetes 內部的負載均衡,使用 iptables 或 ipvs 轉發到 Pod:node

TKE 默認的 LoadBalancer 類型 Service 與默認的 Ingress 也都是這樣實現的,但目前也支持了 LB 直通 Pod 的方式,即 LB 後端直接綁 Pod IP+Port,不綁節點的 NodePort:nginx

爲何須要 LB 直通 Pod ?

LB 直接綁 NodePort 來實現雲上的 Ingress 或 LoadBalancer 類型 Service 是最簡單通用的方法,那爲何有了這種實現還不夠,還要搞個 LB 直通 Pod 的模式?後端

首先,咱們分析下傳統 NodePort 實現方式存在的一些問題:api

  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 的場景一般有:session

  1. 在四層獲取客戶端真實源 IP,但又不但願經過使用 externalTrafficPolicy: Local 的方式。
  2. 但願進一步提高網絡性能。
  3. 讓會話保持更容易。
  4. 解決全局鏈接調度的負載不均。

須要什麼前提條件 ?

使用 LB 直通 Pod,須要知足如下前提條件:app

  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,示例:spa

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模式:

  1. 若是經過 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模式:

  1. 若是經過 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: /

參考資料

【騰訊雲原生】雲說新品、雲研新術、雲遊新活、雲賞資訊,掃碼關注同名公衆號,及時獲取更多幹貨!!

相關文章
相關標籤/搜索