在虛擬私有雲網路之間建立內部負載平衡器

本頁面說明如何在虛擬私有雲網路間的 Google Kubernetes Engine (GKE) 上,建立內部直通式網路負載平衡器。

閱讀本頁面前,請確認您已熟悉下列概念:

事前準備

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

  • 啟用 Google Kubernetes Engine API。
  • 啟用 Google Kubernetes Engine API
  • 如要使用 Google Cloud CLI 執行這項工作,請安裝並初始化 gcloud CLI。如果您先前已安裝 gcloud CLI,請執行 gcloud components update 指令,取得最新版本。較舊的 gcloud CLI 版本可能不支援執行本文件中的指令。

使用 Private Service Connect 建立內部負載平衡器

服務生產者可以使用服務連結,透過 Private Service Connect,讓其他虛擬私有雲網路的服務消費者使用服務。您可以使用 ServiceAttachment 自訂資源建立、管理及刪除服務連結。GKE Private Service Connect 控制器會監控 ServiceAttachment 資源,並在 Compute Engine 中自動建立、更新或刪除對應的 ServiceAttachment 資源。

需求條件和限制

  • 適用 Private Service Connect 的限制。
  • 您可以在 GKE 1.21.4-gke.300 以上版本中建立服務附件。
  • 叢集必須啟用 HttpLoadBalancing外掛程式。新的 GKE 叢集預設會啟用 HttpLoadBalancing 外掛程式。
  • 您無法在多個服務附件設定中使用相同的子網路。
  • 您必須建立使用內部直通式網路負載平衡器的 GKE 服務。
  • GKE 服務只能使用單一通訊協定。不支援混合通訊協定 GKE 服務。
  • 如果 GKE 版本早於 1.22.4-gke.100,則無法在其他專案 (Shared VPC) 中指定子網路。如果是 Shared VPC,請確保符合Shared VPC 的所有規定。
  • 建立服務附件後,您就無法更新內部負載平衡器。如要變更負載平衡器設定,您必須刪除並重新建立服務連結。

建立 ServiceAttachment

  1. 建立子網路。

    您必須為每個 ServiceAttachment 建立新的子網路。

    gcloud compute networks subnets create SUBNET_NAME \
        --project PROJECT_ID \
        --network NETWORK_NAME \
        --region REGION \
        --range SUBNET_RANGE \
        --purpose PRIVATE_SERVICE_CONNECT
    

    更改下列內容:

    • SUBNET_NAME:新子網路的名稱。在 GKE 1.22.4-gke.100 以上版本中,您可以使用這個欄位的完整資源網址,指定其他專案中的子網路。您可以使用 gcloud compute networks subnets describe 指令,取得完整的資源網址。
    • PROJECT_ID:專案的 ID。 Cloud de Confiance
    • NETWORK_NAME:子網路的虛擬私有雲網路名稱。
    • REGION:新子網路的區域。您必須使用與所建立服務相同的區域。
    • SUBNET_RANGE:子網路要使用的 IP 位址範圍。
  2. 部署工作負載。

    下列資訊清單說明執行範例網頁應用程式容器映像檔的 Deployment。將資訊清單儲存為 my-deployment.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: psc-ilb
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: psc-ilb
      template:
        metadata:
          labels:
            app: psc-ilb
        spec:
          containers:
          - name: whereami
            image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1
            ports:
              - name: http
                containerPort: 8080
            readinessProbe:
              httpGet:
                path: /healthz
                port: 8080
                scheme: HTTP
              initialDelaySeconds: 5
              timeoutSeconds: 1
    
  3. 將資訊清單套用至叢集:

    kubectl apply -f my-deployment.yaml
    
  4. 建立服務。 下列資訊清單說明一項服務,該服務會在 TCP 通訊埠 8080 上建立內部直通式網路負載平衡器。將資訊清單儲存為 my-service.yaml:

     apiVersion: v1
     kind: Service
     metadata:
       name: SERVICE_NAME
       annotations:
         networking.gke.io/load-balancer-type: "Internal"
     spec:
       type: LoadBalancer
       selector:
         app: psc-ilb
       ports:
       - port: 80
         targetPort: 8080
         protocol: TCP
    

    更改下列內容:

    • SERVICE_NAME:新服務的名稱。
  5. 將資訊清單套用至叢集:

    kubectl apply -f my-service.yaml
    
  6. 建立 ServiceAttachment。

    下列資訊清單說明 ServiceAttachment,該資訊清單會向服務消費者公開您建立的服務。將資訊清單儲存為 my-psc.yaml:

    apiVersion: networking.gke.io/v1
    kind: ServiceAttachment
    metadata:
     name: SERVICE_ATTACHMENT_NAME
     namespace: default
    spec:
     connectionPreference: ACCEPT_AUTOMATIC
     natSubnets:
     - SUBNET_NAME
     proxyProtocol: false
     reconcileConnections: false  # set to true to enable connection reconciliation
     resourceRef:
       kind: Service
       name: SERVICE_NAME
    

    更改下列內容:

    • SERVICE_ATTACHMENT_NAME:新服務附件的名稱。
    • SUBNET_NAME:新子網路的名稱。在 GKE 1.22.4-gke.100 以上版本中,您可以使用這個欄位的完整資源網址,指定其他專案中的子網路。您可以使用 gcloud compute networks subnets describe 指令取得完整資源網址。如為 Shared VPC 設定,請使用下列格式: projects/HOST_PROJECT_ID/regions/COMPUTE_REGION/subnetworks/SUBNET_NAME。

    如要進一步瞭解資訊清單欄位,請參閱「服務附件欄位」。

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

    kubectl apply -f my-psc.yaml
    
  8. 確認 Private Service Connect 控制器已建立服務連結:

    gcloud compute service-attachments list
    

    輸出內容會顯示服務連結,並附上自動產生的名稱:

    NAME        REGION       PRODUCER_FORWARDING_RULE          CONNECTION_PREFERENCE
    k8s1-sa-... REGION_NAME  a3fea439c870148bdba5e59c9ea9451a  ACCEPT_AUTOMATIC
    

查看ServiceAttachment

您可以使用下列指令查看 ServiceAttachment 的詳細資料:

kubectl describe serviceattachment SERVICE_ATTACHMENT_NAME

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

Name:        <sa-name>
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  networking.gke.io/v1beta1
Kind:         ServiceAttachment
Metadata:
  ...
Status:
  Forwarding Rule URL:      https://www.googleapis.com/compute/beta/projects/<project>/regions/<region>/forwardingRules/<fr-name>
  Last Modified Timestamp:  2021-07-08T01:32:39Z
  Service Attachment URL:   https://www.googleapis.com/compute/beta/projects/<projects>/regions/<region>/serviceAttachments/<gce-service-attachment-name>
Events:                     <none>

取用 ServiceAttachment

如要從其他專案使用服務,請按照下列步驟操作:

  1. 取得 ServiceAttachment 的網址:

    kubectl get serviceattachment SERVICE_ATTACHMENT_NAME -o=jsonpath="{.status.serviceAttachmentURL}"
    

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

      serviceAttachmentURL: https://www.googleapis.com/compute/alpha/projects/<project>/region/<region>/serviceAttachments/k8s1-...my-sa
    
  2. 使用 ServiceAttachment 的網址建立 Private Service Connect 端點。

  3. 在用戶專案的 VM 中使用 curl 指令,確認可以連線至供應商專案中部署的服務:

    curl PSC_IP_ADDRESS
    

    將 PSC_IP_ADDRESS 替換為用戶專案中轉送規則的 IP 位址。

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

    {
      "cluster_name":"cluster",
      "host_header":"10.128.15.200",
      "node_name":"gke-psc-default-pool-be9b6e0e-dvxg.c.gke_project.internal",
      "pod_name":"foo-7bf648dcfd-l5jf8",
      "pod_name_emoji":"👚",
      "project_id":"gke_project",
      "timestamp":"2021-06-29T21:32:03",
      "zone":"ZONE_NAME"
    }
    

更新 ServiceAttachment

您可以按照下列步驟更新 ServiceAttachment:

  1. 編輯 my-psc.yaml 中的 ServiceAttachment 資訊清單:

    apiVersion: networking.gke.io/v1
    kind: ServiceAttachment
    metadata:
      name: my-sa
      namespace: default
    spec:
      connectionPreference: ACCEPT_AUTOMATIC
      natSubnets:
      - my-nat-subnet
      proxyProtocol: false
      resourceRef:
        kind: Service
        name: ilb-service
    
  2. 將資訊清單套用至叢集:

    kubectl apply -f my-psc.yaml
    

刪除 ServiceAttachment

您無法刪除已連線至服務連結的內部直通式網路負載平衡器。您必須分別刪除服務連結和 GKE 服務。

  1. 刪除服務附件:

    kubectl delete serviceattachment SERVICE_ATTACHMENT_NAME --wait=false
    

    這項指令會將服務連結標示為待刪除,但資源仍會存在。您也可以省略 --wait 旗標,等待刪除作業完成。

  2. 刪除服務:

    kubectl delete svc SERVICE_NAME
    
  3. 刪除子網路:

    gcloud compute networks subnets delete SUBNET_NAME
    

ServiceAttachment 個欄位

ServiceAttachment 包含下列欄位:

  • connectionPreference:連線偏好設定,決定客戶連線至服務的方式。您可以使用 ACCEPT_AUTOMATIC 自動核准專案,也可以使用 ACCEPT_MANUAL 明確核准專案。詳情請參閱「使用 Private Service Connect 發布服務」。
  • natSubnets:服務連結要使用的子網路資源名稱清單。
  • proxyProtocol:設為 true 時,要求中會提供消費者來源 IP 和 Private Service Connect 連線 ID。這個欄位為選填,如未提供,預設值為 false。
  • reconcileConnections (預先發布版):設為 true 時,如果服務消費者接受或拒絕清單有所變更,系統會自動終止現有的未授權連線。如果設為 false,變更只會影響新的連線。這個欄位為選填,預設值為 false。這個欄位支援 GKE 1.36.0-gke.2459000 以上版本。
  • consumerAllowList:允許連線至 ServiceAttachment 的消費者專案清單。只有在 connectionPreference 為 ACCEPT_MANUAL 時,才能使用此欄位。如要進一步瞭解這個欄位,請參閱「使用 Private Service Connect 發布服務」。
    • project:用戶專案的專案 ID 或編號。
    • connectionLimit:消費者專案的連線限制。這個欄位為選填。
    • forceSendFields:要傳送的欄位名稱,會納入 API 要求。 這是選填欄位。
    • nullFields:要納入 API 要求 (值為空值) 的欄位名稱。這是選填欄位。
  • consumerRejectList:禁止連線至 ServiceAttachment 的消費者專案 ID 或編號清單。只有在 connectionPreference 為 ACCEPT_MANUAL 時,才能使用這個欄位。如要進一步瞭解這個欄位,請參閱「使用 Private Service Connect 發布服務」。
  • resourceRef:Kubernetes 資源的參照。

    • kind:Kubernetes 資源類型。必須使用 Service。
    • name:Kubernetes 資源的名稱,必須與內部直通式網路負載平衡器位於相同命名空間。

疑難排解

您可以使用下列指令查看錯誤訊息:

kubectl get events -n NAMESPACE

將 NAMESPACE 替換為內部直通式網路負載平衡器的命名空間。

刪除內部直通式網路負載平衡器時發生錯誤

如果您嘗試刪除服務附件使用的內部直通式網路負載平衡器,就會看到類似下列的錯誤訊息。您必須先刪除 ServiceAttachment,才能刪除內部直通式網路負載平衡器。

Error syncing load balancer: failed to ensure load balancer: googleapi:
Error 400: The forwarding_rule resource '<fwd-rule-URL>' is already being used
by '<svc-attachment-URL>', resourceInUseByAnotherResource.

啟用全域存取權時發生錯誤

如果內部直通式網路負載平衡器使用 Private Service Connect 服務連結,啟用全域存取權時可能會發生錯誤。

症狀:

更新 GKE 服務資訊清單並設定 networking.gke.io/internal-load-balancer-allow-global-access: "true" 註解,啟用全域存取權時,套用資訊清單會失敗。執行 kubectl get events 指令時,您會看到下列錯誤訊息:

Error syncing load balancer: failed to ensure load balancer: googleapi: Error 400: The forwarding_rule resource '...' is already being used by '...', resourceInUseByAnotherResource

原因:

發生這項錯誤的原因是,GKE 控制層嘗試重新建立負載平衡器的轉送規則,以啟用全域存取權。不過,由於轉送規則正由 ServiceAttachment 使用,因此無法刪除並重新建立,導致發生錯誤。

解決方法:

如要在負載平衡器上啟用全域存取權,同時盡量減少停機時間,請更新 GKE 服務設定並手動更新轉送規則:

  1. 更新 GKE 服務資訊清單:更新 GKE 服務資訊清單,加入 networking.gke.io/internal-load-balancer-allow-global-access: "true" 註解。

  2. 手動啟用轉送規則的全球存取權:按照「啟用全球存取權」一文中的步驟,使用Cloud de Confiance 控制台、Google Cloud CLI 或 Compute Engine API 更新負載平衡器的轉送規則。

未同步處理的「ReconcileConnections」欄位

如果您在 Compute Engine ReconcileConnectionsServiceAttachment 資源中手動啟用該欄位,但 Kubernetes 資訊清單中省略了該欄位,則該欄位會預設為 false。GKE 控制器就不會覆寫該欄位的值。

症狀:

Kubernetes ServiceAttachment 資源具有 networking.gke.io/unsynced-field: ReconcileConnections 註解。執行 kubectl get events 指令時,您會看到類似下列內容的警告事件:

Field "ReconcileConnections" is not specified in the ServiceAttachment CR but has a value in GCE. The controller will not overwrite this field until it is explicitly set in the CR.

解決方法:

如要解決這項警告並同步處理值,請採取下列其中一項行動:

  • 更新 GKE ServiceAttachment 資源:更新 GKE ServiceAttachment 資訊清單,加入 reconcileConnections: true (如要停用,請加入 false)。
  • 更新 Compute Engine ServiceAttachment 資源:手動將 reconcileConnections 欄位設為 false。

後續步驟