在私人 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. 在虛擬私有雲網路的指定子網路中,建立 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. 登入 Google Cloud 帳戶。如果您是 Google Cloud新手,歡迎 建立帳戶,親自評估產品在實際工作環境中的成效。新客戶還能獲得價值 $300 美元的免費抵免額,可用於執行、測試及部署工作負載。
  2. 安裝 Google Cloud CLI。

  3. 若您採用的是外部識別資訊提供者 (IdP),請先使用聯合身分登入 gcloud CLI

  4. 執行下列指令,初始化 gcloud CLI:

    gcloud init
  5. 建立或選取 Google Cloud 專案

    選取或建立專案所需的角色

    • 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您在專案中獲派角色,即可選取該專案。
    • 建立專案:如要建立專案,您需要專案建立者角色 (roles/resourcemanager.projectCreator),其中包含 resourcemanager.projects.create 權限。瞭解如何授予角色
    • 建立 Google Cloud 專案:

      gcloud projects create PROJECT_ID

      PROJECT_ID 替換為您要建立的 Google Cloud 專案名稱。

    • 選取您建立的 Google Cloud 專案:

      gcloud config set project PROJECT_ID

      PROJECT_ID 替換為 Google Cloud 專案名稱。

  6. 確認專案已啟用計費功能 Google Cloud

  7. 啟用 Cloud Resource Manager、Compute Engine、Eventarc、GKE 和 Pub/Sub API:

    啟用 API 時所需的角色

    您必須具備 serviceusage.services.enable 權限,才能啟用 API。如果您建立了專案,可能已透過「擁有者」角色 (roles/owner) 取得這項權限。否則,您可以透過「服務使用情形管理員」角色 (roles/serviceusage.serviceUsageAdmin) 取得這項權限。瞭解如何授予角色

    gcloud services enable compute.googleapis.com container.googleapis.com cloudresourcemanager.googleapis.com eventarc.googleapis.com pubsub.googleapis.com
  8. 安裝 Google Cloud CLI。

  9. 若您採用的是外部識別資訊提供者 (IdP),請先使用聯合身分登入 gcloud CLI

  10. 執行下列指令,初始化 gcloud CLI:

    gcloud init
  11. 建立或選取 Google Cloud 專案

    選取或建立專案所需的角色

    • 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您在專案中獲派角色,即可選取該專案。
    • 建立專案:如要建立專案,您需要專案建立者角色 (roles/resourcemanager.projectCreator),其中包含 resourcemanager.projects.create 權限。瞭解如何授予角色
    • 建立 Google Cloud 專案:

      gcloud projects create PROJECT_ID

      PROJECT_ID 替換為您要建立的 Google Cloud 專案名稱。

    • 選取您建立的 Google Cloud 專案:

      gcloud config set project PROJECT_ID

      PROJECT_ID 替換為 Google Cloud 專案名稱。

  12. 確認專案已啟用計費功能 Google Cloud

  13. 啟用 Cloud Resource Manager、Compute Engine、Eventarc、GKE 和 Pub/Sub API:

    啟用 API 時所需的角色

    您必須具備 serviceusage.services.enable 權限,才能啟用 API。如果您建立了專案,可能已透過「擁有者」角色 (roles/owner) 取得這項權限。否則,您可以透過「服務使用情形管理員」角色 (roles/serviceusage.serviceUsageAdmin) 取得這項權限。瞭解如何授予角色

    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 的子網路

除非您建立禁止使用的組織政策,否則新專案一開始即設有預設網路 (自動模式虛擬私有雲網路),其中在每個區域都有一個子網路。每個虛擬私有雲網路都含有一或多個稱為「子網路」的 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。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 收取費用,請刪除含有相關資源的專案,或者保留專案但刪除個別資源。

刪除專案

    刪除 Google Cloud 專案:

    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

後續步驟