設定外部應用程式負載平衡器的 Ingress

本頁面說明如何建立 Kubernetes Ingress 物件,設定外部應用程式負載平衡器。

閱讀本頁內容前,請務必熟悉 GKE 網路概念。

事前準備

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

  • 啟用 Google Kubernetes Engine API。
  • 啟用 Google Kubernetes Engine API
  • 如要使用 Google Cloud CLI 執行這項工作,請安裝並初始化 gcloud CLI。如果您先前已安裝 gcloud CLI,請執行 gcloud components update 指令,取得最新版本。較舊的 gcloud CLI 版本可能不支援執行本文件中的指令。
  • 請確認您有現有的 Autopilot 或 Standard 叢集。如要建立新叢集,請參閱「建立 Autopilot 叢集」。

啟用 HttpLoadBalancing 外掛程式

叢集必須啟用 HttpLoadBalancing 外掛程式。這項外掛程式預設為啟用。在 Autopilot 叢集中,您無法停用這個外掛程式。

您可以使用 Google Cloud 控制台或 Google Cloud CLI 啟用 HttpLoadBalancing 外掛程式。

控制台

  1. 前往 Google Cloud 控制台的「Google Kubernetes Engine」頁面。

    前往「Google Kubernetes Engine」

  2. 按一下您要修改的叢集名稱。

  3. 在「Networking」(網路) 下方的「HTTP Load Balancing」(HTTP 負載平衡) 欄位中,按一下「Edit HTTP Load Balancing」(編輯 HTTP 負載平衡)。

  4. 勾選「啟用 HTTP 負載平衡」核取方塊。

  5. 按一下 [儲存變更]。

gcloud

gcloud container clusters update CLUSTER_NAME --update-addons=HttpLoadBalancing=ENABLED

將 CLUSTER_NAME 替換為叢集名稱。

建立靜態 IP 位址

外部應用程式負載平衡器會提供一個穩定的 IP 位址,您可以使用該位址將要求轉送至一或多項服務。如要使用永久 IP 位址,請務必先預留全域靜態外部 IP 位址,再建立 Ingress。

如果您修改現有 Ingress,改用靜態 IP 位址而非臨時 IP 位址,GKE 重新建立負載平衡器的轉送規則時,可能會變更負載平衡器的 IP 位址。

建立外部應用程式負載平衡器

在本練習中,您將設定外部應用程式負載平衡器,根據網址路徑將要求轉送至不同服務。


如要直接在 Google Cloud 控制台中,按照這項工作的逐步指南操作,請按一下「Guide me」(逐步引導):

逐步引導


建立 Deployment 和 Service

建立兩個 Deployment,並將 Service 命名為 hello-world-1 和 hello-world-2:

  1. 將下列資訊清單儲存為 hello-world-deployment-1.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello-world-deployment-1
    spec:
      selector:
        matchLabels:
          greeting: hello
          version: one
      replicas: 3
      template:
        metadata:
          labels:
            greeting: hello
            version: one
        spec:
          containers:
          - name: hello-app-1
            image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0"
            env:
            - name: "PORT"
              value: "50000"
    

    這個資訊清單描述了含有三個副本的 Deployment 範例。

  2. 將資訊清單套用至叢集:

    kubectl apply -f hello-world-deployment-1.yaml
    
  3. 將下列資訊清單儲存為 hello-world-service-1.yaml:

    apiVersion: v1
    kind: Service
    metadata:
      name: hello-world-1
    spec:
      type: NodePort
      selector:
        greeting: hello
        version: one
      ports:
      - protocol: TCP
        port: 60000
        targetPort: 50000
    

    這個資訊清單會說明具有下列屬性的 Service:

    • 任何具有 greeting: hello 標籤和 version: one 標籤的 Pod 都是 Service 的成員。
    • 當要求傳送至 TCP 通訊埠 60000 上的 Service 時,GKE 會將其轉送至 TCP 通訊埠 50000 上的其中一個成員 Pod。
    • 服務類型為 NodePort,除非使用容器原生負載平衡,否則這是必要條件。如果使用容器原生負載平衡,服務類型則不受限制,但除非您明確需要 NodePort 服務提供的 nodePort,否則建議您使用 type ClusterIP 服務。不支援將 LoadBalancer 服務做為 Ingress 後端。
  4. 將資訊清單套用至叢集:

    kubectl apply -f hello-world-service-1.yaml
    
  5. 將下列資訊清單儲存為 hello-world-deployment-2.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello-world-deployment-2
    spec:
      selector:
        matchLabels:
          greeting: hello
          version: two
      replicas: 3
      template:
        metadata:
          labels:
            greeting: hello
            version: two
        spec:
          containers:
          - name: hello-app-2
            image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
            env:
            - name: "PORT"
              value: "8080"
    

    這個資訊清單說明含有三個副本的範例 Deployment。

  6. 將資訊清單套用至叢集:

    kubectl apply -f hello-world-deployment-2.yaml
    
  7. 將下列資訊清單儲存為 hello-world-service-2.yaml:

    apiVersion: v1
    kind: Service
    metadata:
      name: hello-world-2
    spec:
      type: NodePort
      selector:
        greeting: hello
        version: two
      ports:
      - protocol: TCP
        port: 80
        targetPort: 8080
    

    這個資訊清單會說明具有下列屬性的 Service:

    • 任何具有 greeting: hello 標籤和 version: two 標籤的 Pod 都是 Service 的成員。
    • 當要求傳送至 TCP 通訊埠 80 上的 Service 時,GKE 會將其轉送至 TCP 通訊埠 8080 上的其中一個成員 Pod。
  8. 將資訊清單套用至叢集:

    kubectl apply -f hello-world-service-2.yaml
    

建立 Ingress

建立 Ingress,根據要求中的網址路徑指定要求轉送規則。建立 Ingress 時,GKE Ingress 控制器會建立並設定外部應用程式負載平衡器。

  1. 將下列資訊清單儲存為 my-ingress.yaml:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: my-ingress
      annotations:
        # If the class annotation is not specified it defaults to "gce".
        kubernetes.io/ingress.class: "gce"
    spec:
      rules:
      - http:
          paths:
          - path: /*
            pathType: ImplementationSpecific
            backend:
              service:
                name: hello-world-1
                port:
                  number: 60000
          - path: /v2
            pathType: ImplementationSpecific
            backend:
              service:
                name: hello-world-2
                port:
                  number: 80
    

    這份資訊清單說明具有下列屬性的 Ingress:

    • GKE Ingress 類別有兩種,如要指定 Ingress 類別,請使用 kubernetes.io/ingress.class 註解。您無法使用 spec.ingressClassName 指定 GKE Ingress。

    • gce 類別會部署外部應用程式負載平衡器。

    • gce-internal 類別會部署內部應用程式負載平衡器。

    • 部署不含 spec.ingressClassName 和 kubernetes.io/ingress.class 註解的 Ingress 資源時,GKE 會建立外部應用程式負載平衡器。如果您指定 kubernetes.io/ingress.class: gce 註解,也會發生相同行為。詳情請參閱「GKE Ingress 控制器行為」。

    • GKE 會為每個 backend.service 建立Google Cloud 後端服務。每個後端服務都對應至 Kubernetes 服務,且每個後端服務都必須參照Google Cloud 健康狀態檢查。這項健康狀態檢查不同於 Kubernetes 活躍性或完備性探測,因為健康狀態檢查是在叢集外部實作。詳情請參閱「健康狀態檢查」

    • 當用戶端傳送要求至網址路徑為 / 的負載平衡器時,GKE 會將要求轉送至通訊埠 60000 上的 hello-world-1 Service。當用戶端使用網址路徑 /v2 向負載平衡器傳送要求時,GKE 會將要求轉送至通訊埠 80 上的 hello-world-2 Service。如要進一步瞭解 path 和 pathType 屬性,請參閱「網址路徑」。

    • 如要預留全域靜態外部 IP 位址,請在 Ingress 物件中加入 kubernetes.io/ingress.global-static-ip-name 註解,如下所示:

     apiVersion: networking.k8s.io/v1
     kind: Ingress
     metadata:
       name: my-ingress
       annotations:
         kubernetes.io/ingress.global-static-ip-name: my-static-address
     ```
    
  2. 將資訊清單套用至叢集:

    kubectl apply -f my-ingress.yaml
    

測試外部應用程式負載平衡器

等待約五分鐘,讓系統設定負載平衡器,然後測試外部應用程式負載平衡器:

  1. 檢視 Ingress:

    kubectl get ingress my-ingress --output yaml
    

    輸出內容會顯示外部應用程式負載平衡器的 IP 位址:

    status:
      loadBalancer:
        ingress:
        - ip: 203.0.113.1
    
  2. 測試 / 路徑:

    curl LOAD_BALANCER_IP_ADDRESS/
    

    將 LOAD_BALANCER_IP_ADDRESS 改成負載平衡器的外部 IP 位址。

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

    Hello, world!
    Version: 1.0.0
    Hostname: ...
    

    如果輸出內容包含 404 錯誤,請稍候幾分鐘。

  3. 測試 /v2 路徑:

    curl load-balancer-ip/v2
    

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

    Hello, world!
    Version: 2.0.0
    Hostname: ...
    

外部負載平衡 Ingress 的運作方式

本節說明可為 GKE 應用程式啟用外部負載平衡的元件和設定,包括網址路徑比對、網路端點群組和 Shared VPC 整合。

網址路徑

Ingress 的 path 欄位唯一支援的萬用字元是 * 字元。* 字元必須接在正斜線 (/) 後方,且必須是模式中的最後一個字元。舉例來說,/*、/foo/* 和 /foo/bar/* 是有效模式,但 *、/foo/bar* 和 /foo/*/bar 則不是。

較明確的模式會優先於較不明確的模式。如果您同時擁有 /foo/* 和 /foo/bar/*,系統會將 /foo/bar/bat 視為與 /foo/bar/* 相符。如要進一步瞭解路徑限制和模式比對,請參閱「網址對應說明文件」。

如果 GKE 叢集執行的版本早於 1.21.3-gke.1600,pathType 欄位只支援 ImplementationSpecific 值。如果叢集執行 1.21.3-gke.1600 以上版本,pathType 也支援 Prefix 和 Exact 值。

網路端點群組

如果叢集支援容器原生負載平衡,建議您使用網路端點群組 (NEG)。建立 Ingress 時,GKE 會在專案中建立應用程式負載平衡器,並在叢集執行的每個可用區中建立 NEG。NEG 中的端點和服務的端點會保持同步。對於 1.17 以上版本的 GKE 叢集,在特定條件下,容器原生負載平衡功能為預設設定,不需要明確的 cloud.google.com/neg: '{"ingress": true}' 服務註解。如果叢集預設不使用 NEG,我們仍強烈建議您使用容器原生負載平衡,但必須針對每個服務明確啟用這項功能。請按照下列方式將註解套用至服務:

kind: Service
...
  annotations:
    cloud.google.com/neg: '{"ingress": true}'
...

新增這項註解時,系統會為現有服務建立新的 BackendService。這可能會導致服務暫時中斷。

Shared VPC

如果您要在服務專案中部署 Ingress 資源,並希望 GKE 控制平面管理主機專案中的防火牆資源,則必須按照「管理使用共用 VPC 的叢集防火牆資源」一文的說明,在主機專案中授予服務專案的 GKE 服務帳戶適當的 IAM 權限。這樣一來,Ingress 控制器就能建立防火牆規則,允許輸入流量和 Google Cloud 健康狀態檢查流量。

以下是 Ingress 資源記錄中可能出現的事件範例。如果權限設定不正確,Ingress 控制器無法建立防火牆規則,允許 Google Cloud 健康狀態檢查的輸入流量,就會發生這項錯誤。

Firewall change required by security admin: `gcloud compute firewall-rules update <RULE_NAME> --description "GCE L7 firewall rule" --allow tcp:<PORT> --source-ranges 130.211.0.0/22,35.191.0.0/16 --target-tags <TARGET_TAG> --project <HOST_PROJECT>

如果偏好從主機專案手動佈建防火牆規則,則可以將 networking.gke.io/suppress-firewall-xpn-error: "true" 註解新增至 Ingress 資源,藉此將 firewallXPNError 事件設為靜音。

外部 Ingress 註解摘要

您可以使用下列註解,設定外部 Ingress 資源和相關聯 Kubernetes Service 物件的行為。

Ingress 註解

註解 說明
kubernetes.io/ingress.allow-http 指定是否允許用戶端與 HTTP(S) 負載平衡器之間的 HTTP 流量。可能的值為「true」和「false」,預設值為「true」。請參閱「停用 HTTP」。
ingress.gcp.kubernetes.io/pre-shared-cert 使用這個註解,將憑證資源附加至 GKE Ingress 資源。詳情請參閱「使用外部應用程式負載平衡器時的多個 SSL 憑證」。
kubernetes.io/ingress.global-static-ip-name 使用這個註解,指定負載平衡器應使用您先前建立的靜態外部 IP 位址。請參閱「HTTP(S) 負載平衡器的靜態 IP 位址」。
networking.gke.io/v1beta1.FrontendConfig 使用這個註解,即可自訂負載平衡器的用戶端設定。詳情請參閱「輸入設定」。
networking.gke.io/suppress-firewall-xpn-error 如果是 Ingress 負載平衡器,當 Kubernetes 因權限不足而無法變更防火牆規則時,系統每隔幾分鐘就會建立 firewallXPNError 事件。在 GLBC 1.4 以上版本中,您可以將 networking.gke.io/suppress-firewall-xpn-error: "true" 註解新增至 Ingress 資源,藉此將 firewallXPNError 事件設為靜音。如要取消靜音,請移除這項註解。可能的值為 true 和 false。預設值為 false。
註解 說明
cloud.google.com/app-protocols 使用這個註解設定負載平衡器與應用程式之間的通訊協定。可能的通訊協定包括 HTTP、HTTPS 和 HTTP2。
cloud.google.com/backend-config 使用這個註解設定與 Service 相關聯的後端服務。詳情請參閱「輸入設定」。
cloud.google.com/neg 使用這項註解指定負載平衡器應使用網路端點群組。請參閱「使用容器原生負載平衡」。

後續步驟