使用容器原生負載平衡

本頁面說明如何在 Google Kubernetes Engine 中使用容器原生負載平衡。

總覽

「容器原生負載平衡」可讓 HTTP(S) 負載平衡器直接定位 Pod,並將其流量平均分配至 Pod。

容器原生負載平衡運用的資料模型稱為網路端點群組 (NEG),NEG 是網路端點的集合,由 IP 和通訊埠組合表示。

優勢

容器原生負載平衡具備下列優勢:

Pod 是負載平衡的一等公民
kube-proxy 會設定節點的 iptables 規則,將流量分配到多個 Pod。要是沒有容器原生負載平衡,負載平衡器流量會前往節點執行個體群組,並且透過 iptables 規則轉送到多個 Pod,而這些 Pod 不一定位於同一節點內。要是擁有容器原生負載平衡,負載平衡器流量會直接分配到多個 Pod,而這些 Pod 應接收流量,並且消除額外的網路躍點。此外,容器原生負載平衡直接以 Pod 為目標,因此健康狀態檢查可獲得改善。

此圖比較預設行為 (左) 和容器原生負載平衡器行為。
網路效能獲得改善
因為容器原生負載平衡器可直接與 Pod 交流,而且連線的網路躍點較少,所以延遲時間和總處理量都獲得改善。
瀏覽權限提升
使用容器原生負載平衡時,您有權限可瀏覽用戶端到 HTTP 負載平衡器的來回時間 (RTT),包括 Stackdriver UI 支援。如此一來,NEG 層級服務的疑難排解就會變得更加容易。
HTTP(S) 負載平衡器功能的支援
容器原生負載平衡提供 Google Kubernetes Engine 的原生支援,其中包含數種 HTTP 負載平衡功能,例如與 GCP 服務 (如 Google Cloud ArmorCloud CDNCloud Identity-Aware Proxy) 整合的功能。此外,還具備負載平衡演算法,可精確分配流量。
支援 Traffic Director
需有 NEG 資料模型,才能使用 Traffic Director,這是 GCP 的完全託管的服務網格流量控制層。

Pod 完備性

對於相關的 Pod,相應的 Ingress 控制器會管理 cloud.google.com/load-balancer-neg-ready 類型的完備性門檻。Ingress 控制器會輪詢負載平衡器健康狀態檢查的狀態,NEG 中所有端點的健康狀態都包括在內。當負載平衡器健康狀態檢查的狀態,顯示出與特定 Pod 對應的端點處於健康狀態時,Ingress 控制器會將 Pod 的完備性門檻值設為 True。然後,在每個 Node 上運行的 kubelet 會將完備性門檻的值以及 Pod 的完備性探測 (如有定義) 一併納入考量,計算 Pod 的有效完備性。

對於容器原生的負載平衡,以下版本會自動啟用 Pod 完備性門檻:

  • 執行 v1.13.8 以上版本的 v1.13 GKE 叢集
  • 執行 v1.14.4 以上版本的 v1.14 GKE 叢集

完備性門檻會控制滾動式更新的速率。以上列出的 GKE 版本會自動將完備性門檻新增至 Pod。當您啟動滾動式更新時,隨著 GKE 建立新的 Pod,會將每個新 Pod 的端點新增至 NEG。從負載平衡器的角度來看,當端點處於健康狀態時,Ingress 控制器會將完備性門檻設為 True。因此,新建立的 Pod 必須至少通過其完備性門檻,「接下來」GKE 才能刪除舊的 Pod。這樣可確保 Pod 的對應端點已通過負載平衡器的健康狀態檢查,並確保後端容量維持不變。

如果 Pod 的完備性門檻並未顯示 Pod 已準備就緒,可能是因為容器映像檔錯誤,或是負載平衡器健康狀態檢查設定錯誤,導致負載平衡器未將流量導向新 Pod。如果在推出更新後的 Deployment 時發生故障,在嘗試建立新的 Pod 後,因為該 Pod 的完備性門檻永遠不會為 True,所以會暫停推出。如要瞭解如何偵測並修正這種狀況,請參閱疑難排解一節

在缺少容器原生負載平衡和完備性門檻的情況下,GKE 在將 Pod 標記為準備就緒之前,無法偵測到負載平衡器的端點是否處於健康狀態。在先前的 Kubernetes 版本中,您可以指定延遲期間 (Deployment 規格中的 minReadySeconds) 來控制 Pod 移除和替換的速率。

需求

Google Kubernetes Engine 上的容器原生負載平衡器必須滿足下列需求:

Google Kubernetes Engine v1.13.8 或 v1.14.4

容器原生負載平衡器通常可用於:

  • 執行 v1.13.8 以上版本的 v1.13 GKE 叢集
  • 執行 v1.14.4 以上版本的 v1.14 GKE 叢集
虛擬私人雲端原生

如要使用容器原生負載平衡,叢集必須是虛擬私人雲端原生。詳情請參閱使用別名 IP 建立虛擬私人雲端原生叢集

HTTP 負載平衡

如要使用容器原生負載平衡,您的叢集必須啟用 HTTP 負載平衡。根據預設,GKE 叢集已啟用 HTTP 負載平衡,不得停用該功能。

限制

容器原生負載平衡器無法搭配舊版網路使用。

限制

容器原生負載平衡器不支援內部負載平衡器和網路負載平衡器。

定價

您在本指南中建立的 Ingress 所佈建的 HTTP(S) 負載平衡器,系統會向您收取費用。負載平衡器定價資訊,請參閱 Compute Engine 定價頁面的負載平衡和轉送規則

使用容器原生負載平衡

下列各節會逐步引導您在 Google Kubernetes Engine 上設定容器原生負載平衡。

建立虛擬私人雲端原生叢集

如要使用容器原生負載平衡,使用別名 IP 建立叢集就必須啟用。

例如,下列指令建立一個名為 neg-demo-cluster 的叢集,而 us-central1-a 區域含有一個自動佈建子網路:

gcloud container clusters create neg-demo-cluster \
    --enable-ip-alias \
    --create-subnetwork="" \
    --network=default \
    --zone=us-central1-a

建立 Deployment

接著,將工作負載部署到叢集。

下列的 Deploymentneg-demo-app 會執行容器化 HTTP 伺服器的單一執行個體。建議使用會使用 Pod 完備性反饋的工作負載。如需更多資訊和 GKE 版本需求,請參閱前面的 Pod 完備性一節

使用 Pod 完備性反饋

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: neg-demo-app # Label for the Deployment
  name: neg-demo-app # Name of Deployment
spec:
  selector:
    matchLabels:
      run: neg-demo-app
  template: # Pod template
    metadata:
      labels:
        run: neg-demo-app # Labels Pods from this Deployment
    spec: # Pod specification; each Pod created by this Deployment has this specification
      containers:
      - image: k8s.gcr.io/serve_hostname:v1.4 # Application to run in Deployment's Pods
        name: hostname # Container name
  

使用硬式編碼延遲

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: neg-demo-app # Label for the Deployment
  name: neg-demo-app # Name of Deployment
spec:
  minReadySeconds: 60 # Number of seconds to wait after a Pod is created and its status is Ready
  selector:
    matchLabels:
      run: neg-demo-app
  template: # Pod template
    metadata:
      labels:
        run: neg-demo-app # Labels Pods from this Deployment
    spec: # Pod specification; each Pod created by this Deployment has this specification
      containers:
      - image: k8s.gcr.io/serve_hostname:v1.4 # Application to run in Deployment's Pods
        name: hostname # Container name
      # Note: The following line is necessary only on clusters running GKE v1.11 and lower.
      # For details, see https://cloud.google.com/kubernetes-engine/docs/how-to/container-native-load-balancing#align_rollouts
      terminationGracePeriodSeconds: 60 # Number of seconds to wait for connections to terminate before shutting down Pods
  

在此 Deployment 中,各容器都會執行一個 HTTP 伺服器。HTTP 伺服器會傳回應用程式伺服器的主機名稱 (亦即伺服器執行所在的 Pod 名稱) 做為回應。

將此份資訊清單儲存為 neg-demo-app.yaml,然後執行下列指令來建立 Deployment:

kubectl apply -f neg-demo-app.yaml

為容器原生負載平衡器建立 Service

建立 Deployment 後,必須將部署的多個 Pod 組成一個 Service

下列的 Service 範例 neg-demo-svc 會以前一節建立的 Deployment 範例為目標:

apiVersion: v1
kind: Service
metadata:
  name: neg-demo-svc # Name of Service
  annotations:
    cloud.google.com/neg: '{"ingress": true}' # Creates an NEG after an Ingress is created
spec: # Service's specification
  type: NodePort
  selector:
    run: neg-demo-app # Selects Pods labelled run: neg-demo-app
  ports:
  - port: 80 # Service's port
    protocol: TCP
    targetPort: 9376

Service 的註解 cloud.google.com/neg: '{"ingress": true}' 會啟用容器原生負載平衡。然而,要等到您為 Service 建立 Ingress 後,才會建立負載平衡器。

將此份資訊清單儲存為 neg-demo-svc.yaml,然後執行下列指令來建立 Service:

kubectl apply -f neg-demo-svc.yaml

為 Service 建立 Ingress

下列的 Ingress 範例 neg-demo-ing 會以您建立的 Service 為目標:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: neg-demo-ing
spec:
  backend:
    serviceName: neg-demo-svc # Name of the Service targeted by the Ingress
    servicePort: 80 # Should match the port used by the Service

將此份資訊清單儲存為 neg-demo-ing.yaml,然後執行下列指令來建立 Ingress:

kubectl apply -f neg-demo-ing.yaml

建立 Ingress 後,HTTP 負載平衡器隨即會在專案裡建立,NEG 會在叢集執行所在的每個區域裡建立。NEG 裡的端點和 Service 端點會保持同步。

驗證 Ingress

在部署工作負載、將工作負載的多個 Pod 組成一個 Service,並為 Service 建立 Ingress 之後,應該要確認 Ingress 已成功佈建容器原生負載平衡器。

如要擷取 Ingress 的狀態,請執行下列指令:

kubectl describe ingress neg-demo-ing

在指令輸出中,找出 ADDCREATE 事件:

Events:
Type     Reason   Age                From                     Message
----     ------   ----               ----                     -------
Normal   ADD      16m                loadbalancer-controller  default/neg-demo-ing
Normal   Service  4s                 loadbalancer-controller  default backend set to neg-demo-svc:32524
Normal   CREATE   2s                 loadbalancer-controller  ip: 192.0.2.0

測試負載平衡器功能

下列各節說明如何測試容器原生負載平衡器的功能。

造訪 Ingress IP 位址

請等候數分鐘,以等待 HTTP 負載平衡器完成設定。

您可以造訪 Ingress 的 IP 位址,確認容器原生負載平衡器功能運作正常。

如要取得 Ingress IP 位址,請執行下列指令:

kubectl get ingress neg-demo-ing

在指令列輸出中,Ingress 的 IP 位址會顯示於 ADDRESS 欄。使用網路瀏覽器造訪 IP 位址。

檢查後端服務健康狀態

您也可以取得負載平衡器後端服務的健康狀態。

首先,取得專案裡執行的後端服務清單:

gcloud compute backend-services list

複製含 Service 名稱的後端名稱,例如 neg-demo-svc。然後,取得後端服務的健康狀態:

gcloud compute backend-services get-health [BACKEND_SERVICE_NAME] --global

驗證 Ingress 功能

要如預期般測試負載平衡器功能,還有另外一種方法:調度 Deployment 範例的資源,將測試要求傳送到 Ingress,然後驗證回應的備用資源數量正確無誤。

下列指令會將一個執行個體的 neg-demo-app Deployment 資源擴充到兩個執行個體:

kubectl scale deployment neg-demo-app --replicas 2

請稍候幾分鐘,才會完成發布。如要確認發布已完成,請執行下列指令:

kubectl get deployment neg-demo-app

在指令輸出中,確認有兩個可用的備用資源:

NAME           DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
neg-demo-app   2         2         2            2           26m

然後,執行下列指令來計算負載平衡器傳出的不重複回應之數量:

for i in `seq 1 100`; do \
  curl --connect-timeout 1 -s [IP_ADDRESS] && echo; \
done  | sort | uniq -c

其中 [IP_ADDRESS] 是 Ingress 的 IP 位址。您可以從 kubectl describe ingress neg-demo-ing 取得 Ingress 的 IP 位址。

在指令輸出中,發現不重複回應的數量等於備用資源數量,這就表示所有後端 Pod 都在處理流量:

44 neg-demo-app-7f7dfd7bc6-dcn95
56 neg-demo-app-7f7dfd7bc6-jrmzf

清除所用資源

完成本頁面的工作之後,為避免您的帳戶中產生不必要的費用,請按照下列步驟移除資源:

刪除叢集

gcloud

gcloud container clusters delete neg-demo-cluster

主控台

  1. 造訪 GCP Console 的 Google Kubernetes Engine 選單。

    造訪 Google Kubernetes Engine 選單

  2. 選取 [neg-demo-cluster]

  3. 按一下 [Delete] (刪除)

疑難排解

請使用以下技巧確認您的網路設定。下列各節說明如何解決關於容器原生負載平衡的特定問題。

  • 如要進一步瞭解如何列出網路端點群組,請參閱負載平衡器說明文件

  • 您可以在服務的 neg-status 註解中,找到與該服務相對應的 NEG 名稱和區域。取得 Service 規格:

    kubectl get svc svc-name -o yaml

    metadata:annotations:cloud.google.com/neg-status 註解會列出服務對應的 NEG 名稱和 NEG 區域。

  • 您可以透過下列指令,檢查與 NEG 相對應的後端服務狀態:

    gcloud compute backend-service [--project PROJECT_NAME] \
      get-health BACKEND_SERVICE_NAME --global
    

    請注意,後端服務的名稱與其 NEG 相同。

  • 如何列印服務事件記錄:

    kubectl describe svc [SERVICE_NAME]
    

    服務的名稱字串包含對應 GKE 服務的名稱和命名空間。

無法使用別名 IP 建立叢集

問題
嘗試使用別名 IP 建立叢集時,可能會碰到下列錯誤:
ResponseError: code=400, message=IP aliases cannot be used with a legacy network.
可能原因
嘗試透過使用舊版網路的別名 IP 來建立叢集時,可能會發生上列錯誤。
解決方法
請勿在啟用舊版網路的情況下使用別名 IP 建立叢集。別名 IP 使用詳情請參閱使用別名 IP 建立虛擬私人雲端原生叢集

流量未達端點

問題
502 錯誤或連線遭拒。
可能原因

新端點只要會回應健康狀態檢查,則在附加到負載平衡器後通常就可存取。如果流量達不到端點,就可能會發生 502 錯誤或連線遭拒。

如果容器無法處理 SIGTERM,也可能會造成 502 錯誤和連線遭拒。如果容器未明確處理 SIGTERM,則會立即終止並停止處理要求。負載平衡器會持續將傳入的流量傳送至已終止的容器,導致發生錯誤。

解決方法

將置容器設為處理 SIGTERM,並在整個終止寬限期內 (預設為 30 秒) 繼續回應要求。將 Pod 設為在收到 SIGTERM 時,開始讓健康狀態檢查失敗。如此會向負載平衡器發出信號,要求在端點正在取消程式設計時,停止向 Pod 傳送流量。

如需更多資訊,請參閱 Pod 終止說明文件以及關於 Pod 終止最佳做法的文章

如要對流量未抵達端點的問題進行疑難排解,請確認防火牆規則允許傳入 TCP 流量到 130.211.0.0/2235.191.0.0/16 範圍內的端點。詳情請參閱 Cloud Load Balancing 說明文件中的新增健康狀態檢查

查看專案裡的後端服務。相關後端服務的名稱字串,包含了對應的 Google Kubernetes Engine Service 名稱:

gcloud compute backend-services list

向後端服務擷取後端健康狀態:

gcloud compute backend-services get-health [BACKEND_SERVICE_NAME]

如果所有後端健康狀態不良,就表示防火牆、Ingress 或 Service 可能設定有誤。

如果有些後端健康狀態短時間不良,就表示網路程式設計延遲時間可能是原因所在。

如果有些後端沒有出現在後端服務清單,就表示程式設計延遲時間可能是原因所在。要確認這點,請執行下列指令,當中的 [NEG] 是後端服務名稱。(NEG 和後端服務共用同一個名稱):

gcloud compute network-endpoint-groups list-network-endpoints [NEG]

確認所有預期的端點是否都已在 NEG 中。

停止發布

問題
更新的 Deployment 延遲推出,且最新備用資源的數量與與所需備用資源的數量不符。
可能原因

Deployment 的健康狀態檢查失敗。容器映像檔可能不正確,或是健康狀態檢查可能設定錯誤。Pod 的滾動式替換作業會等候新啟動的 Pod 傳送其 Pod 完備性門檻。只有當 Pod 在回應負載平衡器健康狀態檢查時,才會發生這種情況。如果 Pod 沒有回應,或是健康狀態檢查設定有誤,就無法達到完備性門檻,導致無法繼續發布。

如果您使用的是 kubectl 1.13 或以上版本,則可以使用以下指令檢查 Pod 完備性門檻的狀態:

kubectl get my-Pod -o wide

檢查 READINESS GATES 欄。

kubectl 1.12 以下版本沒有這個資料欄。標記為處於 READY 狀態的 Pod,可能會有完備性門檻失敗的問題。如要驗證這一點,請使用以下指令:

kubectl get my-pod -o yaml

系統會在輸出結果中列出完備性門檻和其狀態。

解決方法

確認 Deployment 的 Pod 規格中的容器映像檔運作正常,且能回應健康狀態檢查。請確認健康狀態檢查設定正確無誤。

已知問題

Google Kubernetes Engine 上的容器原生負載平衡具有下列已知問題:

垃圾收集未完成

Google Kubernetes Engine 每兩分鐘就會對容器原生負載平衡器進行垃圾收集。如果叢集在負載平衡器完全移除前就遭到刪除,就必須手動刪除負載平衡器的 NEG。

請執行下列指令來查看專案裡的 NEG:

gcloud compute network-endpoint-groups list

在指令輸出中,找出相關的 NEG。

如要刪除 NEG,請執行下列指令,其中的 [NEG] 是 NEG 的名稱:

gcloud compute network-endpoint-groups delete [NEG]

工作負載的發布以及端點的傳播應保持一致

將工作負載部署到叢集時,或更新現有工作負載時,容器原生負載平衡器傳播新端點的所需時間可能會超過工作負載發布完成的所需時間。您在本指南中部署的 Deployment 範例為了讓發布與端點的傳播保持一致,會使用下列兩個欄位:terminationGracePeriodSecondsminReadySeconds

terminationGracePeriodSeconds 允許 Pod 安全關閉,方法是等待連線在 Pod 預定刪除後終止。

minReadySeconds 會在 Pod 建立後新增延遲期間。您要指定下列狀態的最短秒數:在新 Pod 中沒有任何容器當機 (即系統認定 Pod 可用) 的情況下,新 Pod 處於 Ready 狀態的最短秒數。

您應將工作負載的 minReadySeconds 值和 terminationGracePeriodSeconds 值設成 60 秒以上,這樣就能確保服務不會因工作負載的發布而中斷。

terminationGracePeriodSeconds 在所有 Pod 規格中都可用;minReadySeconds 適用於 Deployment 和 DaemonSet。

如要進一步瞭解如何微調發布,請參閱 RollingUpdateStrategy

後續步驟

本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Kubernetes Engine 說明文件