使用 Ingress 執行 HTTP(S) 負載平衡

在 Google Kubernetes Engine 中,Ingress 物件定義了將外部 HTTP(S) 流量轉送至叢集中執行的應用程式的規則。Ingress 物件會與一或多個 Service 物件關聯,每個 Service 物件會再與一組 pod 關聯。

建立 Ingress 物件時,GKE 輸入控制器會根據 Ingress 中的資訊及相關聯的 Service 建立 Google Cloud Platform HTTP(S) 負載平衡器,並進行設定。

HTTP(S) 負載平衡的功能

Ingress 設定的 HTTP(S) 負載平衡包括以下功能:

彈性的 Service 設定
Ingress 定義流量如何到達您的 Service,以及流量如何轉送到您的應用程式。此外,Ingress 可以為叢集中的多個 Service 提供單一 IP 位址。
與 GCP 網路服務整合
Ingress 可以設定 GCP 功能,例如 Google 代管的 SSL 憑證 (Beta 版)Cloud ArmorCloud CDN 以及 Cloud Identity-Aware Proxy
支援多個傳輸層安全標準 (TLS) 憑證
Ingress 可以指定使用多個傳輸層安全標準 (TLS) 憑證來要求終止。

如要進一步瞭解這些功能,請參閱 HTTP(S) 負載平衡概念

提供 SSL 憑證的方法

有三種方法可以將 SSL 憑證提供給 HTTPS 負載平衡器:

Google 代管憑證
系統會針對您的網域佈建、配置、更新及代管 Google 代管的 SSL 憑證。代管憑證不支援使用萬用字元網域或多個主體別名 (SAN)
與 GCP 共用的自行管理憑證
您可以佈建自己的 SSL 憑證,並在 GCP 專案建立憑證資源。接著,您就可以在 Ingress 上的註解中列出憑證資源,以建立使用該憑證的 HTTP(S) 負載平衡器。詳情請參閱預先共用憑證的操作說明
將自行管理憑證做為密鑰資源
您可以佈建自己的 SSL 憑證,並建立密鑰來保存憑證。接著,您就可以參閱 Ingress 規範中的密鑰,以建立使用憑證的 HTTP(S) 負載平衡器。詳情請參閱在密鑰中使用憑證的操作說明

限制

命名空間的總長度和 Ingress 的名稱不得超過 55 個字元。若未遵照本指南執行,可能導致 GKE 輸入控制器異常。詳情請參閱此問題

網址對應的最大規則數為 50。這代表您可以在 Ingress 中指定最多 50 個規則。

如果使用 GKE 輸入控制器,則叢集的節點數不能超過 1000 個。

要使 GKE 輸入控制器使用 readinessProbes 作為健康狀況檢查,則 Ingress 的 Pod 必須在 Ingress 建立時存在。如果您的複本縮放為 0,則將套用預設的健康狀況檢查。詳情請參閱此問題評論

Pod 的 readinessProbe 變更,在 Ingress 建立後便不會對其造成影響。

多項後端服務

HTTP(S) 負載平衡器提供穩定的 IP 位址,用來將要求轉送到各種後端服務。

舉例來說,您可以設定負載平衡器,使其根據 URL 路徑,將請求轉送到不同的後端服務。傳送到 your-store.example 的要求可以轉送到顯示原價商品的後端服務,傳送到 your-store.example/discount 的要求可以轉送到顯示折扣商品的後端服務。

您也可以設定負載平衡器,根據主機名稱來轉送要求,讓傳送到 your-store.example 的要求前往某個後端服務,而傳送到 your-experimental-store.example 的要求前往另一個後端服務。

在 GKE 叢集中,您可以透過建立 Kubernetes Ingress 物件,來建立和設定 HTTP(S) 負載平衡器。Ingress 物件必須與一或多個 Service 物件關聯,而每個 Service 物件都會與一組 pod 關聯。

以下是 Ingress 的資訊清單:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: my-products
          servicePort: 60000
      - path: /discounted
        backend:
          serviceName: my-discounted-products
          servicePort: 80

建立 Ingress 時,GKE 輸入控制器會根據 Ingress 和關聯的 Service 中的資訊,建立和設定 HTTP(S) 負載平衡器。同時,系統會給負載平衡器一個穩定的 IP 位址,以與網域名稱建立關聯。

上述範例假設您已將負載平衡器的 IP 位址與網域名稱 your-store.example 關聯。要求由用戶端傳送至 your-store.example 後,會轉送至通訊埠 60000 上名為 my-products 的 Kubernetes Service。要求由用戶端傳送至 your-store.example/discounted 後,會轉送至通訊埠 80 上名為 my-discounted-products 的 Kubernetes Service。

Ingress 的 path 欄位僅支援 * 字元做為萬用字元。* 字元必須在正斜線 (/) 之後,並且必須是模式中的最後一個字元。例如,/*/foo/*/foo/bar/* 為有效模式,而 *、/foo/bar* 及 /foo/*/bar 則是無效的模式。

較明確的模式會優先於較不明確的模式。如果您同時有 /foo/*/foo/bar/*,系統會使用 /foo/bar/bat 來比對 /foo/bar/*

如要進一步瞭解路徑限制和模式比對,請參閱網址對應說明文件

my-products Service 的資訊清單看起來可能像這樣:

apiVersion: v1
kind: Service
metadata:
  name: my-products
spec:
  type: NodePort
  selector:
    app: products
    department: sales
  ports:
  - protocol: TCP
    port: 60000
    targetPort: 50000

在 Service 資訊清單中,請注意 typeNodePort。如要使用 Ingress 設定 HTTP(S) 負載平衡器,則必須設定這個類型。

在 Service 資訊清單中,selector 欄位表示同時具有 app: products 標籤與 department: sales 標籤的任何 pod 都是這個 Service 的成員。

當要求傳入通訊埠 60000 上的 Service 時,會轉送至在 TCP 通訊埠 50000 上的其中一個成員 pod。

請注意,每個成員 pod 都必須有監聽 TCP 通訊埠 50000 的容器。

my-discounted-products Service 的資訊清單看起來可能像這樣:

apiVersion: v1
kind: Service
metadata:
  name: my-discounted-products
spec:
  type: NodePort
  selector:
    app: discounted-products
    department: sales
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

在 Service 資訊清單中,selector 欄位表示同時具有 app: discounted-products 標籤與 department: sales 標籤的任何 pod 都是這個 Service 的成員。

當要求傳入在通訊埠 80 上的 Service 時,會轉送至在 TCP 通訊埠 8080 上的其中一個成員 pod。

請注意,每個成員 Pod 都必須有監聽 TCP 通訊埠 8080 的容器。

預設後端

在 Ingress 資訊清單中提供 backend 欄位,即可指定預設後端。只要任何要求不符合 rules 欄位中的路徑,就會傳送到 backend 欄位中指定的 Service 和通訊埠。例如,在下面的 Ingress 中,所有不符合 //discounted 的要求都會傳送到通訊埠 60001 上名為 my-products 的 Service。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  backend:
    serviceName: my-products
    servicePort: 60001
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: my-products
          servicePort: 60000
      - path: /discounted
        backend:
          serviceName: my-discounted-products
          servicePort: 80

如果您沒有指定預設後端,GKE 便會提供傳回 404 的預設後端。

健康狀態檢查

透過 Ingress 公開的服務必須回應來自負載平衡器的健康狀態檢查。作為負載平衡流量最終目標的任何容器,都必須執行以下操作之一以顯示其狀態為健康:

  • 以 HTTP 200 狀態向 / 路徑上的 GET 要求提供回應。

  • 設定 HTTP 就緒探測器。在就緒探測器指定的 path 上為 HTTP 要求提供 HTTP 200 狀態的回應。請注意,透過 Ingress 公開的服務,必須指向啟用就緒探測器的同一容器通訊埠。

    例如,假設一個容器指定了此就緒探測器:

    ...
    readinessProbe:
      httpGet:
        path: /healthy
    

    然後,如果容器的 /healthy 路徑處理程序傳回 HTTP 200 狀態,則負載平衡器會認為容器是運作中且健康的。

比較 Kubernetes Service 與 GCP 後端服務

Kubernetes ServiceGCP 後端服務不同。兩者之間有很強的關係,但這種關係不一定是一對一的。GKE 輸入控制器為 Ingress 資訊清單中的每對 (serviceNameservicePort) 建立 GCP 後端服務。因此,一個 Kubernetes Service 物件可能與多個 GCP 後端服務相關。

支援 GCP 功能

您可以使用 BackendConfig 設定 HTTP(S) 負載平衡器,以使用 Cloud ArmorCloud CDNCloud IAP 等功能。

BackendConfig 為自訂資源,用來保存 GCP 功能的設定資訊。

Ingress 資訊清單會參照到 Service,而 Service 資訊清單則透過 beta.cloud.google.com/backend-config 註解參照到 BackendConfig。

...
kind: Ingress
...
spec:
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: my-service
          servicePort: 80
...

kind: Service
metadata:
  name: my-service
  ...
  annotations:
    beta.cloud.google.com/backend-config: '{"ports": {"80":"my-backend-config"}}'
spec:
  type: NodePort
  ...
 

WebSocket 的支援

使用 HTTP(S) 負載平衡,WebSocket 通訊協定才有效。您無需再進行設定。

如果您打算使用 WebSocket 通訊協定,則可能需要使用大於預設值 30 秒的逾時值。若要為透過 Ingress 設定的後端服務設定逾時值,請建立 BackendConfig 物件,並在 Service 資訊清單中使用 beta.cloud.google.com/backend-config 註解。

詳情請參閱透過輸入設定後端服務

HTTP(S) 負載平衡器的靜態 IP 位址

建立 Ingress 物件時,您會取得一個穩定的外部 IP 位址,用戶端可以使用該位址存取您的 Service,並存取您正在執行的容器。這個 IP 位址在 Ingress 物件的整個生命週期中會持續存在,因此可說是相當穩定。刪除 Ingress 再從同一份資訊清單檔案建立新的 Ingress,並不能保證會獲得相同的外部 IP 位址。

如果您想在刪除 Ingress 後再建立新的 Ingress 時,IP 位址都能保持不變 (永久 IP 位址),則必須保留一個全域靜態外部 IP 位址,然後在您的Ingress 資訊清單中加入一個註解,提供您保留的靜態 IP 位址名稱。

例如,假設您保留了一個名為 my-static-address 的全域靜態外部 IP 位址。在您的 Ingress 資訊清單中,請加入一個 kubernetes.io/ingress.global-static-ip-name 註解,如下所示:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: my-static-address

如要深入瞭解如何為 Ingress 建立靜態外部 IP 位址,請參閱設定靜態 IP 位址以及使用靜態 IP 位址設定網域名稱

在用戶端和負載平衡器之間設定 HTTPS (TLS)

HTTP(S) 負載平衡器是用戶端與應用程式間的 Proxy。如果要接受來自用戶端的 HTTPS 要求,負載平衡器必須要有憑證,以向用戶端證明其身分。負載平衡器還必須要有私密金鑰才能完成 HTTPS 握手。

當負載平衡器接受來自用戶端的 HTTPS 要求時,用戶端和負載平衡器之間的流量將會使用 TLS 加密。不過負載平衡器會終止 TLS 加密,並將要求在不加密的情況下轉給應用程式。要瞭解如何加密負載平衡器與應用程式之間的流量,請參閱負載平衡器與應用程式之間的 HTTPS

您可以選擇使用 Google 代管的 SSL 憑證 (Beta 版),或使用您自行管理的憑證。如要進一步瞭解如何建立使用 Google 代管憑證的 Ingress,請參閱使用 Google 代管的 SSL 憑證 (Beta 版)

如要向 HTTP(S) 負載平衡器提供您自行建立的憑證與金鑰,您可以在 Ingress 資訊清單的 tls 欄位中指定 Kubernetes 密鑰的名稱。您之前建立的密鑰包含了憑證與金鑰。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress-2
spec:
  tls:
  - secretName: my-secret
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: my-metrics
          servicePort: 60000

對密鑰的變更會定期選取,因此如果您修改了密鑰內部的資料,則最多需要 10 分鐘才能將這些變更套用於負載平衡器。

要進一步瞭解如何使用密鑰來提供憑證給負載平衡器,請參閱使用 Ingress 在 HTTP(S) 負載平衡中使用多個安全資料傳輸層 (SSL) 憑證

停用 HTTP

如果您希望用戶端和 HTTP(S) 負載平衡器之間的所有流量都使用 HTTPS,則可以透過在 Ingress 資訊清單中包含 kubernetes.io/ingress.allow-http 註解來停用 HTTP。將註解的值設定為 "false"

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress-2
  annotations:
    kubernetes.io/ingress.allow-http: "false"
spec:
  tls:
  - secretName: my-secret
  ...

負載平衡器的預先共用憑證

除了使用 Kubernetes 密鑰為負載平衡器提供憑證以終止 HTTP(S),您也可以使用之前上傳至 GCP 專案的憑證。詳情請參閱使用預先共用憑證以及使用 Ingress 在 HTTP(S) 負載平衡中使用多個 SSL 憑證

負載平衡器與應用程式之間的 HTTPS (TLS)

HTTP(S) 負載平衡器是用戶端與應用程式間的 Proxy。用戶端可以使用 HTTP 或 HTTPS 與負載平衡器的 Proxy 進行通訊。但是,負載平衡器 Proxy 與應用程式間的連結預設使用 HTTP。如果您在 GKE pod 中執行的應用程式能接收 HTTPS 要求,您可以將負載平衡器設為將要求轉送到您的應用程式時使用 HTTPS。

如要設定負載平衡器與應用程式之間所使用的通訊協定,請在 Service 資訊清單中使用 cloud.google.com/app-protocols 註解。

以下 Service 資訊清單指定了兩個通訊埠。註解表示當 HTTP(S) 負載平衡器指定 Service 的通訊埠 80 時,應該使用 HTTP。當負載平衡器指定 Service 的通訊埠 443 時,則應該使用 HTTPS。

apiVersion: v1
kind: Service
metadata:
  name: my-service-3
  annotations:
    cloud.google.com/app-protocols: '{"my-https-port":"HTTPS","my-http-port":"HTTP"}'
spec:
  type: NodePort
  selector:
    app: metrics
    department: sales
  ports:
  - name: my-https-port
    port: 443
    targetPort: 8443
  - name: my-http-port
    port: 80
    targetPort: 50001

cloud.google.com/app-protocols 註解與先前的 service.alpha.kubernetes.io/app-protocols 註解具有相同的用途。新舊註解的名稱可以共存,如以下 Service 資訊清單中所示。當兩個註解出現在同一個 Service 資訊清單中時,以 service.alpha.kubernetes.io/app-protocols 為優先。

apiVersion: v1
kind: Service
metadata:
  name: my-service-3
  annotations:
    cloud.google.com/app-protocols: '{"my-https-port":"HTTPS","my-http-port":"HTTP"}'
    service.alpha.kubernetes.io/app-protocols: '{"my-first-port":"HTTPS","my-second-port":"HTTP"}'
spec:
  type: NodePort
  selector:
    app: metrics
    department: sales
  ports:
  - name: my-first-port
    port: 443
    targetPort: 8443
  - name: my-second-port
    port: 80
    targetPort: 50001

使用多個 TLS 憑證

假設您希望 HTTP(S) 負載平衡器提供 your-store.example 和 your-experimental-store.example 這兩個主機名稱的內容。此外,您希望負載平衡器在 your-store.example 與 your-experimental-store.example 使用不同的憑證。

您可以在 Ingress 資訊清單中指定多個憑證,如果憑證中的一般名稱 (CN) 與要求中使用的主機名稱相符,負載平衡器則會選擇該憑證。有關如何設定多個憑證的詳細訊息,請參閱使用 Ingress 在 HTTP(S) 負載平衡中使用多個安全資料傳輸層 (SSL) 憑證

後續步驟

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

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

這個網頁
Kubernetes Engine 說明文件