在私人 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. 在叢集和 HTTPRoute 資訊清單中部署 Gateway,設定 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 時所需的角色

    如要啟用 API,您必須具備 serviceusage.services.enable 權限。如果您建立了專案,可能已透過「擁有者」角色 (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 時所需的角色

    如要啟用 API,您必須具備 serviceusage.services.enable 權限。如果您建立了專案,可能已透過「擁有者」角色 (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)。根據預設,這個 Identity and Access Management (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 控制台的「Welcome」(歡迎)頁面找到專案編號,也可以執行下列指令:

    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。詳情請參閱「部署閘道」。系統會部署 HTTPRoute 資訊清單來建立路徑,並將流量傳送至應用程式後端。

  1. 在叢集中部署閘道。

    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 資訊清單,將通訊埠 80 的 HTTP 流量轉送至 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 控制台的「Welcome」(歡迎)頁面找到專案編號,也可以執行下列指令:

    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

後續步驟