透過獨立的區域 NEG 使用容器原生負載平衡

本頁說明如何建立 Kubernetes 服務,並在 Google Kubernetes Engine (GKE) VPC 原生叢集中,以區域GCE_VM_IP_PORT網路端點群組 (NEG) 做為後端。

如要瞭解容器原生負載平衡的優點、需求和限制,請參閱「容器原生負載平衡」。

總覽

NEG 代表一組端點。GKE 支援 GCE_VM_IP_PORT 類型的獨立 NEG。GCE_VM_IP_PORT NEG 支援使用 VM 主要內部 IP 位址或其中一個別名 IP 範圍的 IP 位址的端點。

在 GKE VPC 原生叢集使用獨立 NEG 的情況下,每個端點都是 Pod IP 位址和目標通訊埠。Pod IP 位址來自節點的 Pod 別名 IP 範圍,而該範圍來自叢集的 Pod 子網路次要 IP 位址範圍。

GKE 提供 NEG 控制器,可管理GCE_VM_IP_PORT NEG 的成員資格。您可以將建立的 NEG 新增為後端,用於在 GKE API 外部設定的負載平衡器後端服務。

下圖說明 Kubernetes API 物件如何對應至 Compute Engine 物件。

Kubernetes 服務對應於 Compute Engine 網路端點群組,而 Kubernetes Pod 則對應於 Compute Engine 網路端點。控制層的 NEG 控制器元件會管理這項作業。

使用 NEG 的 Ingress

將 NEG 與 GKE Ingress 搭配使用時,Ingress 控制器會協助建立負載平衡器的所有層面。包括建立虛擬 IP 位址、轉送規則、健康狀態檢查、防火牆規則等。

建議使用 Ingress,因為它具備許多功能,可簡化 NEG 管理作業,是使用容器原生負載平衡的最佳方式。如果 Ingress 管理的 NEG 無法滿足您的用途,可以選擇使用獨立 NEG。

獨立的 NEG

如果 NEG 是透過 Ingress 以外的任何方式佈建負載平衡器,則視為獨立 NEG。獨立 NEG 是透過 NEG 控制器部署及管理,但轉送規則、健康狀態檢查和其他負載平衡物件則為手動部署。

獨立 NEG 不會與啟用 Ingress 的容器原生負載平衡功能衝突。

下圖說明在各情境中,負載平衡物件的部署方式有何差異:

使用獨立 NEG 和 Ingress 管理的 NEG 時,GKE 控制層上的 NEG 控制器會管理 NEG 和網路端點物件。如果是獨立 NEG,使用者會管理其他所有元件,如前幾段所述。

根據預設,GKE NEG 控制器只會在叢集有節點的區域中,建立獨立的 NEG。如要簡化負載平衡器設定,您也可以在建立 Service 後,立即在特定可用區 (或區域內的所有可用區) 預先佈建空白 NEG,不必等待工作負載部署。預先佈建 NEG 的支援功能目前處於預覽階段。

防止 NEG 外洩

使用獨立 NEG 時,您必須負責管理 NEG 的生命週期,以及構成負載平衡器的資源。您可能會透過下列方式洩漏 NEG:

  • 如果後端服務仍參照相關聯的 NEG,刪除 GKE 服務時,系統不會進行垃圾收集。從後端服務取消參照 NEG,以便刪除 NEG。
  • 刪除叢集時,在下列情況下,系統不會刪除獨立的 NEG:

    • 後端服務仍參照 NEG。
    • 叢集刪除程序會在控制器刪除 NEG 之前,先關閉 NEG 控制器。

    為避免 NEG 外洩,請先從後端服務取消參照 NEG,然後刪除所有 NEG,再刪除叢集。

如果叢集或服務刪除後仍有 NEG 洩漏,您可以使用 Google Cloud CLI 刪除 NEG。

獨立 NEG 的用途

獨立 NEG 有多種重要用途。獨立 NEG 非常靈活。 這與 Ingress (搭配或不搭配 NEG 使用) 不同,後者定義了一組特定的負載平衡物件,這些物件經過審慎選擇,方便使用者直接使用。

獨立 NEG 的用途包括:

容器和 VM 的異質服務

NEG 可同時包含 VM 和容器 IP 位址。也就是說,單一虛擬 IP 位址可指向由 Kubernetes 和非 Kubernetes 工作負載組成的後端。這項功能也可用於將現有工作負載遷移至 GKE 叢集。

獨立 NEG 可以指向 VM IP,因此您可以手動設定負載平衡器,指向由 VM 和容器組成的後端,以提供相同的服務 VIP。

自訂 Ingress 控制器

您可以透過自訂 Ingress 控制器 (或不使用 Ingress 控制器),設定以獨立 NEG 為目標的負載平衡器。

搭配 GKE 使用 Cloud Service Mesh

您可以搭配 GKE 使用 Cloud Service Mesh。Cloud Service Mesh 使用獨立 NEG,為代管服務網格提供容器原生負載平衡。

搭配 GKE 使用外部 Proxy 網路負載平衡器

您可以透過外部 Proxy 網路負載平衡器,使用獨立 NEG 直接對容器進行負載平衡,Kubernetes/GKE 原生不支援這項功能。

Pod 完備性

就緒閘是 Kubernetes 的擴充性功能,可將額外的意見回饋或信號注入 PodStatus,讓 Pod 轉換為就緒狀態。NEG 控制器會管理自訂 readiness 閘道,確保從 Compute Engine 負載平衡器到 Pod 的完整網路路徑正常運作。如要瞭解 GKE 中的 Pod 完備性門檻,請參閱容器原生負載平衡。

具備 NEG 的 Ingress 會代表負載平衡器部署及管理 Compute Engine 健康狀態檢查。不過,獨立 NEG 不會對 Compute Engine 健康狀態檢查做出任何假設,因為這類檢查應會分開部署及管理。請務必一併設定 Compute Engine 健康狀態檢查和負載平衡器,以免流量傳送至尚未準備好接收流量的後端。如果沒有與 NEG 相關聯的健康狀態檢查狀態 (通常是因為未設定健康狀態檢查),則 NEG 控制器會在 NEG 中設定對應的端點時,將 Pod 的 readiness 閘道值標示為 True。

事前準備

開始之前,請務必先完成下列工作:

  • 啟用 Google Kubernetes Engine API。
  • 啟用 Google Kubernetes Engine API
  • 如要使用 Google Cloud CLI 執行這項工作,請安裝並初始化 gcloud CLI。如果您先前已安裝 gcloud CLI,請執行 gcloud components update 指令,取得最新版本。較舊的 gcloud CLI 版本可能不支援執行本文件中的指令。
  • 確認您已有 VPC 原生叢集。叢集必須啟用 HttpLoadBalancing 外掛程式。新的 GKE 叢集預設會啟用 HttpLoadBalancing 外掛程式。

    如要建立新的 Standard 叢集,請參閱「建立 VPC 原生叢集」。Autopilot 叢集預設為 VPC 原生叢集。

使用獨立式廣告 NEG

下列操作說明說明如何在 GKE 上,搭配使用獨立 NEG 與外部 HTTP 負載平衡器。

您必須建立下列物件:

  • 建立及管理 Pod 的部署項目。
  • 建立 NEG 的 Service。
  • 使用 Compute Engine API 建立的負載平衡器。這與搭配 Ingress 使用 NEG 不同,在後者中,Ingress 會為您建立及設定負載平衡器。使用獨立 NEG 時,您必須負責將 NEG 和後端服務建立關聯,才能將 Pod 連線至負載平衡器。負載平衡器由多個元件組成,如下圖所示:

負載平衡器的元件包括轉送規則、目標 HTTP Proxy、網址對應、健康狀態檢查和後端服務。這會將流量導向包含 Pod IP 位址的 NEG。

建立 Deployment

以下範例資訊清單會指定 Deployment,執行容器化 HTTP 伺服器的三個執行個體。HTTP 伺服器會回應要求,並提供應用程式伺服器的主機名稱,以及伺服器執行的 Pod 名稱。

建議您使用會採用 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:
  replicas: 3
  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: registry.k8s.io/e2e-test-images/agnhost:2.40 # Application to run in Deployment's Pods
        name: hostname
        args:
        - serve-hostname
        - --port=9376
  

使用硬式編碼延遲

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
  replicas: 3
  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: registry.k8s.io/e2e-test-images/agnhost:2.40 # Application to run in Deployment's Pods
        name: hostname
        args:
        - serve-hostname
        - --port=9376
  

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

kubectl apply -f neg-demo-app.yaml

建立 Service

下列資訊清單指定了 Service,其中:

  • 任何具有 run: neg-demo-app 標籤的 Pod 都是這項服務的成員。
  • 服務有一個ServicePort 欄位,通訊埠為 80。
  • cloud.google.com/neg 註解會指定通訊埠 80 將與 NEG 建立關聯。選用的 name 欄位會指定 NEG 的名稱為 NEG_NAME。如果省略 name 欄位,系統會自動產生專屬名稱。詳情請參閱「命名 NEG」。
  • 每個成員 Pod 都必須有一個監聽 TCP 通訊埠 9376 的容器。
apiVersion: v1
kind: Service
metadata:
  name: neg-demo-svc
  annotations:
    cloud.google.com/neg: '{"exposed_ports": {"80":{"name": "NEG_NAME"}}}'
spec:
  type: ClusterIP
  selector:
    run: neg-demo-app # Selects Pods labelled run: neg-demo-app
  ports:
  - port: 80
    protocol: TCP
    targetPort: 9376

將 NEG_NAME 替換為 NEG 名稱。NEG 名稱在所屬區域中不得重複。

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

kubectl apply -f neg-demo-svc.yaml

建立 Service 後,系統會在幾分鐘內建立 NEG。

服務類型

雖然這個範例使用 ClusterIP 服務,但所有五種服務類型都支援獨立 NEG。建議使用預設類型 ClusterIP。

為 NEG 命名

在 GKE 1.18.18-gke.1200 以上版本中,您可以指定 NEG 的自訂名稱,也可以讓 GKE 自動產生名稱。舊版 GKE 僅支援自動產生的 NEG 名稱。

GKE 會在叢集使用的每個可用區中建立一個 NEG。所有 NEG 都使用相同的名稱。

指定名稱

指定自訂 NEG 名稱可簡化負載平衡器的設定,因為您事先知道 NEG 的名稱和區域。自訂 NEG 名稱必須符合下列規定:

  • 如果是可用區叢集,名稱在叢集可用區中不得重複;如果是區域叢集,名稱在區域中不得重複。

  • 不得與任何現有 NEG 的名稱相符,且該 NEG 並非由 GKE NEG 控制器建立。

  • 不得包含底線。

在 Service 的 cloud.google.com/neg 註解中使用 name 欄位,指定 NEG 名稱:

cloud.google.com/neg: '{"exposed_ports": {"80":{"name": "NEG_NAME"}}}'

將 NEG_NAME 替換為 NEG 名稱。NEG 名稱在所屬區域中不得重複。

使用自動產生的名稱

系統自動產生的 NEG 名稱保證不會重複。如要使用自動產生的名稱,請省略 name 欄位:

cloud.google.com/neg: '{"exposed_ports": {"80":{}}}'

自動產生的名稱格式如下:

k8s1-CLUSTER_UID-NAMESPACE-SERVICE-PORT-RANDOM_HASH

將通訊埠對應至多個 NEG

服務可以監聽多個連接埠。根據定義,NEG 只有單一 IP 位址和通訊埠。也就是說,如果您指定具有多個通訊埠的服務,系統會為每個通訊埠建立 NEG。

cloud.google.com/neg 註解的格式為:

cloud.google.com/neg: '{
   "exposed_ports":{
      "SERVICE_PORT_1":{},
      "SERVICE_PORT_2":{},
      "SERVICE_PORT_3":{},
      ...
   }
 }'

在本例中,每個 SERVICE_PORT_N 都是不同的通訊埠編號,代表服務的現有服務通訊埠。針對列出的每個服務通訊埠,NEG 控制器會在叢集占用的每個可用區中建立一個 NEG。

預先佈建空白 NEG

根據預設,GKE NEG 控制器只會在叢集有節點的可用區中,建立獨立的 NEG。如果叢集擴大並在新的區域中新增節點,控制器會自動建立對應的 NEG。如要在設定 Kubernetes 服務後,立即將空白 NEG 附加至後端服務,不必等待節點擴充至這些區域,請預先佈建空白 NEG (預先發布版)。預先佈建 NEG 可簡化負載平衡器設定,因為工作負載最終擴充至這些新區域時,系統會自動開始進行流量路徑設定。

如要啟用預先佈建功能,請使用選用的 zones 欄位,擴充 Kubernetes 服務的 cloud.google.com/neg 註解,例如:

cloud.google.com/neg: '{"exposed_ports": {"80":{}}, "zones":["us-central1-a", "us-central1-b"]}'

如果您在 exposed_ports 下指定多個連接埠,設定的可用區設定會套用至為所有這些連接埠建立的 NEG。

zones 欄位接受字串值清單。您可以透過下列方式設定 zones 欄位:

  • 省略或空白清單: 如果缺少 zones 欄位或設為 [],控制器會使用預設行為:

    • 只有在叢集有節點的可用區中,才會建立 NEG。
    • 未使用的 NEG 會標示為 INACTIVE。
  • 萬用字元 ["*"]:這個選項會在 GKE 叢集所在區域的所有可用區中,建立空白的 NEG。這項行為適用於區域和可用區叢集 (如果是可用區叢集,GKE 會在區域的所有其他可用區中建立空白 NEG)。

  • 明確的可用區清單:這個選項會在指定可用區 (例如 ["us-central1-a", "us-central1-b"]) 中建立 NEG,以及叢集有節點的任何其他可用區。

需求條件和限制
  • 叢集必須使用 GKE 1.36.2-gke.3104000 以上版本。
  • zones 欄位中列出的所有可用區,都必須與叢集位於相同區域。
  • 如果 zones 欄位的格式設定不正確,控制器會改回標準行為,並在 Service 物件上引發 Warning 事件。
  • 空白 NEG 會計入區域專案配額。在多項服務中使用萬用字元設定,可能會超出限制。
  • 使用萬用字元 (["*"]) 選項設定 zones 欄位時,區域中新建立的可用區可能需要較長時間,才能傳播 NEG 預先佈建。如果工作負載依賴新可用區,請在註解中明確指定這些可用區。

擷取 NEG 狀態

使用下列指令擷取叢集服務的狀態:

kubectl get service neg-demo-svc -o yaml

輸出結果會與下列內容相似:

cloud.google.com/neg-status: '{
   "network-endpoint-groups":{
      "SERVICE_PORT_1": "NEG_NAME_1",
      "SERVICE_PORT_2": "NEG_NAME_2",
      ...
   },
   "zones":["ZONE_1", "ZONE_2", ...]
}

在這個輸出內容中,network-endpoint-groups 對應中的每個元素都是服務通訊埠 (例如 SERVICE_PORT_1),以及對應的代管 NEG 名稱 (例如 NEG_NAME_1)。zones 清單包含每個有 NEG 的區域 (例如 ZONE_1)。

輸出結果會與下列內容相似:

apiVersion: v1
kind: Service
metadata:
  annotations:
    cloud.google.com/neg: '{"exposed_ports": {"80":{}}}'
    cloud.google.com/neg-status: '{"network_endpoint_groups":{"80":"k8s1-cca197ad-default-neg-demo-app-80-4db81e02"},"zones":["ZONE_1", "ZONE_2"]}'
  labels:
    run: neg-demo-app
  name: neg-demo-app
  namespace: default
  selfLink: /api/v1/namespaces/default/services/neg-demo-app
  ...
spec:
  clusterIP: 10.0.14.252
  ports:
  - port: 80
    protocol: TCP
    targetPort: 9376
  selector:
    run: neg-demo-app
  sessionAffinity: None
status:
  loadBalancer: {}

在這個範例中,註解顯示服務通訊埠 80 會公開至名為 k8s1-cca197ad-default-neg-demo-app-80-4db81e02 的 NEG。

驗證 NEG 建立作業

建立 Service 後,系統會在幾分鐘內建立 NEG。如果 Pod 符合 Service 資訊清單中指定的標籤,建立 NEG 時,其中就會包含 Pod 的 IP。

您可以透過兩種方式,確認 NEG 已建立且設定正確。在 GKE 1.18.6-gke.6400 以上版本中,自訂資源 ServiceNetworkEndpointGroup 會儲存 Service 控制器建立的 NEG 狀態資訊。在舊版中,您必須直接檢查 NEG。

ServiceNetworkEndpointGroup資源

取得所有 ServiceNetworkEndpointGroup 資源,列出叢集中的 NEG:

kubectl get svcneg

如要觀察 NEG 的狀態,請檢查 ServiceNetworkEndpointGroup 資源的狀態:

kubectl get svcneg NEG_NAME -o yaml

將 NEG_NAME 替換為要檢查的個別 NEG 名稱。

這項指令的輸出內容包含狀態區段,其中可能含有錯誤訊息。如果您有預先佈建的 NEG,即使這些可用區中尚未執行任何 Pod,輸出內容也會顯示這些 NEG 處於 ACTIVE 狀態。

部分錯誤會回報為服務事件。您可以查詢 Service 物件,進一步瞭解詳細資料:

kubectl describe service SERVICE_NAME

將 SERVICE_NAME 替換為相關服務的名稱。

如要確認 NEG 控制器是否成功同步處理 NEG,請檢查 ServiceNetworkEndpointGroup 資源的狀態欄位,確認是否有 type:Synced 條件。上次同步處理的時間會顯示在 status.lastSyncTime 欄位中。

ServiceNetworkEndpointGroup 資源僅存在於 GKE 1.18 以上版本。

直接檢查 NEG

列出專案中的 NEG,並檢查是否有與您建立的服務相符的 NEG,藉此確認 NEG 是否存在。 Google CloudNEG 名稱的格式如下:

k8s1-CLUSTER_UID-NAMESPACE-SERVICE-PORT-RANDOM_HASH

使用下列指令列出 NEG:

gcloud compute network-endpoint-groups list

輸出結果會與下列內容相似:

NAME                                          LOCATION       ENDPOINT_TYPE   SIZE
k8s1-70aa83a6-default-my-service-80-c9710a6f  ZONE_NAME      GCE_VM_IP_PORT  3

這項輸出內容顯示 NEG 的 SIZE 為 3,表示有三個端點,對應於 Deployment 中的三個 Pod。

使用下列指令找出個別端點:

gcloud compute network-endpoint-groups list-network-endpoints NEG_NAME

將 NEG_NAME 替換為要顯示個別端點的 NEG 名稱。

輸出內容會顯示三個端點,每個端點都有 Pod 的 IP 位址和通訊埠:

INSTANCE                                           IP_ADDRESS  PORT
gke-cluster-3-default-pool-4cc71a15-qlpf  10.12.1.43  9376
gke-cluster-3-default-pool-4cc71a15-qlpf  10.12.1.44  9376
gke-cluster-3-default-pool-4cc71a15-w9nk  10.12.2.26  9376

將外部應用程式負載平衡器附加至獨立 NEG

您可以使用 Compute Engine API,將 NEG 做為外部應用程式負載平衡器的後端。

  1. 建立防火牆規則。負載平衡器需要存取叢集端點,才能執行健康狀態檢查。這個指令會建立防火牆規則,允許存取:

    gcloud compute firewall-rules create fw-allow-health-check-and-proxy \
       --network=NETWORK_NAME \
       --action=allow \
       --direction=ingress \
       --target-tags=GKE_NODE_NETWORK_TAGS \
       --source-ranges=130.211.0.0/22,35.191.0.0/16 \
       --rules=tcp:9376
    

    更改下列內容:

    • NETWORK_NAME:叢集執行的網路。
    • GKE_NODE_NETWORK_TAGS:GKE 節點上的網路標記。

    如果您未建立節點的自訂網路標記,GKE 會自動為您產生標記。您可以執行下列指令,查詢這些產生的標記:

    gcloud compute instances describe INSTANCE_NAME
    

    將 INSTANCE_NAME 替換為主機 Compute Engine VM 執行個體的名稱,該執行個體執行 GKE 節點。舉例來說,上一節的輸出內容會顯示 GKE 節點的 INSTANCE 資料欄中的執行個體名稱。

    如果是 Standard 叢集,您也可以執行 gcloud compute instances list,列出專案中的所有執行個體。

  2. 為負載平衡器建立全域虛擬 IP 位址:

    gcloud compute addresses create hostname-server-vip \
        --ip-version=IPV4 \
        --global
    
  3. 建立健康狀態檢查。負載平衡器會使用這項資訊,偵測 NEG 內個別端點的即時狀態。

    gcloud compute health-checks create http http-basic-check \
        --use-serving-port
    
  4. 建立後端服務,指定這是全域外部應用程式負載平衡器:

    gcloud compute backend-services create my-bes \
        --protocol HTTP \
        --health-checks http-basic-check \
        --global
    
  5. 為負載平衡器建立網址對應和目標 Proxy。這個範例非常簡單,因為本指南使用的 serve_hostname 應用程式只有一個端點,而且沒有網址。

    gcloud compute url-maps create web-map \
        --default-service my-bes
    
    gcloud compute target-http-proxies create http-lb-proxy \
        --url-map web-map
    
  6. 建立轉送規則。這會建立負載平衡器。

    gcloud compute forwarding-rules create http-forwarding-rule \
        --address=HOSTNAME_SERVER_VIP \
        --global \
        --target-http-proxy=http-lb-proxy \
        --ports=80
    

    將 HOSTNAME_SERVER_VIP 替換為負載平衡器要使用的 IP 位址。如果省略 --address,GKE 會自動指派臨時 IP 位址。

    您也可以預留新的靜態外部 IP 位址。

查核點

您目前已建立下列資源:

  • 外部虛擬 IP 位址
  • 轉送規則
  • 防火牆規則
  • 目標 HTTP Proxy
  • Compute Engine 健康狀態檢查的網址對應
  • 後端服務
  • Compute Engine 健康狀態檢查

這些資源之間的關係如下圖所示:

您建立的資源之間的關係。

這些資源合在一起就是負載平衡器。在下一個步驟中,您將為負載平衡器新增後端。

這裡展示的獨立 NEG 優點之一,是負載平衡器和後端的生命週期可以完全獨立。應用程式、服務或 GKE 叢集刪除後,負載平衡器仍可繼續運作。您可以在負載平衡器中新增及移除新的 NEG 或多個 NEG,不必變更任何前端負載平衡器物件。

在負載平衡器中新增後端

使用 gcloud compute backend-services add-backend 將 NEG 新增為 my-bes 後端服務的後端,藉此將 NEG 連線至負載平衡器:

gcloud compute backend-services add-backend my-bes \
    --global \
    --network-endpoint-group=NEG_NAME \
    --network-endpoint-group-zone=NEG_ZONE \
    --balancing-mode RATE --max-rate-per-endpoint 5

更改下列內容:

  • NEG_NAME:網路端點群組的名稱。名稱可以是您在建立 NEG 時指定的名稱,也可以是系統自動產生的名稱。如果您未指定 NEG 名稱,請按照下列操作說明找出自動產生的名稱。
  • NEG_ZONE:網路端點群組所在的可用區。請按照下列操作說明找出這個值。

使用下列指令,取得 NEG 的名稱和位置:

gcloud compute network-endpoint-groups list

輸出結果會與下列內容相似:

NAME                                          LOCATION       ENDPOINT_TYPE   SIZE
k8s1-70aa83a6-default-my-service-80-c9710a6f  ZONE_NAME      GCE_VM_IP_PORT  3

在本範例輸出內容中,NEG 名稱為 k8s1-70aa83a6-default-my-service-80-c9710a6f。

您可以將多個 NEG 新增至同一個後端服務。全域後端服務 (例如 my-bes) 的 NEG 後端可位於不同區域,但區域後端服務的後端必須位於單一區域。

驗證負載平衡器是否正常運作

您可以透過下列兩種方式,驗證設定的負載平衡器是否正常運作:

  • 確認健康狀態檢查設定正確無誤,且回報狀態為正常。
  • 存取應用程式並驗證其回應。

驗證健康檢查

確認後端服務已與健康狀態檢查和網路端點群組建立關聯,且個別端點健康狀態良好。

使用這項指令,確認後端服務與健康狀態檢查和網路端點群組相關聯:

gcloud compute backend-services describe my-bes --global

輸出結果會與下列內容相似:

backends:
- balancingMode: RATE
  capacityScaler: 1.0
  group: ... /networkEndpointGroups/k8s1-70aa83a6-default-my-service-80-c9710a6f
...
healthChecks:
- ... /healthChecks/http-basic-check
...
name: my-bes
...

接著,請檢查個別端點的健康狀態:

gcloud compute backend-services get-health my-bes --global

輸出內容的 status: 部分大致如下:

status:
  healthStatus:
  - healthState: HEALTHY
    instance: ... gke-cluster-3-default-pool-4cc71a15-qlpf
    ipAddress: 10.12.1.43
    port: 50000
  - healthState: HEALTHY
    instance: ... gke-cluster-3-default-pool-4cc71a15-qlpf
    ipAddress: 10.12.1.44
    port: 50000
  - healthState: HEALTHY
    instance: ... gke-cluster-3-default-pool-4cc71a15-w9nk
    ipAddress: 10.12.2.26
    port: 50000

存取應用程式

透過負載平衡器的 IP 位址存取應用程式,確認一切運作正常。

首先,取得負載平衡器的虛擬 IP 位址:

gcloud compute addresses describe hostname-server-vip --global | grep "address:"

輸出內容會包含 IP 位址。接著,將要求傳送至該 IP 位址 (本例中為 34.98.102.37):

curl 34.98.102.37

serve_hostname 應用程式的回應應為 neg-demo-app。

將內部應用程式負載平衡器附加至獨立 NEG

您可以透過 NEG,為在獨立 GKE Pod 中執行的服務設定內部應用程式負載平衡器。

設定僅限 Proxy 的子網路

Proxy 專用子網路適用於負載平衡器所在區域的所有區域性內部應用程式負載平衡器。

控制台

如果使用 Google Cloud 控制台,可以稍後再建立僅限 Proxy 的子網路。

gcloud

使用 gcloud compute networks subnets create 指令,建立僅限 Proxy 的子網路。

gcloud compute networks subnets create proxy-only-subnet \
    --purpose=REGIONAL_MANAGED_PROXY \
    --role=ACTIVE \
    --region=COMPUTE_REGION \
    --network=lb-network \
    --range=10.129.0.0/23

將 COMPUTE_REGION 替換為子網路的 Compute Engine。

API

使用 subnetworks.insert 方法建立僅限 Proxy 的子網路。

POST https://compute.googleapis.com/compute/projects/PROJECT_ID/regions/COMPUTE_REGION/subnetworks
{
  "name": "proxy-only-subnet",
  "ipCidrRange": "10.129.0.0/23",
  "network": "projects/PROJECT_ID/global/networks/lb-network",
  "region": "projects/PROJECT_ID/regions/COMPUTE_REGION",
  "purpose": "REGIONAL_MANAGED_PROXY",
  "role": "ACTIVE"
}

更改下列內容:

  • PROJECT_ID:您的專案 ID。
  • COMPUTE_REGION:子網路的 Compute Engine。

設定防火牆規則

這個範例使用以下防火牆規則:

  • fw-allow-ssh:適用於負載平衡執行個體的輸入規則,允許來自任何位址的 TCP 通訊埠 22 輸入 SSH 連線。您可以為這項規則選擇更嚴格的來源 IP 範圍。舉例來說,您可以只指定啟動 SSH 工作階段的系統 IP 範圍。本範例使用目標標記 allow-ssh 識別要套用防火牆規則的 VM。

  • fw-allow-health-check:輸入規則,適用於負載平衡的執行個體,允許來自 Google Cloud健康狀態檢查系統 (位於 130.211.0.0/22 和 35.191.0.0/16) 的所有 TCP 流量。本範例使用目標標記 load-balanced-backend 識別應套用規則的執行個體。

  • fw-allow-proxies:適用於負載平衡執行個體的輸入規則,允許來自內部 HTTP(S) 負載平衡器代管 Proxy 的 TCP 流量 (通訊埠 9376)。本範例使用目標標記 load-balanced-backend 識別應套用規則的執行個體。

如果沒有這些防火牆規則,預設拒絕輸入規則將會封鎖傳入至後端執行個體的流量。

控制台

  1. 前往 Google Cloud 控制台的「Firewall policies」(防火牆政策) 頁面。

    前往「Firewall policies」(防火牆政策) 頁面

  2. 按一下「Create firewall rule」(建立防火牆規則) ,建立允許連入 SSH 連線的規則:

    • Name (名稱):fw-allow-ssh
    • Network (網路):lb-network
    • 「Direction of traffic」(流量方向):[ingress] (輸入)
    • 「Action on match」(相符時執行的動作):[allow] (允許)
    • 「Target」(目標):指定的目標標記
    • 「Target tags」(目標標記):allow-ssh
    • Source filter (來源篩選器):IPv4 ranges
    • Source IPv4 ranges (來源 IPv4 範圍):0.0.0.0/0
    • 「通訊協定和通訊埠」:
      • 選取「指定的通訊協定和通訊埠」。
      • 選取 tcp 核取方塊,並指定通訊埠 22。
  3. 點選「建立」。

  4. 再次按一下「建立防火牆規則」,建立允許Google Cloud 健康狀態檢查的規則:

    • Name (名稱):fw-allow-health-check
    • Network (網路):lb-network
    • 「Direction of traffic」(流量方向):[ingress] (輸入)
    • 「Action on match」(相符時執行的動作):[allow] (允許)
    • 「Target」(目標):指定的目標標記
    • 「Target tags」(目標標記):load-balanced-backend
    • Source filter (來源篩選器):IPv4 ranges
    • Source IPv4 ranges (來源 IPv4 範圍):130.211.0.0/22 和 35.191.0.0/16
    • 「通訊協定和通訊埠」:
      • 選取「指定的通訊協定和通訊埠」
      • 選取 tcp 核取方塊,並指定通訊埠 80。 最佳做法是將這項規則限制在與健康狀態檢查所用通訊協定和通訊埠相符的範圍內。如果您使用 tcp:80 做為通訊協定和通訊埠, Google Cloud 可以透過通訊埠 80 上的 HTTP 與 VM 聯絡,但無法透過通訊埠 443 上的 HTTPS 與 VM 聯絡。
  5. 點選「建立」。

  6. 再次按一下「建立防火牆規則」,建立規則,允許負載平衡器的 Proxy 伺服器連線至後端:

    • Name (名稱):fw-allow-proxies
    • Network (網路):lb-network
    • 「Direction of traffic」(流量方向):[ingress] (輸入)
    • 「Action on match」(相符時執行的動作):[allow] (允許)
    • 「Target」(目標):指定的目標標記
    • 「Target tags」(目標標記):load-balanced-backend
    • Source filter (來源篩選器):IPv4 ranges
    • Source IPv4 ranges (來源 IPv4 範圍):10.129.0.0/23
    • 「通訊協定和通訊埠」:
      • 選取「指定的通訊協定和通訊埠」。
      • 勾選「tcp」核取方塊,並指定通訊埠 9376。
  7. 點選「建立」。

gcloud

  1. 建立 fw-allow-ssh 防火牆規則,允許透過 SSH 連線至具有 allow-ssh 網路標記的 VM。如果省略 source-ranges,Google Cloud 會將規則解讀為任何來源。

    gcloud compute firewall-rules create fw-allow-ssh \
        --network=lb-network \
        --action=allow \
        --direction=ingress \
        --target-tags=allow-ssh \
        --rules=tcp:22
    
  2. 建立 fw-allow-health-check 規則,允許健康狀態檢查。 Google Cloud這個範例可允許來自健康狀態檢查探測器的所有 TCP 流量,但您可以根據自己的需求設定一組較少的通訊埠。

    gcloud compute firewall-rules create fw-allow-health-check \
        --network=lb-network \
        --action=allow \
        --direction=ingress \
        --source-ranges=130.211.0.0/22,35.191.0.0/16 \
        --target-tags=load-balanced-backend \
        --rules=tcp
    
  3. 建立 fw-allow-proxies 規則,允許內部 HTTP(S) 負載平衡器的 Proxy 連線至後端。

    gcloud compute firewall-rules create fw-allow-proxies \
        --network=lb-network \
        --action=allow \
        --direction=ingress \
        --source-ranges=10.129.0.0/23 \
        --target-tags=load-balanced-backend \
        --rules=tcp:9376
    

API

對 firewalls.insert 方法發出 POST 要求,建立 fw-allow-ssh 防火牆規則。

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/firewalls
{
  "name": "fw-allow-ssh",
  "network": "projects/PROJECT_ID/global/networks/lb-network",
  "sourceRanges": [
    "0.0.0.0/0"
  ],
  "targetTags": [
    "allow-ssh"
  ],
  "allowed": [
   {
     "IPProtocol": "tcp",
     "ports": [
       "22"
     ]
   }
  ],
 "direction": "INGRESS"
}

將 PROJECT_ID 替換為專案 ID。

對 firewalls.insert 方法提出 POST 要求,建立 fw-allow-health-check 防火牆規則。

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/firewalls
{
  "name": "fw-allow-health-check",
  "network": "projects/PROJECT_ID/global/networks/lb-network",
  "sourceRanges": [
    "130.211.0.0/22",
    "35.191.0.0/16"
  ],
  "targetTags": [
    "load-balanced-backend"
  ],
  "allowed": [
    {
      "IPProtocol": "tcp"
    }
  ],
  "direction": "INGRESS"
}

建立 fw-allow-proxies 防火牆規則,允許在 Proxy 子網路中傳輸 TCP 流量。firewalls.insert

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/firewalls
{
  "name": "fw-allow-proxies",
  "network": "projects/PROJECT_ID/global/networks/lb-network",
  "sourceRanges": [
    "10.129.0.0/23"
  ],
  "targetTags": [
    "load-balanced-backend"
  ],
  "allowed": [
    {
      "IPProtocol": "tcp",
      "ports": [
        "9376"
      ]
    }
  ],
  "direction": "INGRESS"
}

將 PROJECT_ID 替換為專案 ID。

設定負載平衡器

轉送規則的 IP 位址請使用後端子網路。如果您嘗試使用僅限 Proxy 的子網路,系統會無法建立轉送規則。

控制台

選擇負載平衡器類型

  1. 前往 Google Cloud 控制台的「建立負載平衡器」頁面。 前往「Create a load balancer」(建立負載平衡器)
  2. 在「HTTP(S) 負載平衡」下方,按一下「開始設定」。
  3. 選擇 [Only between my VMs] (僅在我的 VM 之間),這項設定代表使用內部的負載平衡器。
  4. 按一下「繼續」。

準備負載平衡器

  1. 在負載平衡器的「Name」(名稱) 中輸入 l7-ilb-gke-map。
  2. 在「Region」(區域) 部分,選取您建立子網路的區域。
  3. 在「Network」(網路) 部分,選取「lb-network」。

保留僅限 Proxy 子網路

預留僅限 Proxy 的子網路:

  1. 按一下 [Reserve a Subnet] (保留子網路)。
  2. 在「Name」(名稱) 中輸入 proxy-only-subnet。
  3. 在「IP address range」(IP 位址範圍) 中輸入 10.129.0.0/23。
  4. 按一下「新增」。

設定後端服務

  1. 按一下 [Backend configuration] (後端設定)。
  2. 在「Create or select backend services」(建立或選取後端服務) 選單中,選取 [Create a backend service] (建立後端服務)。
  3. 將後端服務的「名稱」設為 l7-ilb-gke-backend-service。
  4. 在「後端類型」部分,選取「網路端點群組」。
  5. 在「Backends」(後端) 部分的「New backend」(新增後端) 資訊卡中:
    1. 將「Network endpoint group」(網路端點群組) 設為 GKE 建立的 NEG。如要取得 NEG 名稱,請參閱「驗證 NEG 建立作業」。
    2. 在「Maximum RPS」(每秒要求數上限) 部分,指定每個端點的每秒要求數上限為 5。如有必要,Google Cloud 會超過這個上限。
    3. 按一下「完成」。
  6. 從「健康狀態檢查」下拉式選單中,選取「建立健康狀態檢查」,然後指定下列參數:
    1. Name (名稱):l7-ilb-gke-basic-check
    2. 「通訊協定」:HTTP
    3. 通訊埠規格:供應通訊埠
    4. 按一下 [Save and Continue] (儲存並繼續)。
  7. 按一下 [Create] (建立)。

設定網址對應

  1. 按一下「轉送規則」。確認 l7-ilb-gke-backend-service 是唯一不相符主機和路徑的後端服務。

設定前端

按一下「前端設定」,然後執行下列步驟:

HTTP:

  1. 點選「前端設定」。
  2. 按一下 [Add frontend IP and port] (新增前端 IP 和通訊埠)。
  3. 將「名稱」設為 l7-ilb-gke-forwarding-rule。
  4. 將「Protocol」(通訊協定) 設為「HTTP」HTTP。
  5. 將「Subnetwork」(子網路) 設為叢集子網路的名稱。
  6. 在「內部 IP」下方,選取「保留靜態內部 IP 位址」。
  7. 在顯示的面板中提供下列詳細資料:
    1. Name (名稱):l7-ilb-gke-ip
    2. 在「Static IP address」(靜態 IP 位址) 區段中,選取「Let me choose」(自行選擇)。
    3. 在「Custom IP address」(自訂 IP 位址) 部分中,輸入 10.1.2.199。
    4. 點選「保留」。
  8. 將「Port」(通訊埠) 設為 80。
  9. 按一下「完成」。

HTTPS:

如果在用戶端與負載平衡器間使用 HTTPS,則需要一或多個 SSL 憑證資源才能設定 Proxy。如要瞭解如何建立 SSL 憑證資源,請參閱「SSL 憑證」。內部 HTTP(S) 負載平衡器不支援 Google 管理的憑證。

  1. 點選「前端設定」。
  2. 按一下 [Add frontend IP and port] (新增前端 IP 和通訊埠)。
  3. 在「Name」(名稱) 欄位中,輸入 l7-ilb-gke-forwarding-rule。
  4. 在「Protocol」(通訊協定) 欄位中選取 HTTPS (includes HTTP/2)。
  5. 將「Subnet」(子網路) 設為叢集子網路的名稱。
  6. 在「內部 IP」下方,選取「保留靜態內部 IP 位址」。
  7. 在顯示的面板中提供下列詳細資料:
    1. Name (名稱):l7-ilb-gke-ip
    2. 在「Static IP address」(靜態 IP 位址) 區段中,選取「Let me choose」(自行選擇)。
    3. 在「Custom IP address」(自訂 IP 位址) 部分中,輸入 10.1.2.199。
    4. 點選「保留」。
  8. 確認「Port」(通訊埠) 已設為 443,以允許 HTTPS 流量。
  9. 按一下「Certificate」(憑證) 下拉式選單。
    1. 如果已有自行管理的 SSL 憑證資源,且想要做為主要 SSL 憑證使用,請在下拉式選單中選取所需資源。
    2. 否則,請選取「建立新憑證」。
      1. 在「Name」(名稱) 部分填入 l7-ilb-cert。
      2. 在適當的欄位中上傳 PEM 格式的檔案:
        • 公用金鑰憑證
        • 憑證鏈結
        • 私密金鑰
      3. 點選「建立」。
  10. 如要新增主要 SSL 憑證資源以外的憑證資源,請按照下列步驟操作:
    1. 按一下「Add certificate」(新增憑證)。
    2. 從「Certificates」(憑證) 清單中選取所需憑證,或是按一下「Create a new certificate」(建立新憑證) 並按照指示操作。
  11. 按一下「完成」。

完成設定程序

點選「建立」。

gcloud

  1. 使用 gcloud compute health-checks create http 指令定義 HTTP 健康狀態檢查。

    gcloud compute health-checks create http l7-ilb-gke-basic-check \
        --region=COMPUTE_REGION \
        --use-serving-port
    
  2. 使用 gcloud compute backend-services create 指令定義後端服務。

    gcloud compute backend-services create l7-ilb-gke-backend-service \
        --load-balancing-scheme=INTERNAL_MANAGED \
        --protocol=HTTP \
        --health-checks=l7-ilb-gke-basic-check \
        --health-checks-region=COMPUTE_REGION \
        --region=COMPUTE_REGION
    
  3. 設定 DEPLOYMENT_NAME 變數:

    export DEPLOYMENT_NAME=NEG_NAME
    

    將 NEG_NAME 替換為 NEG 名稱。

  4. 使用 gcloud compute backend-services add-backend 指令,將 NEG 後端新增至後端服務。

    gcloud compute backend-services add-backend l7-ilb-gke-backend-service \
        --network-endpoint-group=$DEPLOYMENT_NAME \
        --network-endpoint-group-zone=COMPUTE_ZONE-b \
        --region=COMPUTE_REGION \
        --balancing-mode=RATE \
        --max-rate-per-endpoint=5
    
  5. 使用 gcloud compute url-maps create 指令建立網址對應。

    gcloud compute url-maps create l7-ilb-gke-map \
        --default-service=l7-ilb-gke-backend-service \
        --region=COMPUTE_REGION
    
  6. 建立目標 Proxy。

    HTTP:

    使用 gcloud compute target-http-proxies create 指令。

    gcloud compute target-http-proxies create l7-ilb-gke-proxy \
        --url-map=l7-ilb-gke-map \
        --url-map-region=COMPUTE_REGION \
        --region=COMPUTE_REGION
    

    HTTPS:

    如要瞭解如何建立 SSL 憑證資源,請參閱「SSL 憑證」。內部 HTTP(S) 負載平衡器不支援 Google 代管憑證。

    將檔案路徑指派給變數名稱。

    export LB_CERT=PATH_TO_PEM_FORMATTED_FILE
    
    export LB_PRIVATE_KEY=PATH_TO_PEM_FORMATTED_FILE
    

    使用 gcloud compute ssl-certificates create 指令,建立區域性 SSL 憑證。

    gcloud compute ssl-certificates create

    gcloud compute ssl-certificates create l7-ilb-cert \
        --certificate=$LB_CERT \
        --private-key=$LB_PRIVATE_KEY \
        --region=COMPUTE_REGION
    

    使用區域性 SSL 憑證,透過 gcloud compute target-https-proxies create 指令建立目標 Proxy。

    gcloud compute target-https-proxies create l7-ilb-gke-proxy \
        --url-map=l7-ilb-gke-map \
        --region=COMPUTE_REGION \
        --ssl-certificates=l7-ilb-cert
    
  7. 建立轉送規則。

    如果是自訂網路,您必須參照轉送規則中的子網路。請注意,這是 VM 子網路,而不是 Proxy 子網路。

    HTTP:

    使用 gcloud compute forwarding-rules create 指令,並加上正確的旗標。

    gcloud compute forwarding-rules create l7-ilb-gke-forwarding-rule \
        --load-balancing-scheme=INTERNAL_MANAGED \
        --network=lb-network \
        --subnet=SUBNET_NAME \
        --address=10.1.2.199 \
        --ports=80 \
        --region=COMPUTE_REGION \
        --target-http-proxy=l7-ilb-gke-proxy \
        --target-http-proxy-region=COMPUTE_REGION
    

    HTTPS:

    使用 gcloud compute forwarding-rules create 指令,並加上正確的旗標。

    gcloud compute forwarding-rules create l7-ilb-gke-forwarding-rule \
        --load-balancing-scheme=INTERNAL_MANAGED \
        --network=lb-network \
        --subnet=SUBNET_NAME  \
        --address=10.1.2.199 \
        --ports=443 \
        --region=COMPUTE_REGION \
        --target-https-proxy=l7-ilb-gke-proxy \
        --target-https-proxy-region=COMPUTE_REGION
    

    將 SUBNET_NAME 替換為叢集的子網路名稱。

API

對 regionHealthChecks.insert 方法發出 POST 要求,建立健康狀態檢查。

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/regions/COMPUTE_REGION/healthChecks
{
   "name": "l7-ilb-gke-basic-check",
   "type": "HTTP",
   "httpHealthCheck": {
     "portSpecification": "USE_SERVING_PORT"
   }
}

將 PROJECT_ID 替換為專案 ID。

向 regionBackendServices.insert 方法發出 POST 要求,建立區域後端服務。

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/regions/COMPUTE_REGION/backendServices
{
  "name": "l7-ilb-gke-backend-service",
  "backends": [
    {
      "group": "https://www.googleapis.com/compute/v1/projects/PROJECT_ID/zones/COMPUTE_ZONE/networkEndpointGroups/NEG_NAME",
      "balancingMode": "RATE",
      "maxRatePerEndpoint": 5
    }
  ],
  "healthChecks": [
    "projects/PROJECT_ID/regions/COMPUTE_REGION/healthChecks/l7-ilb-gke-basic-check"
  ],
  "loadBalancingScheme": "INTERNAL_MANAGED"
}

更改下列內容:

  • PROJECT_ID:專案 ID。
  • NEG_NAME:NEG 的名稱。

向 regionUrlMaps.insert 方法發出 POST 要求,建立網址對應。

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/regions/COMPUTE_REGION/urlMaps
{
  "name": "l7-ilb-gke-map",
  "defaultService": "projects/PROJECT_ID/regions/COMPUTE_REGION/backendServices/l7-ilb-gke-backend-service"
}

將 PROJECT_ID 替換為專案 ID。

對 regionTargetHttpProxies.insert 方法發出 POST 要求,建立目標 HTTP Proxy。

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/regions/COMPUTE_REGION/targetHttpProxy
{
  "name": "l7-ilb-gke-proxy",
  "urlMap": "projects/PROJECT_ID/global/urlMaps/l7-ilb-gke-map",
  "region": "COMPUTE_REGION"
}

將 PROJECT_ID 替換為專案 ID。

對 forwardingRules.insert 方法發出 POST 要求,建立轉送規則。

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/regions/COMPUTE_REGION/forwardingRules
{
  "name": "l7-ilb-gke-forwarding-rule",
  "IPAddress": "10.1.2.199",
  "IPProtocol": "TCP",
  "portRange": "80-80",
  "target": "projects/PROJECT_ID/regions/COMPUTE_REGION/targetHttpProxies/l7-ilb-gke-proxy",
  "loadBalancingScheme": "INTERNAL_MANAGED",
  "subnetwork": "projects/PROJECT_ID/regions/COMPUTE_REGION/subnetworks/SUBNET_NAME",
  "network": "projects/PROJECT_ID/global/networks/lb-network",
  "networkTier": "PREMIUM",
}

將 PROJECT_ID 替換為專案 ID。

測試

在可用區中建立 VM 執行個體,測試連線能力:

gcloud compute instances create l7-ilb-client \
    --image-family=debian-9 \
    --image-project=debian-cloud \
    --zone=COMPUTE_ZONE \
    --network=lb-network \
    --subnet=SUBNET_NAME \
    --tags=l7-ilb-client,allow-ssh

登入用戶端執行個體,確認可以使用內部應用程式負載平衡器的轉送規則 IP 位址,連上後端的 HTTP(S) 服務,且流量在 NEG 的端點之間達到負載平衡。

使用 SSH 連線至每個用戶端執行個體:

gcloud compute ssh l7-ilb-client \
    --zone=COMPUTE_ZONE-b

確認 IP 是否提供主機名稱:

curl 10.1.2.199

如要測試 HTTPS,請執行下列指令:

curl -k -s 'https://test.example.com:443' --connect-to test.example.com:443:10.1.2.199:443

-k 旗標會導致 curl 略過憑證驗證。

執行 100 個要求,並確認這些要求已完成負載平衡。

HTTP:

{
RESULTS=
for i in {1..100}
do
    RESULTS="$RESULTS:$(curl --silent 10.1.2.199)"
done
echo "***"
echo "*** Results of load-balancing to 10.1.2.199: "
echo "***"
echo "$RESULTS" | tr ':' '\n' | grep -Ev "^$" | sort | uniq -c
echo
}

HTTPS:

{
RESULTS=
for i in {1..100}
do
    RESULTS="$RESULTS:$(curl -k -s 'https://test.example.com:443' --connect-to test.example.com:443:10.1.2.199:443
)"
done
echo "***"
echo "*** Results of load-balancing to 10.1.2.199: "
echo "***"
echo "$RESULTS" | tr ':' '\n' | grep -Ev "^$" | sort | uniq -c
echo
}

將外部 Proxy 網路負載平衡器附加至獨立 NEG

您可以使用獨立 NEG,透過外部 Proxy 網路負載平衡器直接對容器進行負載平衡,Kubernetes 或 GKE 原生不支援這項功能。Proxy 網路負載平衡器僅適用於 TCP 流量,無論是否使用 SSL 皆可。如果是 HTTP(S) 流量,建議改用應用程式負載平衡器。

  1. 建立防火牆規則,允許健康狀態檢查。

    負載平衡器需要存取叢集端點,才能執行健康狀態檢查。以下指令會建立防火牆規則,允許存取:

    gcloud compute firewall-rules create allow-tcp-lb-and-health \
       --network=NETWORK_NAME \
       --target-tags=GKE_NODE_NETWORK_TAGS \
       --source-ranges=130.211.0.0/22,35.191.0.0/16 \
       --allow tcp:9376
    

    更改下列內容:

    • NETWORK_NAME:叢集執行的網路。
    • GKE_NODE_NETWORK_TAGS:GKE 節點上的網路標記。

    如果您沒有為節點建立自訂網路標記,GKE 會自動為您產生標記。您可以執行下列指令,查詢這些產生的標記:

    gcloud compute instances describe INSTANCE_NAME
    

    將 INSTANCE_NAME 替換為執行 GKE 節點的主機 Compute Engine VM 執行個體名稱。舉例來說,直接檢查 NEG 一節中的輸出內容,會顯示 GKE 節點的 INSTANCE 欄位中的執行個體名稱。

    如果是標準叢集,您也可以執行 gcloud compute instances list,列出專案中的所有執行個體。

    如果是 Autopilot 叢集,請指定叢集服務帳戶,而非網路標記。

    將 --target-tags=GKE_NODE_NETWORK_TAGS 旗標替換為 --target-service-accounts=SERVICE_ACCOUNT_EMAIL。建議您為叢集使用僅具備必要權限的自訂服務帳戶。

  2. 為負載平衡器建立全域虛擬 IP 位址:

    gcloud compute addresses create tcp-lb-static-ipv4 \
       --ip-version=IPV4 \
       --global
    
  3. 定義後端端點的健康狀態檢查。

    負載平衡器會使用健康狀態檢查,偵測 NEG 內個別端點的即時狀態。

    gcloud compute health-checks create tcp my-tcp-health-check \
       --use-serving-port
    
  4. 建立具有工作階段相依性的後端服務。

    這個後端服務會指定這是具有 CLIENT_IP 工作階段相依性的外部 Proxy 網路負載平衡器:

    gcloud compute backend-services create my-tcp-lb \
       --load-balancing-scheme EXTERNAL_MANAGED \
       --global-health-checks \
       --global \
       --protocol TCP \
       --health-checks my-tcp-health-check \
       --timeout 5m \
       --session-affinity=CLIENT_IP
    
  5. 為負載平衡器建立目標 TCP Proxy。

    如要開啟Proxy 標頭,請將值設為 PROXY_V1,而非 NONE。

    gcloud compute target-tcp-proxies create my-tcp-lb-target-proxy \
        --backend-service my-tcp-lb \
        --proxy-header NONE
    
  6. 建立轉送規則來轉送流量。

    這項轉送規則會建立負載平衡器。

     gcloud compute forwarding-rules create my-tcp-lb-ipv4-forwarding-rule \
        --load-balancing-scheme EXTERNAL_MANAGED \
        --global \
        --target-tcp-proxy my-tcp-lb-target-proxy \
        --address tcp-lb-static-ipv4 \
        --ports 80
    

確認負載平衡器資源建立作業

您已建立下列資源:

  • 外部虛擬 IP 位址
  • 轉送規則
  • 防火牆規則
  • 目標 Proxy
  • 後端服務
  • Compute Engine 健康狀態檢查

外部虛擬 IP 位址會連線至轉送規則,將防火牆規則允許的流量導向目標 Proxy。目標 Proxy 接著會與後端服務通訊,健康狀態檢查會定期檢查後端服務。這些資源之間的關係如下圖所示:

所建立資源之間的關係。

這些資源共同構成負載平衡器。在下一個步驟中,您將後端新增至負載平衡器。

這裡展示的獨立 NEG 優點之一,就是負載平衡器和後端的生命週期完全獨立。應用程式、服務或 GKE 叢集刪除後,負載平衡器仍可繼續運作。您可以從負載平衡器新增及移除新的 NEG 或多個 NEG,而不必變更任何前端負載平衡器物件。

將獨立 NEG 新增為負載平衡器的後端

使用 gcloud compute backend-services add-backend 將 NEG 新增為 my-tcp-lb 後端服務的後端,藉此將 NEG 連線至負載平衡器:

gcloud compute backend-services add-backend my-tcp-lb \
    --global \
    --network-endpoint-group=NEG_NAME \
    --network-endpoint-group-zone=NEG_ZONE \
    --balancing-mode CONNECTION \
    --max-connections 100

更改下列內容:

  • NEG_NAME:網路端點群組的名稱。名稱可能是建立 NEG 時指定的名稱,也可能是自動產生的名稱。如果您未指定 NEG 的名稱,請按照下列操作說明找出自動產生的名稱。
  • NEG_ZONE:網路端點群組所在的可用區。請按照下列操作說明找出這個值。

如要取得 NEG 的名稱和位置,請使用下列指令:

gcloud compute network-endpoint-groups list

輸出結果會與下列內容相似:

NAME: k8s1-65a95e90-default-neg-demo-svc-80-663a85e4
LOCATION: us-central1-a
ENDPOINT_TYPE: GCE_VM_IP_PORT
SIZE: 3

在本範例輸出內容中,NEG 名稱為 kk8s1-65a95e90-default-neg-demo-svc-80-663a85e4,可用區為 us-central1-a。

您可以為同一個後端服務新增多個 NEG。全域後端服務 (例如 my-tcp-lb) 的 NEG 後端可位於不同區域,但區域後端服務的後端必須位於單一區域。

驗證負載平衡器設定和連線

有兩種方法可驗證您設定的負載平衡器是否正常運作:

  • 確認健康狀態檢查設定正確無誤,且回報為正常。
  • 存取應用程式並驗證其回應。

驗證健康檢查

確認後端服務已與健康狀態檢查和網路端點群組建立關聯,且個別端點健康狀態良好。

如要確認後端服務已與健康狀態檢查和網路端點群組建立關聯,請使用下列指令:

gcloud compute backend-services describe my-tcp-lb --global

輸出結果會與下列內容相似:

backends:
- balancingMode: CONNECTION
  group: ... /networkEndpointGroups/k8s1-65a95e90-default-neg-demo-svc-80-663a85e4
  maxConnections: 100
...
healthChecks:
- ... /healthChecks/my-tcp-health-check
...
name: my-tcp-lb
...

接著,請檢查個別端點的健康狀態:

gcloud compute backend-services get-health my-tcp-lb --global

輸出內容的 status: 區段大致如下:

status:
  healthStatus:
  - healthState: HEALTHY
    instance: ... gke-cluster-3-default-pool-4cc71a15-qlpf
    ipAddress: 10.12.1.43
    port: 50000
  - healthState: HEALTHY
    instance: ... gke-cluster-3-default-pool-4cc71a15-qlpf
    ipAddress: 10.12.1.44
    port: 50000
  - healthState: HEALTHY
    instance: ... gke-cluster-3-default-pool-4cc71a15-w9nk
    ipAddress: 10.12.2.26
    port: 50000

驗證應用程式連線

如要確認負載平衡器運作正常,請透過負載平衡器的外部 IP 位址存取應用程式。

  1. 取得負載平衡器的外部 IP 位址:

    如要擷取為負載平衡器保留的外部 IP 位址,請使用下列指令:

    gcloud compute addresses describe tcp-lb-static-ipv4 --global | grep "address:"
    

    這個指令會輸出 IP 位址。

  2. 傳送要求至 IP 位址:

    使用 curl 指令將要求傳送至外部 IP 位址。

    curl EXTERNAL_IP_ADDRESS
    

    將 EXTERNAL_IP_ADDRESS 替換為您在上一個步驟中取得的 IP 位址:

    serve_hostname 應用程式的回應應以 neg-demo-app 開頭。

實作異質服務 (VM 和容器)

負載平衡器可做為混合 Kubernetes 和非 Kubernetes 工作負載的前端。這可能是從 VM 遷移至容器的一部分,或是可從共用負載平衡器獲益的永久架構。如要達成這個目標,請建立以不同類型後端 (包括獨立 NEG) 為目標的負載平衡器。

位於相同後端服務中的 VM 和容器

這個範例說明如何建立 NEG,指向執行工作負載的現有 VM,以及如何將這個 NEG 新增為現有 backendService 的另一個後端。這樣一來,單一負載平衡器就能在 VM 和 GKE 容器之間平衡負載。

這個範例會擴充上一個範例,使用外部 HTTP 負載平衡器。

由於所有端點都依相同的 backendService 分組,因此 VM 和容器端點會視為「相同服務」。這表示主機或路徑比對會根據網址對應規則,一視同仁地對待所有後端。

所述架構。先前建立的負載平衡器會指向兩個 NEG,一個是先前建立的容器 NEG,另一個是包含 VM IP 位址的新 NEG。

將 NEG 設為後端服務的後端時,該後端服務中的所有其他後端也必須是 NEG。您無法在同一個後端服務中,同時使用執行個體群組和 NEG 做為後端。此外,容器和 VM 無法做為同一個 NEG 中的端點,因此必須一律使用不同的 NEG 進行設定。

  1. 使用下列指令,將 VM 部署至 Compute Engine:

    gcloud compute instances create vm1 \
        --zone=COMPUTE_ZONE \
        --network=NETWORK \
        --subnet=SUBNET \
        --image-project=cos-cloud \
        --image-family=cos-stable --tags=vm-neg-tag
    

    更改下列內容:

    • COMPUTE_ZONE:可用區名稱。
    • NETWORK:網路名稱。
    • SUBNET:與網路相關聯的子網路名稱。
  2. 將應用程式部署至 VM:

    gcloud compute ssh vm1 \
        --zone=COMPUTE_ZONE \
        --command="docker run -d --rm --network=host registry.k8s.io/e2e-test-images/agnhost:2.40 serve-hostname --port=9376 && sudo iptables -P INPUT ACCEPT"
    

    這個指令會將先前範例中使用的範例應用程式部署至 VM。為求簡化,應用程式會以 Docker 容器形式執行,但這並非必要。必須使用 iptables 指令,才能允許防火牆存取正在執行的容器。

  3. 確認應用程式在通訊埠 9376 提供服務,並回報在 vm1 執行:

    gcloud compute ssh vm1 \
        --zone=COMPUTE_ZONE \
        --command="curl -s localhost:9376"
    

    伺服器應會回覆 vm1。

  4. 建立要與 VM 端點搭配使用的 NEG。容器和 VM 都可以是 NEG 端點,但單一 NEG 無法同時擁有 VM 和容器端點。

    gcloud compute network-endpoint-groups create vm-neg \
        --subnet=SUBNET \
        --zone=COMPUTE_ZONE
    
  5. 將 VM 端點附加至 NEG:

    gcloud compute network-endpoint-groups update vm-neg \
        --zone=COMPUTE_ZONE \
        --add-endpoint="instance=vm1,ip=VM_PRIMARY_IP,port=9376"
    

    將 VM_PRIMARY_IP 替換為 VM 的主要 IP 位址。

  6. 確認 NEG 具有 VM 端點:

    gcloud compute network-endpoint-groups list-network-endpoints vm-neg \
        --zone COMPUTE_ZONE
    
  7. 使用新增容器後端時所用的指令,將 NEG 附加至後端服務:

    gcloud compute backend-services add-backend my-bes
        --global \
        --network-endpoint-group vm-neg \
        --network-endpoint-group-zone COMPUTE_ZONE \
        --balancing-mode RATE --max-rate-per-endpoint 10
    
  8. 開啟防火牆,允許 VM 的健康狀態檢查:

    gcloud compute firewall-rules create fw-allow-health-check-to-vm1 \
        --network=NETWORK \
        --action=allow \
        --direction=ingress \
        --target-tags=vm-neg-tag \
        --source-ranges=130.211.0.0/22,35.191.0.0/16 \
        --rules=tcp:9376
    
  9. 傳送測試流量,驗證負載平衡器是否將流量轉送至新的 vm1 後端和現有的容器後端:

    for i in `seq 1 100`; do curl ${VIP};echo; done
    

    您應該會看到來自容器 (neg-demo-app) 和 VM (vm1) 端點的回應。

不同後端服務的 VM 和容器

這個範例說明如何建立指向現有 VM (執行工作負載) 的 NEG,以及如何將這個 NEG 新增為新 backendService 的後端。如果容器和 VM 是不同的服務,但需要共用相同的第 7 層負載平衡器,例如服務共用相同的 IP 位址或網域名稱,這項功能就非常實用。

本範例擴充了上一個範例,該範例在與容器後端相同的後端服務中,具有 VM 後端。這個範例會重複使用該 VM。

由於容器和 VM 端點會分組到不同的後端服務,因此會視為不同的服務。也就是說,網址對應會比對後端,並根據主機名稱將流量導向 VM 或容器。

下圖顯示單一虛擬 IP 位址如何對應至兩個主機名稱,而這兩個主機名稱又分別對應至以容器為基礎的後端服務,以及以 VM 為基礎的後端服務。

單一虛擬 IP 位址對應至兩個主機名稱,一個主機名稱用於容器型後端,另一個用於 VM 型後端。

下圖顯示上一節所述的架構:

這個架構有兩個 NEG,一個用於以容器實作的服務,另一個用於以 VM 實作的服務。每個 NEG 都有一個後端服務物件。網址對應物件會根據要求的網址,將流量導向正確的後端服務。

  1. 為 VM 建立新的後端服務:

    gcloud compute backend-services create my-vm-bes \
       --protocol HTTP \
       --health-checks http-basic-check \
       --global
    
  2. 將 VM 的 NEG (vm-neg) 附加至後端服務:

    gcloud compute backend-services add-backend my-vm-bes \
        --global \
        --network-endpoint-group vm-neg \
        --network-endpoint-group-zone COMPUTE_ZONE \
        --balancing-mode RATE --max-rate-per-endpoint 10
    
  3. 在網址對應中新增主機規則,將 container.example.com 主機的要求導向容器後端服務:

    gcloud compute url-maps add-path-matcher web-map \
        --path-matcher-name=container-path --default-service=my-bes \
        --new-hosts=container.example.com --global
    
  4. 在網址對應中新增另一個主機規則,將 vm.example.com 主機的要求導向 VM 後端服務:

    gcloud compute url-maps add-path-matcher web-map \
        --path-matcher-name=vm-path --default-service=my-vm-bes \
        --new-hosts=vm.example.com --global
    
  5. 確認負載平衡器是否根據要求的路徑,將流量傳送至 VM 後端:

    curl -H "HOST:vm.example.com" VIRTUAL_IP
    

    將 VIRTUAL_IP 替換為虛擬 IP 位址。

獨立 NEG 的限制

定價

如要瞭解負載平衡器的定價詳情,請參閱定價頁面的負載平衡部分。使用 NEG 不會產生額外費用。

疑難排解

本節提供疑難排解步驟,協助您解決獨立 NEG 的常見問題。

未設定獨立 NEG

症狀:未建立 NEG。

可能的解決方法:

  • 檢查與服務相關的事件,找出錯誤訊息。
  • 確認獨立 NEG 註解的 JSON 格式正確無誤,且公開的連接埠與服務規格中的現有連接埠相符。
  • 驗證 NEG 狀態註解,並確認預期的服務連接埠是否有對應的 NEG。
  • 使用 gcloud compute network-endpoint-groups list 指令,確認 NEG 已在預期可用區中建立。
  • 如果使用 GKE 1.18 以上版本,請檢查 Service 的 svcneg 資源是否存在。如果是,請檢查 Initialized 條件,查看是否有任何錯誤資訊。
  • 如果您使用自訂 NEG 名稱,請確保每個 NEG 名稱在所屬區域中都是唯一的。

流量無法連上端點

症狀:502 錯誤或連線遭拒。

可能的解決方法:

  • 設定服務後,只要將新端點附加至 NEG,且端點會回應健康狀態檢查,通常就能連上這些端點。
  • 如果在這段時間過後,流量仍無法到達端點,導致 HTTP(S) 傳回 502 錯誤代碼,或 TCP/SSL 負載平衡器拒絕連線,請檢查下列事項:
    • 確認防火牆規則允許從下列範圍傳入端點的 TCP 流量:130.211.0.0/22 和 35.191.0.0/16。
    • 使用 Google Cloud CLI 或在 NEG 上呼叫 getHealthbackendService 的 listEndpoints API,並將 showHealth 參數設為 SHOW,確認端點是否正常運作。

停滯的推出作業

症狀:推出更新後的 Deployment 時停滯,且最新副本數量與所選副本數量不符。

可能的解決方法:

Deployment 的健康狀態檢查失敗。容器映像檔可能不正確,或健康狀態檢查設定有誤。Pod 的滾動替換作業會等待新啟動的 Pod 通過 Pod 準備就緒閘道。只有在 Pod 回應負載平衡器健康狀態檢查時,才會發生這種情況。如果 Pod 沒有回應,或健康狀態檢查設定錯誤,就無法滿足 readiness 閘道條件,推出作業也無法繼續。

  • 如果您使用 kubectl 1.13 以上版本,可以透過下列指令檢查 Pod readiness 閘的狀態:

    kubectl get my-Pod -o wide
    

    檢查 READINESS GATES 欄。

    kubectl 1.12 以下版本沒有這個資料欄。標示為「READY」狀態的 Pod 可能有失敗的就緒閘道。如要確認這一點,請使用下列指令:

    kubectl get my-pod -o yaml
    

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

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

  • 確認健康狀態檢查設定正確無誤。

NEG 不會進行垃圾收集

症狀:應已刪除的 NEG 仍存在。

可能的解決方法:

  • 如果後端服務參照 NEG,系統就不會進行垃圾收集。詳情請參閱「防止 NEG 外洩」。
  • 如果使用 1.18 以上版本,可以透過服務 neg 程序檢查 ServiceNetworkEndpointGroup 資源中的事件。
  • 確認服務是否仍需要 NEG。檢查與 NEG 相對應的服務svcneg 資源,並確認是否有 Service 註解。

NEG 未與服務同步

症狀:預期的 (Pod IP) 端點不存在於 NEG 中、NEG 未同步處理,或發生 Failed to sync NEG_NAME (will not retry): neg name NEG_NAME is already in use, found a custom named neg with an empty description 錯誤

可能的解決方法:

如果您使用 GKE 1.18 以上版本,請檢查 svcneg 資源,瞭解相關資訊:

  • 檢查 status.lastSyncTime 值,確認 NEG 最近是否已同步。
  • 檢查Synced條件,找出最近一次同步處理期間發生的任何錯誤。

如果您使用 GKE 1.19.9 以上版本,請檢查是否有 NEG 的名稱和區域,與 GKE NEG 控制器需要建立的 NEG 名稱和區域相符。舉例來說,您可能已在叢集可用區 (或其中一個叢集可用區) 中,使用 gcloud CLI 或 Google Cloud 控制台,建立 NEG 控制器需要使用的 NEG 名稱。在這種情況下,您必須先刪除現有 NEG,NEG 控制器才能同步處理端點。獨立 NEG 的建立和成員資格,都是由 NEG 控制器管理。

後續步驟