在专用 GKE 集群中的专用 HTTP 端点上接收 PubSub 事件


本教程介绍了如何在专用 Google Kubernetes Engine (GKE) 集群中创建专用 HTTP 端点,以使用 Eventarc 接收 Pub/Sub 消息事件。如需详细了解此事件目标位置,请参阅将事件路由到 VPC 网络中的内部 HTTP 端点

专用 GKE 集群是一种 Virtual Private Cloud (VPC) 原生集群,其中的节点仅具有内部 IP 地址,这意味着节点和 Pod 默认与互联网隔离。您可以选择对控制平面没有客户端访问权限、具有受限访问权限或不受限访问权限。您不能将现有非专用集群转换为专用集群。如需了解详情,请参阅专用集群简介

您可以在终端或 Cloud Shell 中使用 Google Cloud CLI 运行以下命令。

目标

在此教程中,您将学习以下操作:

  1. 在默认 VPC 网络中创建一个代理专用子网,并创建一个 VPC 防火墙规则。
  2. 创建对公共端点没有客户端访问权限的专用 GKE Autopilot 集群。
  3. 在 VPC 网络的指定子网中创建 Compute Engine 虚拟机 (VM) 实例。
  4. 建立与虚拟机实例的 SSH 连接,并在虚拟机实例上部署事件接收器服务。
  5. 在集群中部署网关和 HTTPRoute 清单,以对 Kubernetes 中的流量到应用后端的路由进行配置。
  6. 创建网络连接,以允许提供方 VPC 网络发起与使用方 VPC 网络的连接。
  7. 创建 Eventarc 触发器,以将 Pub/Sub 事件路由到虚拟机实例上的事件接收器。
  8. 向 Pub/Sub 主题发布消息以生成事件,并在应用 Pod 日志中查看事件正文。

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用情况来估算费用。 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. To initialize the gcloud CLI, run the following command:

    gcloud init
  4. 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.

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

  6. 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
  7. Install the Google Cloud CLI.
  8. To initialize the gcloud CLI, run the following command:

    gcloud init
  9. 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.

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

  11. 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
  12. 更新 Google Cloud CLI 组件:
    gcloud components update
  13. 使用您的账号登录:
    gcloud auth login
  14. 如果您是项目创建者,则会被授予基本 Owner 角色 (roles/owner)。默认情况下,此 Identity and Access Management (IAM) 角色可提供完全访问大多数 Google Cloud 资源所需的权限,您可以跳过此步骤。

    如果您不是项目创建者,则必须向主账号授予项目的必需权限。例如,主账号可以是 Google 账号(针对最终用户)或服务账号(针对应用和计算工作负载)。如需了解详情,请参阅事件目标位置的角色和权限页面。

    所需权限

    如需获得完成本快速入门所需的权限,请让您的管理员为您授予项目的以下 IAM 角色:

    如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限

    您也可以通过自定义角色或其他预定义角色来获取所需的权限。

  15. 记下 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 角色,这些角色包含所需的最小权限并遵循最小权限原则。

  16. 如果您在 2021 年 4 月 8 日或之前启用了 Cloud Pub/Sub 服务代理,以支持经过身份验证的 Pub/Sub 推送请求,请向该服务代理授予 Service Account Token Creator 角色 (roles/iam.serviceAccountTokenCreator)。否则,系统会默认授予此角色:
    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member=serviceAccount:service-PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
        --role=roles/iam.serviceAccountTokenCreator

创建代理专用子网

除非您创建组织政策来禁止 VPC 网络,否则新项目会首先创建一个默认网络(自动模式 VPC 网络),此网络在每个区域内都包含一个子网。每个 VPC 网络均由一个或多个 IP 地址范围(即“子网”)组成。子网属于区域级资源,并且具有与之关联的 IP 地址范围。

  1. 使用 gcloud compute networks subnets create 命令在默认网络中创建代理专用子网。

    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. 创建一条防火墙规则,以与代理专用子网的范围匹配并允许 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

在指定子网中创建虚拟机实例

Compute Engine 虚拟机实例是托管在 Google 基础架构上的虚拟机。术语 Compute Engine 实例、虚拟机实例和虚拟机是同义词,可互换使用。虚拟机实例包括 GKE 集群、App Engine 柔性环境实例,以及 Compute Engine 虚拟机上构建的其他 Google Cloud 产品。

使用 gcloud compute instances create 命令在您之前创建的子网中创建 Compute Engine 虚拟机实例。关联服务账号,并将虚拟机的访问权限范围设置为 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

如需了解详情,请参阅创建并启动虚拟机实例

在虚拟机上部署事件接收器

使用预构建的映像 us-docker.pkg.dev/cloudrun/container/hello 在虚拟机上部署一项服务,以监听端口 80 并接收和记录事件。

  1. 通过运行以下命令,与虚拟机实例建立 SSH 连接:

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

    建立与 SSH 服务器的连接后,请在虚拟机实例上运行其余命令。

  2. 如有必要,安装 kubectl 和所有必需的插件

  3. 在虚拟机实例中,使用 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 服务向流量公开应用。运行以下 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 流量路由

网关资源表示在 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 指定派生此网关的 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
    

创建网络连接

网络连接是一种资源,允许提供方 VPC 网络通过 Private Service Connect 接口启动与使用方 VPC 网络的连接。

为了发布事件,Eventarc 使用网络连接与 VPC 网络中托管的内部 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 主题时将事件路由到虚拟机上部署的事件接收器。

  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)'
    

如需详细了解如何配置触发器,请参阅将事件路由到 VPC 网络中的内部 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. 退出虚拟机,然后删除虚拟机实例:
      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

后续步骤