保護 GKE Ingress 的流量

本頁面說明如何保護及最佳化 Google Kubernetes Engine (GKE) Ingress 的流量。您可以在用戶端和負載平衡器之間設定 SSL 憑證,並確保負載平衡器與後端應用程式之間的流量安全無虞。繼續操作前,請務必先瞭解 GKE 如何透過 HTTPS 保護 Ingress

本頁內容適用於網路專家,他們負責為機構設計及建構網路,並安裝、設定及支援網路設備。如要進一步瞭解我們在Google Cloud 內容中提及的常見角色和範例工作,請參閱「常見的 GKE 使用者角色和工作」。

保護並最佳化用戶端與負載平衡器之間的流量

如要接受來自用戶端的 HTTPS 要求,負載平衡器必須要有憑證,以向用戶端證明其身分。負載平衡器還必須要有私密金鑰才能完成 HTTPS 握手。如要進一步瞭解如何為 HTTP(S) 負載平衡器提供 SSL 憑證,請參閱設定用戶端與負載平衡器之間的 TLS

使用 Google 代管憑證

如要設定一或多個 Google 代管的 SSL 憑證,並將其與 Ingress 建立關聯,您需要:

  • 在與 Ingress 相同的命名空間中,建立一或多個 ManagedCertificate 物件。您最多可以為負載平衡器指定 15 個憑證
  • ManagedCertificate 物件與 Ingress 建立關聯,方法是將 networking.gke.io/managed-certificates 註解新增至 Ingress。這個註解是以半形逗號分隔的 ManagedCertificate 物件清單。

限制

本節將說明 Google 管理的憑證的限制。如果您必須使用自行管理憑證,或已具備要在 Ingress 上設定的 SSL 憑證,請參閱「在用戶端和負載平衡器之間設定 HTTPS (TLS)」。

  • 與您取得且自行管理的憑證相較,Google 代管憑證較不具彈性。Google 代管憑證最多支援 100 個非萬用字元網域。與自行管理的憑證不同,Google 代管憑證不支援萬用字元網域。

  • Ingress 支援的憑證數量和類型是由 Google 代管的 SSL 憑證限制所定義。

  • 系統不支援更新 Google 代管憑證。詳情請參閱「手動更新 Google 代管的憑證」。

  • 如果憑證是直接向憑證授權單位撤銷,Google 不會自動輪替憑證。您必須刪除 ManagedCertificate,然後建立新的憑證。

  • GKE Ingress 不支援由 Certificate Manager 管理的憑證。如要使用 Certificate Manager 管理的憑證,請使用 Gateway API

必要條件

  • 您必須擁有網域名稱,網域名稱的長度不得超過 63 個字元。您可以向任何網域名稱註冊商購買網域名稱。

  • 如果您使用 GKE Standard 叢集,則必須啟用 HttpLoadBalancing 外掛程式。

  • Ingress 資訊清單必須包含 kubernetes.io/ingress.class: "gce" 註解。系統不支援「ingressClassName」欄位。

  • 您必須在相同專案和命名空間中套用 IngressManagedCertificate 資源。

  • 建立保留 (靜態) 外部 IP 位址。即使您刪除 Ingress,保留靜態 IP 位址可確保您持續擁有該位址。如果您沒有保留 IP 位址,位址可能會有所異動,導致您必須重新設定網域的 DNS 記錄。使用 Google Cloud CLI 或 Google Cloud 控制台建立保留 IP 位址。

    gcloud

    如要建立保留的 IP 位址,請執行下列指令:

    gcloud compute addresses create ADDRESS_NAME --global
    

    ADDRESS_NAME 替換為您要建立的預留 IP 位址名稱。

    如要找出您建立的靜態 IP 位址,請執行下列指令:

    gcloud compute addresses describe ADDRESS_NAME --global
    

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

    address: 203.0.113.32
    ...
    

    控制台

    如要建立保留 IP 位址,請執行下列步驟:

    1. 前往 Google Cloud 控制台的「External IP addresses」(外部 IP 位址) 頁面。

      前往「External IP Addresses」(外部 IP 位址)

    2. 為 IP 位址指定名稱 (例如 example-ip-address)。

    3. 指定要使用 IPv4IPv6 位址。

    4. 在「Type」(類型) 欄位選取「Global」(全域) 選項

    5. 按一下「預訂」。 IP 位址會列在「External Address」(外部位址) 欄位中。

    設定連接器

    附註:此步驟需要使用設定連接器。請按照安裝操作說明在叢集上安裝設定連接器。

    apiVersion: compute.cnrm.cloud.google.com/v1beta1
    kind: ComputeAddress
    metadata:
      name: example-ip-address
    spec:
      location: global
    如要部署此資訊清單,請以 compute-address.yaml 格式將其下載至您的電腦,並執行下列指令:

    kubectl apply -f compute-address.yaml
    

設定 Google 代管憑證

  1. 建立 ManagedCertificate 物件。該資源可以指定 SSL 憑證的網域。系統不支援萬用字元網域。

    下列資訊清單說明 ManagedCertificate 物件。將資訊清單儲存為 managed-cert.yaml

    apiVersion: networking.gke.io/v1
    kind: ManagedCertificate
    metadata:
      name: FIRST_CERT_NAME
    spec:
      domains:
        - FIRST_DOMAIN
    ---
    apiVersion: networking.gke.io/v1
    kind: ManagedCertificate
    metadata:
      name: SECOND_CERT_NAME
    spec:
      domains:
        - SECOND_DOMAIN
    

    更改下列內容:

    • FIRST_CERT_NAME:第一個 ManagedCertificate 物件的名稱。
    • FIRST_DOMAIN:您擁有的第一個網域。
    • SECOND_CERT_NAME:第二個 ManagedCertificate 物件的名稱。
    • SECOND_DOMAIN:您擁有的第二個網域。

    ManagedCertificate 物件的名稱與實際建立的憑證名稱不同。您只需要知道 ManagedCertificate 物件的名稱,即可在 Ingress 中使用這些物件。

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

    kubectl apply -f managed-cert.yaml
    
  3. 按照操作說明建立 Deployment 和 Service,將應用程式公開發布到網際網路。

  4. 如要讓這個 ManagedCertificate 物件成為 Active,請使用 networking.gke.io/managed-certificates 註解將其附加至 Ingress,如下列範例所示。您不必先Active ManagedCertificate,即可將其附加至 Ingress。

     apiVersion: networking.k8s.io/v1
     kind: Ingress
     metadata:
       name: my-gmc-ingress
       annotations:
         networking.gke.io/managed-certificates: "FIRST_CERT_NAME,SECOND_CERT_NAME"
     spec:
       rules:
       - host: FIRST_DOMAIN
         http:
           paths:
           - pathType: ImplementationSpecific
             backend:
               service:
                 name: my-mc-service
                 port:
                   number: 60001
       - host: SECOND_DOMAIN
         http:
           paths:
           - pathType: ImplementationSpecific
             backend:
               service:
                 name: my-mc-service
                 port:
                   number: 60002
     ```
    
    Replace <code><var>FIRST_DOMAIN</var></code> and
    <code><var>SECOND_DOMAIN</var></code> with your domain names.
    
    This manifest describes an Ingress that lists pre-shared certificate
    resources in an annotation.
    
    Note: It might take several hours for Google Cloud to provision the load
    balancer and the managed certificates, and for the load balancer to begin
    using the new certificates. For more information, see
    [Deploy a Google-managed certificate with load balancer authorization](/certificate-manager/docs/deploy-google-managed-lb-auth#wait_until_the_certificate_has_been_activated).
    
  5. 等待 Google 代管憑證完成佈建。這項作業最多可能需要 60 分鐘。您可以使用下列指令檢查憑證狀態:

    kubectl describe managedcertificate managed-cert
    

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

    Name:         managed-cert
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    API Version:  networking.gke.io/v1
    Kind:         ManagedCertificate
    (...)
    Spec:
     Domains:
       FQDN_1
       FQDN_2
    Status:
     CertificateStatus: Active
    (...)
    

    Status.CertificateStatus 欄位的值表示已佈建憑證。如果 Status.CertificateStatus 不是 Active,表示憑證尚未佈建。

  6. 使用 https:// 前置字串造訪您的網域,驗證 SSL 是否運作正常。此時瀏覽器會顯示連線是否安全,並供您查看憑證的詳細資料。

從自行管理憑證遷移至 Google 代管憑證

如果要將 Ingress 從使用自行管理的 SSL 憑證遷移至使用 Google 代管的 SSL 憑證,請勿在 Google 代管的 SSL 憑證啟用前,刪除任何自行管理的 SSL 憑證。Google 代管 SSL 憑證佈建完畢後,便會自動啟用。Google 代管 SSL 憑證啟用後,您就可以刪除自行管理 SSL 憑證。

請按照以下操作說明,從自行管理 SSL 憑證遷移至 Google 代管 SSL 憑證。

  1. 如上一節所述,將新的 Google 管理憑證新增至 Ingress。
  2. 等待 Google 代管憑證資源狀態顯示為 Active。 使用下列指令檢查憑證狀態:

    kubectl describe managedcertificate managed-cert
    
  3. 狀態顯示為 Active 時,請更新 Ingress,以移除對自行管理憑證的參照。

移除 Google 代管憑證

如要移除叢集中的 Google 代管憑證,您必須刪除 ManagedCertificate 物件,並移除參照該物件的 Ingress 註解。

  1. 刪除 ManagedCertificate 物件:

    kubectl delete -f managed-cert.yaml
    

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

    managedcertificate.networking.gke.io "managed-cert" deleted
    
  2. 移除 Ingress 中的註解:

    kubectl annotate ingress managed-cert-ingress networking.gke.io/managed-certificates-
    

    注意指令結尾的減號「-」。-

  3. 釋出您為負載平衡器保留的靜態 IP 位址。

    您可以使用 Google Cloud CLI、 Google Cloud 控制台或 Config Connector,釋出保留的 IP 位址。

    gcloud

    使用下列指令釋出保留的 IP 位址:

    gcloud compute addresses delete ADDRESS_NAME --global
    

    ADDRESS_NAME 替換為 IP 位址名稱。

    控制台

    如要釋出保留的 IP 位址,請按照下列步驟操作:

    1. 前往 Google Cloud 控制台的「External IP addresses」(外部 IP 位址) 頁面。

      前往「External IP Addresses」(外部 IP 位址)

    2. 找出要釋放的 IP 位址,然後選取旁邊的核取方塊。

    3. 按一下 [Release IP address] (釋出 IP 位址)

    設定連接器

    附註:此步驟需要使用設定連接器。請按照安裝操作說明在叢集上安裝設定連接器。

    apiVersion: compute.cnrm.cloud.google.com/v1beta1
    kind: ComputeAddress
    metadata:
      name: example-ip-address
    spec:
      location: global

    如要部署此資訊清單,請以 compute-address.yaml 格式將其下載至您的電腦,並執行下列指令:

    kubectl delete -f compute-address.yaml
    

建立憑證和金鑰

如要使用預先共用的憑證或 Kubernetes 密鑰,您必須先取得一或多個憑證,以及對應的私密金鑰。每一個憑證都必須有一個與您所擁有的網域相等的共用名稱 (CN)。若您已有具備適當的「共用名稱」值的兩個憑證檔案,可直接前往下一節。

  1. 建立第一個金鑰:

    openssl genrsa -out test-ingress-1.key 2048
    
  2. 建立第一個憑證簽署要求:

    openssl req -new -key test-ingress-1.key -out test-ingress-1.csr \
        -subj "/CN=FIRST_DOMAIN"
    

    FIRST_DOMAIN 替換為您擁有的網域名稱,例如 example.com

  3. 建立第一個憑證:

    openssl x509 -req -days 365 -in test-ingress-1.csr -signkey test-ingress-1.key \
        -out test-ingress-1.crt
    
  4. 建立第二個金鑰:

    openssl genrsa -out test-ingress-2.key 2048
    
  5. 建立第二個憑證簽署要求:

    openssl req -new -key test-ingress-2.key -out test-ingress-2.csr \
        -subj "/CN=SECOND_DOMAIN"
    

    SECOND_DOMAIN 替換成您擁有的其他網域名稱,例如 examplepetstore.com

  6. 建立第二個憑證:

    openssl x509 -req -days 365 -in test-ingress-2.csr -signkey test-ingress-2.key \
        -out test-ingress-2.crt
    

如要進一步瞭解憑證和金鑰,請參閱「SSL 憑證總覽」一文。

您現在有兩個憑證檔案和兩個金鑰檔案。

其餘工作會使用下列預留位置來參照您的網域、憑證和金鑰:

  • FIRST_CERT_FILE:第一個憑證檔案的路徑。
  • FIRST_KEY_FILE:與第一個憑證搭配使用的金鑰檔案路徑。
  • FIRST_DOMAIN:您擁有的網域名稱。
  • FIRST_SECRET_NAME:包含第一個憑證和金鑰的 Secret 名稱。
  • SECOND_CERT_FILE:第二個憑證檔案的路徑。
  • SECOND_KEY_FILE:與第二個憑證搭配使用的金鑰檔案路徑。
  • SECOND_DOMAIN:您擁有的第二個網域名稱。
  • SECOND_SECRET_NAME:包含第二個憑證和金鑰的 Secret 名稱。

使用預先共用的憑證

您可以上傳自行管理的 SSL 憑證至專案。 Google Cloud 這類憑證稱為預先共用憑證。您可以為 Ingress 指定一或多個預先共用的憑證。

如要使用多個預先共用的憑證,請按照下列步驟操作:

  1. 為每個憑證和金鑰組在 Google Cloud中建立公開顯示的 SSL 憑證資源。

     gcloud compute ssl-certificates create FIRST_CERT_NAME \
         --certificate=FIRST_CERT_FILE \
         --private-key=FIRST_KEY_FILE
     ```
    
    ```sh
     gcloud compute ssl-certificates create SECOND_CERT_NAME \
         --certificate=SECOND_CERT_FILE \
         --private-key=SECOND_KEY_FILE
     ```
    
    Replace the following:
    
    • FIRST_CERT_NAMESECOND_CERT_NAME:第一個和第二個憑證的名稱。
    • FIRST_CERT_FILESECOND_CERT_FILE:您的第一和第二個憑證檔案
    • FIRST_KEY_FILE:第一個和第二個金鑰檔案。SECOND_KEY_FILE
  2. 在 Ingress 資訊清單中,新增 ingress.gcp.kubernetes.io/pre-shared-cert 註解。註解值是以半形逗號分隔的憑證名稱清單。此外,在 spec.rules 區段中,請加入 host 欄位,指定服務的網域。

     apiVersion: networking.k8s.io/v1
     kind: Ingress
     metadata:
       name: my-psc-ingress
       annotations:
         ingress.gcp.kubernetes.io/pre-shared-cert: "FIRST_CERT_NAME,SECOND_CERT_NAME"
     spec:
       rules:
       - host: FIRST_DOMAIN
         http:
           paths:
           - pathType: ImplementationSpecific
             backend:
               service:
                 name: my-mc-service
                 port:
                   number: 60001
       - host: SECOND_DOMAIN
         http:
           paths:
           - pathType: ImplementationSpecific
             backend:
               service:
                 name: my-mc-service
                 port:
                   number: 60002
     ```
    
    Replace <code><var>FIRST_DOMAIN</var></code> and
    <code><var>SECOND_DOMAIN</var></code> with your domain names.
    
    This manifest describes an Ingress that lists pre-shared certificate
    resources in an annotation.
    

使用 Kubernetes Secret

如要向 HTTP(S) 負載平衡器提供您自行建立的憑證與金鑰,請建立一或多個 Kubernetes 密鑰物件。每個 Secret 都包含憑證和金鑰。將密鑰新增至 Ingress 資訊清單的 tls 欄位。負載平衡器會使用伺服器名稱指示 (SNI),依據 TLS 握手中的網域名稱判斷要向客戶呈現哪些憑證。

如要使用多個憑證,請按照下列步驟操作:

  1. 為每個憑證和金鑰組建立密鑰:

     kubectl create secret tls FIRST_SECRET_NAME \
         --cert=FIRST_CERT_FILE \
         --key=FIRST_KEY_FILE
     ```
    
    ```sh
     kubectl create secret tls SECOND_SECRET_NAME \
         --cert=SECOND_CERT_FILE \
         --key=SECOND_KEY_FILE
     ```
    
  2. 在 Ingress 資訊清單的 spec.tls 區段中,列出您建立的 Secret。此外,在 spec.rules 區段中,請加入 host 欄位,指定服務的網域。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: my-mc-ingress
    spec:
      tls:
      - secretName: FIRST_SECRET_NAME
      - secretName: SECOND_SECRET_NAME
      rules:
      - host: FIRST_DOMAIN
        http:
          paths:
          - pathType: ImplementationSpecific
            backend:
              service:
                name: my-mc-service
                port:
                  number: 60001
      - host: SECOND_DOMAIN
        http:
          paths:
          - pathType: ImplementationSpecific
            backend:
              service:
                name: my-mc-service
                port:
                  number: 60002
    

    FIRST_DOMAINSECOND_DOMAIN 替換為您擁有的網域名稱,例如 example.comexamplepetstore.com

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

如要保護 GKE 叢集的 HTTPS 加密 Ingress,請參閱安全 Ingress 範例。

停用 HTTP

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

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress-2
  annotations:
    kubernetes.io/ingress.allow-http: "false"
spec:
  tls:
  - secretName: SECRET_NAME
  ...

這個資訊清單包含您建立的 Secret 名稱 SECRET_NAME

外部應用程式負載平衡器完成程式設計後,您才能更新 Ingress 並新增註解 kubernetes.io/ingress.allow-http: false

用戶端和負載平衡器之間的 HTTP/2

用戶端可以使用 HTTP/2 向負載平衡器傳送要求,您無需再進行設定。

確保負載平衡器與應用程式之間的流量安全無虞,並進行最佳化

您可以設定負載平衡器與應用程式 Pod 之間的通訊協定,確保端對端安全或提升內部流量效能。負載平衡器預設會使用未加密的 HTTP/1.1 進行後端連線,但您可以啟用 HTTPS 或 HTTP/2,以符合應用程式的特定需求。

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

如果您在 GKE pod 中執行的應用程式能接收 HTTPS 要求,您可以將負載平衡器設為將要求轉送到您的應用程式時使用 HTTPS。若須更多訊息,請參閱負載平衡器和應用程式之間的 HTTPS (TLS)

如要設定負載平衡器與應用程式之間所使用的通訊協定,請在 Service 資訊清單中使用 cloud.google.com/app-protocols 註解。 除非您使用容器原生負載平衡,否則這項服務資訊清單必須包含 type: NodePort。如果您使用容器原生負載平衡,請使用 type: ClusterIP

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

服務資訊清單必須在連接埠註解中包含 name 值。您只能參照指派的 name 編輯服務通訊埠,無法透過 targetPort 值編輯。

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

在負載平衡器和應用程式之間使用 HTTP/2

如果您在 GKE pod 中執行的應用程式能接收 HTTP/2 要求,您可以將負載平衡器設為將要求轉送到您的應用程式時使用 HTTP/2。

如要啟用 HTTP/2,您必須在 Kubernetes Service 清單中使用 cloud.google.com/app-protocols 註解。這項註解會指定負載平衡器用來與應用程式通訊的通訊協定。為確保負載平衡器向後端發出正確的 HTTP/2 要求,後端必須設定 SSL。

以下是為 HTTP/2 設定的服務資訊清單範例:

apiVersion: v1
kind: Service
metadata:
  name: my-http2-service
  annotations:
    cloud.google.com/app-protocols: '{"my-port":"HTTP2"}'
spec:
  type: NodePort
  selector:
    app: my-app
  ports:
  - name: my-port
    protocol: TCP
    port: 443
    targetPort: 8443

注意事項:

  • cloud.google.com/app-protocols 註解設為 '{"my-port":"HTTP2"}',指示負載平衡器對傳送至名為 my-port 的通訊埠的流量使用 HTTP/2。
  • 通訊埠設為 443,並將流量導向 targetPort 8443 上的 Pod。