確保 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 建立關聯,方法是在 Ingress 中新增 networking.gke.io/managed-certificates 註解。這項註解是以半形逗號分隔的 ManagedCertificate 物件清單。

限制

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

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

  • 輸入支援的憑證數量和類型,取決於 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」欄位。

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

  • 建立預留 (靜態) 外部 IP 位址。預留靜態 IP 位址可確保該位址歸您所有,即使刪除 Ingress 也不會受到影響。如果未保留 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. 指定要使用 IPv4 或 IPv6 位址。

    4. 在「類型」中選取「全域」。

    5. 按一下「保留」。 IP 位址會列在「外部位址」欄中。

    Config Connector

    注意:這個步驟需要 Config Connector。按照安裝操作說明,在叢集上安裝 Config Connector。

    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 FIRST_DOMAIN and
    <code>SECOND_DOMAIN 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:       
    Annotations:  
    API Version:  networking.gke.io/v1
    Kind:         ManagedCertificate
    (...)
    Spec:
     Domains:
       FQDN_1
       FQDN_2
    Status:
     CertificateStatus: Active
    (...)
    

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

  6. 如要確認 SSL 是否正常運作,請使用 https:// 前置字元造訪網域。瀏覽器會指出連線安全無虞,且您可以查看憑證詳細資料。

從自行管理憑證遷移至 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 位址)。

    Config Connector

    注意:這個步驟需要 Config Connector。按照安裝操作說明,在叢集上安裝 Config Connector。

    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 Secret,您必須先有一或多個憑證,以及對應的私密金鑰。每張憑證都必須有與您擁有的網域名稱相等的通用名稱 (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_NAME、SECOND_CERT_NAME:第一個和第二個憑證的名稱。
    • FIRST_CERT_FILE、SECOND_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 FIRST_DOMAIN and
    <code>SECOND_DOMAIN with your domain names.
    
    This manifest describes an Ingress that lists pre-shared certificate
    resources in an annotation.
    

使用 Kubernetes Secret

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

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

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

     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_DOMAIN 和 SECOND_DOMAIN 替換為您擁有的網域名稱,例如 example.com 和 examplepetstore.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。

用戶端和負載平衡器之間的 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。如果負載平衡器以服務的通訊埠 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。