在私人 GKE 叢集的私人 HTTP 端點接收 Pub/Sub 事件


本教學課程說明如何在私人 Google Kubernetes Engine (GKE) 叢集中建立私人 HTTP 端點,使用 Eventarc 接收 Pub/Sub 訊息事件。如要進一步瞭解這個事件目的地,請參閱「將事件轉送至虛擬私有雲網路中的內部 HTTP 端點」。

私人 GKE 叢集是虛擬私有雲 (VPC) 原生叢集的一種,節點只會使用內部 IP 位址,因此節點和 Pod 預設會與網際網路隔離。您可以選擇不開放用戶端存取控制層、限制存取權,或開放無限制存取權。您無法將現有的非私人叢集轉換為私人叢集。詳情請參閱「關於私人叢集」。

您可以在終端機或 Cloud Shell 中,使用 Google Cloud CLI 執行下列指令。

目標

在這個教學課程中,您將執行下列操作:

  1. 在預設虛擬私有雲網路中建立僅限 Proxy 的子網路,並建立虛擬私有雲防火牆規則。
  2. 建立無法透過用戶端存取公開端點的私人 GKE Autopilot 叢集。
  3. 在 VPC 網路的指定子網路中,建立 Compute Engine 虛擬機器 (VM) 執行個體。
  4. 建立與 VM 執行個體的 SSH 連線,並在 VM 執行個體上部署事件接收器服務。
  5. 在叢集中部署 Gateway 和 HTTPRoute 資訊清單,以便在 Kubernetes 中設定流量的轉送路徑,將流量轉送至應用程式後端。
  6. 建立網路連結,讓供應商虛擬私有雲網路啟動與用戶虛擬私有雲網路的連線。
  7. 建立 Eventarc 觸發條件,將 Pub/Sub 事件轉送至 VM 執行個體上的事件接收器。
  8. 將訊息發布至 Pub/Sub 主題以產生事件,並在應用程式 Pod 記錄檔中查看事件主體。

費用

在本文件中,您會使用 Google Cloud的下列計費元件:

如要根據預測用量估算費用,請使用 Pricing Calculator

初次使用 Google Cloud 的使用者可能符合免費試用資格。

完成本文所述工作後,您可以刪除已建立的資源,避免繼續計費。詳情請參閱清除所用資源一節。

事前準備

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Install the Google Cloud CLI.

  3. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  4. To initialize the gcloud CLI, run the following command:

    gcloud init
  5. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the Cloud Resource Manager, Compute Engine, Eventarc, GKE, and Pub/Sub APIs:

    gcloud services enable compute.googleapis.com container.googleapis.com cloudresourcemanager.googleapis.com eventarc.googleapis.com pubsub.googleapis.com
  8. Install the Google Cloud CLI.

  9. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  10. To initialize the gcloud CLI, run the following command:

    gcloud init
  11. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  12. Make sure that billing is enabled for your Google Cloud project.

  13. Enable the Cloud Resource Manager, Compute Engine, Eventarc, GKE, and Pub/Sub APIs:

    gcloud services enable compute.googleapis.com container.googleapis.com cloudresourcemanager.googleapis.com eventarc.googleapis.com pubsub.googleapis.com
  14. 更新 Google Cloud CLI 元件:
    gcloud components update
  15. 登入帳戶:
    gcloud auth login
  16. 如果您是專案建立者,系統會授予基本「擁有者」角色 (roles/owner)。根據預設,這個身分與存取權管理 (IAM) 角色包含完全存取大多數 Google Cloud資源所需的權限,因此您可以略過這個步驟。

    如果您不是專案建立者,必須在專案中將必要權限授予適當的主體。舉例來說,主體可以是 Google 帳戶 (適用於使用者) 或服務帳戶 (適用於應用程式和運算工作負載)。詳情請參閱活動目的地的「角色和權限」頁面。

    所需權限

    如要取得完成本快速入門所需的權限,請要求管理員為您授予專案的下列 IAM 角色:

    如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和機構的存取權」。

    您或許還可透過自訂角色或其他預先定義的角色取得必要權限。

  17. 記下 Compute Engine 預設服務帳戶,因為您會將其附加至 Eventarc 觸發程序,代表觸發程序的身分,以利進行測試。啟用或使用採用 Compute Engine 的服務後,系統會自動建立這個服務帳戶,電子郵件地址格式如下: Google Cloud

    PROJECT_NUMBER-compute@developer.gserviceaccount.com

    PROJECT_NUMBER 替換為專案編號。 Google Cloud您可以在 Google Cloud 控制台的「歡迎」頁面找到專案編號,也可以執行下列指令:

    gcloud projects describe PROJECT_ID --format='value(projectNumber)'

    在正式環境中,我們強烈建議建立新的服務帳戶,並授予一或多個包含最低必要權限的 IAM 角色,遵循最低權限原則。

  18. 如果您是在 2021 年 4 月 8 日當天或之前啟用 Cloud Pub/Sub 服務代理,請將服務帳戶權杖建立者角色 (roles/iam.serviceAccountTokenCreator) 授予服務代理,以支援已驗證的 Pub/Sub 推送要求。否則,系統會預設授予這個角色:
    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member=serviceAccount:service-PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
        --role=roles/iam.serviceAccountTokenCreator

建立僅限 Proxy 的子網路

除非您建立禁止此行為的機構政策,否則新專案一開始都會具備預設網路 (自動模式 VPC 網路),其中在每個地區都有一個子網路。每個虛擬私有雲網路都含有一或多個稱為「子網路」的 IP 位址範圍。子網路屬於區域性資源,具有相關聯的 IP 位址範圍。

  1. 使用 gcloud compute networks subnets create 指令,在預設網路中建立僅限 Proxy 的子網路。

    gcloud compute networks subnets create proxy-only-subnet \
        --purpose=REGIONAL_MANAGED_PROXY \
        --role=ACTIVE \
        --region=us-central1 \
        --network=default \
        --range=10.10.10.0/24
    

    請注意,具有 purpose=REGIONAL_MANAGED_PROXY 的子網路會保留給以 Envoy 為基礎的負載平衡器,且 range 必須提供 64 個以上的 IP 位址。

  2. 建立防火牆規則,比對僅限 Proxy 的子網路範圍,並允許 TCP 通訊埠 8080 上的流量。

    gcloud compute firewall-rules create allow-proxy-connection \
        --allow tcp:8080 \
        --source-ranges 10.10.10.0/24 \
        --network=default
    

建立私人 GKE 叢集

使用 gcloud container clusters create-auto 指令,在Autopilot 模式中建立具備私人節點的私人 GKE 叢集,且用戶端無法存取公開端點。

下列範例會建立名為 private-cluster 的私人 GKE 叢集,並建立名為 my-subnet 的子網路:

gcloud container clusters create-auto private-cluster \
    --create-subnetwork name=my-subnet \
    --enable-master-authorized-networks \
    --enable-private-nodes \
    --enable-private-endpoint \
    --region=us-central1

注意事項:

  • --enable-master-authorized-networks 表示僅有您授權的 IP 位址範圍可以存取公開端點。
  • --enable-private-nodes 代表叢集節點沒有外部 IP 位址。
  • --enable-private-endpoint 表示叢集是使用控制層 API 端點的內部 IP 位址進行管理。

建立叢集可能需要幾分鐘的時間。叢集建立完成後,輸出內容應會顯示叢集狀態為 RUNNING

在指定子網路中建立 VM 執行個體

Compute Engine VM 執行個體是指託管在 Google 基礎架構上的虛擬機器。「Compute Engine 執行個體」、「VM 執行個體」和「VM」這幾個詞是同義詞,可以互換使用。VM 執行個體包括 GKE 叢集、App Engine 彈性環境執行個體,以及其他 Google Cloud 以 Compute Engine VM 為基礎建構的產品。

使用 gcloud compute instances create 指令,在先前建立的子網路中建立 Compute Engine VM 執行個體。附加服務帳戶,並將 VM 的存取範圍設為 cloud-platform

gcloud compute instances create my-vm \
    --service-account=PROJECT_NUMBER-compute@developer.gserviceaccount.com \
    --scopes=https://www.googleapis.com/auth/cloud-platform \
    --zone=us-central1-a \
    --subnet=my-subnet

詳情請參閱「建立及啟動 VM 執行個體」。

在 VM 上部署事件接收器

使用預先建構的映像檔 us-docker.pkg.dev/cloudrun/container/hello,在 VM 上部署服務,監聽通訊埠 80,並接收及記錄事件。

  1. 執行下列指令,與 VM 執行個體建立 SSH 連線:

    gcloud compute ssh my-vm --project=PROJECT_ID --zone=us-central1-a
    

    建立與 SSH 伺服器的連線後,請在 VM 執行個體上執行其餘指令。

  2. 如有必要,請安裝 kubectl 和任何必要的外掛程式

  3. 在 VM 執行個體中,使用 get-credentials 指令啟用 kubectl,以便與您建立的叢集搭配使用。

    gcloud container clusters get-credentials private-cluster \
        --region=us-central1 \
        --internal-ip
    
  4. 使用 Kubernetes 指令 kubectl create deployment,將應用程式部署至叢集。

    kubectl create deployment hello-app \
        --image=us-docker.pkg.dev/cloudrun/container/hello
    

    這會建立名為「hello-app」的部署。Deployment 的 Pod 會執行 hello 容器映像檔。

  5. 部署應用程式後,您可以建立 Kubernetes Service,對流量公開應用程式。執行下列 kubectl expose 指令:

    kubectl expose deployment hello-app \
        --type ClusterIP \
        --port 80 \
        --target-port 8080
    

    輸出內容應會顯示 service/hello-app exposed

    您可以忽略類似下列的訊息:

    E0418 14:15:33.970933    1129 memcache.go:287] couldn't get resource list for metrics.k8s.io/v1beta1: the server is currently unable to handle the request
    

設定 Kubernetes 流量轉送

Gateway 資源代表 Kubernetes 中轉送流量的資料層。視衍生自的 GatewayClass 而定,Gateway 可以代表多種不同的負載平衡和路由。詳情請參閱部署閘道。系統會部署 HTTPRoute 資訊清單來建立路徑,並將流量傳送至應用程式後端。

  1. 在叢集中部署 Gateway。

    kubectl apply -f - <<EOF
    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: internal-http
    spec:
      gatewayClassName: gke-l7-rilb
      listeners:
      - name: http
        protocol: HTTP
        port: 80
    EOF
    

    注意事項:

    • gatewayClassName: gke-l7-rilb 會指定這個 Gateway 衍生自的 GatewayClass。gke-l7-rilb 對應於內部應用程式負載平衡器。
    • port: 80 指定閘道只公開通訊埠 80,以監聽 HTTP 流量。
  2. 確認閘道已正確部署。部署所有資源可能需要幾分鐘的時間。

    kubectl describe gateways.gateway.networking.k8s.io internal-http
    

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

    Name:         internal-http
    Namespace:    default
    ...
    API Version:  gateway.networking.k8s.io/v1beta1
    Kind:         Gateway
    ...
    Spec:
      Gateway Class Name:  gke-l7-rilb
      Listeners:
        Allowed Routes:
          Namespaces:
            From:  Same
        Name:      http
        Port:      80
        Protocol:  HTTP
    Status:
      Addresses:
        Type:   IPAddress
        Value:  10.36.172.5
    ...
    Events:
      Type    Reason  Age                From                   Message
      ----    ------  ----               ----                   -------
      Normal  ADD     80s                sc-gateway-controller  default/internal-http
      Normal  UPDATE  20s (x3 over 80s)  sc-gateway-controller  default/internal-http
      Normal  SYNC    20s                sc-gateway-controller  SYNC on default/internal-http was a success
    
  3. 部署 HTTPRoute 資訊清單,將 HTTP 流量轉送至通訊埠 80 的 hello-app 服務。

    kubectl apply -f - <<EOF
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: hello-app-route
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      rules:
      - backendRefs:
        - name: hello-app
          port: 80
    EOF
    

建立網路連結

網路連結是一種資源,可讓供應商虛擬私有雲網路透過 Private Service Connect 介面,啟動與用戶端虛擬私有雲網路的連線。

發布事件時,Eventarc 會使用網路連結,與虛擬私有雲網路中託管的內部 HTTP 端點建立連線。

您可以建立網路連結,自動接受參照該網路連結的任何 Private Service Connect 介面連線。在包含 HTTP 目的地服務的相同網路和區域中,建立網路連結。

gcloud compute network-attachments create my-network-attachment \
    --region=us-central1 \
    --subnets=my-subnet\
    --connection-preference=ACCEPT_AUTOMATIC

詳情請參閱「關於網路連結」。

建立 Eventarc 觸發條件

建立 Eventarc 觸發程序,在訊息發布至 Pub/Sub 主題時,建立新的 Pub/Sub 主題,並將事件傳送至部署在 VM 上的事件接收器。

  1. 擷取閘道位址。

    GATEWAY_ADDRESS=$(kubectl get gateways.gateway.networking.k8s.io internal-http -o=jsonpath="{.status.addresses[0].value}")
    
  2. 建立觸發條件。

    gcloud eventarc triggers create my-trigger \
        --location=us-central1 \
        --destination-http-endpoint-uri="http://$GATEWAY_ADDRESS:80/" \
        --network-attachment="projects/PROJECT_ID/regions/us-central1/networkAttachments/my-network-attachment" \
        --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
        --service-account=PROJECT_NUMBER-compute@developer.gserviceaccount.com
    

    PROJECT_NUMBER 替換為專案編號。 Google Cloud您可以在 Google Cloud 控制台的「歡迎」頁面找到專案編號,也可以執行下列指令:

    gcloud projects describe PROJECT_ID --format='value(projectNumber)'
    

如要進一步瞭解如何設定觸發條件,請參閱將事件路由至虛擬私有雲網路中的內部 HTTP 端點

產生及查看 Pub/Sub 主題事件

您可以將訊息發布至 Pub/Sub 主題,藉此產生事件。

  1. 找出 Pub/Sub 主題並設為環境變數。

    export MY_TOPIC=$(gcloud eventarc triggers describe my-trigger \
        --location=us-central1 \
        --format='value(transport.pubsub.topic)')
    
  2. 將訊息發布至 Pub/Sub 主題,產生事件。

    gcloud pubsub topics publish $MY_TOPIC --message "Hello World"
    

    Eventarc 觸發條件會將事件轉送至私有 GKE 叢集中的內部 HTTP 端點。

  3. 檢查應用程式 Pod 記錄,並確認事件傳送情形。

    POD_NAME=$(kubectl get pod --selector app=hello-app --output=name)
    kubectl logs $POD_NAME
    

    事件主體應類似於下列內容:

    2024/04/18 20:31:43 Hello from Cloud Run! The container started successfully and is listening for HTTP requests on $PORT
    {"severity":"INFO","eventType":"google.cloud.pubsub.topic.v1.messagePublished","message":"Received event of type google.cloud.pubsub.topic.v1.messagePublished.
    Event data: Hello World","event":{"specversion":"1.0","id":"10935738681111260","source":"//pubsub.googleapis.com/projects/my-project/topics/eventarc-us-central1-my-trigger-224","type":"google.cloud.pubsub.topic.v1.messagePublished","datacontenttype":"application/json","time":"2024-04-18T20:40:03Z","data":
    {"message":{"data":"SGVsbG8gV29ybGQ=","messageId":"10935738681111260","publishTime":"2024-04-18T20:40:03Z"}}}}
    

您已成功將事件接收者服務部署至私人 GKE 叢集中的內部 HTTP 端點、建立 Eventarc 觸發條件、從 Pub/Sub 產生事件,並確認觸發條件已將事件如預期地路由至目標端點。

清除所用資源

如要避免系統向您的 Google Cloud 帳戶收取本教學課程中所用資源的相關費用,請刪除含有該項資源的專案,或者保留專案但刪除個別資源。

刪除專案

    Delete a Google Cloud project:

    gcloud projects delete PROJECT_ID

刪除個別資源

  1. 刪除 Eventarc 觸發條件:
      gcloud eventarc triggers delete my-trigger --location=us-central1
  2. 退出 VM,然後刪除 VM 執行個體:
      gcloud compute instances delete my-vm --zone=us-central1-a
  3. 刪除網路連結:
      gcloud compute network-attachments delete my-network-attachment --region=us-central1
  4. 刪除防火牆規則:
      gcloud compute firewall-rules delete allow-proxy-connection
  5. 刪除叢集:
      gcloud container clusters delete private-cluster --region=us-central1
      
  6. Delete the subnet:
      gcloud compute networks subnets delete proxy-only-subnet --region=us-central1

後續步驟