1. 概览
在本实验中,您将创建一个 Eventarc 触发器,用于将 Pub/Sub 主题连接到 Workflows 服务。借助 Eventarc,您可以解耦服务到服务的通信,从而使解决方案更具可扩展性,并实现事件驱动型。您将创建一个包含多个步骤的工作流,以执行业务流程来计算在 Cymbal Eats 订餐的客户的奖励积分。工作流将向在 GKE Autopilot 上运行的应用发送多个请求,并向 Pub/Sub 主题发布消息,以通知订单服务应用有关计算出的奖励积分。

什么是 GKE Autopilot?
GKE Autopilot 是 GKE 中的一种运维模式,在此模式下,Google 会管理您的集群配置,包括节点、扩缩、安全性和其他预配置的设置。Autopilot 集群经过优化,可以运行大多数生产工作负载,并可基于 Kubernetes 清单预配计算资源。此简化配置遵循集群和工作负载设置、可伸缩性以及安全性的 GKE 最佳实践和建议。如需查看内置设置的列表,请参阅 Autopilot 和 Standard 对照表。
使用 GKE Standard 时,用户负责管理工作器节点和节点池配置,其余部分由 GKE 负责。
在 GKE Standard 模式下运行时的客户责任与 Google 责任

使用 GKE Autopilot 时,节点池配置和管理由 Google 负责。这样,您就可以专注于在集群之上运行的应用和服务。
什么是 Eventarc?
借助 Eventarc,您可以构建事件驱动型架构,而无需实现、自定义或维护底层基础架构。Eventarc 提供了一个用于管理解耦的微服务之间的状态更改(称为“事件”)流的标准化解决方案。事件触发后,Eventarc 会通过 Pub/Sub 订阅将这些事件路由到各个目的地(例如工作流、Cloud Run),同时为您管理传送、安全、授权、可观测性和错误处理。
Google 活动提供方
- 超过 90 个 Google Cloud 提供方。这些提供程序直接从来源(例如 Cloud Storage)发送事件,也可以通过 Cloud Audit Logs 条目发送。
- Pub/Sub 提供程序。这些提供程序使用 Pub/Sub 消息将事件发送到 Eventarc。
第三方提供商
第三方提供方是提供 Eventarc 来源的非 Google 实体。
Eventarc 触发器
- Cloud Pub/Sub 事件。Eventarc 可以由发布到 Pub/Sub 主题的消息触发。
- Cloud Audit Logs (CAL) 事件。Cloud Audit Logs 会为每个云项目、文件夹和组织提供管理员活动日志和数据访问审核日志。
- 直接事件。Eventarc 可以由各种直接事件触发,例如更新 Cloud Storage 存储分区或更新 Firebase Remote Config 模板。
活动目的地
- Workflows
- Cloud Run
- GKE
- Cloud Functions(第 2 代)

什么是 Workflows?
Workflows 是一项全托管式服务,可让您集成微服务、任务和 API。Workflows 是一项无服务器服务,可根据您的需求进行扩缩。
工作流应用场景:
- 事件驱动型工作流会在定义的触发器上执行。例如,当提交新订单时,您想要计算客户忠诚度积分。或者,当订单被取消时,可以发布该事件,所有感兴趣的服务都会处理该事件。
- 批处理作业工作流使用 Cloud Scheduler 定期运行作业。例如,每晚运行一次作业,检查处于失败状态的菜单项并将其删除。
Workflows 非常适合用于编排服务的工作流。您可以自动执行包含长达一年的等待和重试过程。
Workflows 优势:
- 配置优于代码:通过将逻辑移至配置而非编写代码来减少技术债务。
- 简化架构。有状态的工作流可让您直观呈现和监控复杂的服务集成,而无需额外的依赖项。
- 整合可靠性和容错性。即使其他系统发生故障,也可以使用默认或自定义重试逻辑和错误处理来控制故障,通过为 Cloud Spanner 的每个步骤设置检查点,帮助您跟踪进度。
- 零维护。按需扩缩:无需修补或维护。您只需在工作流运行时付费,等待或非活跃时无需付费。
在本实验中,您将配置一个事件驱动型工作流。
学习内容
在本实验中,您将学习如何完成以下操作:
- 配置 Pub/Sub 主题和 Eventarc 以触发 Workflows
- 配置工作流以向在 GKE Autopilot 上运行的应用发出 API 调用
- 配置工作流以将消息发布到 Pub/Sub
- 如何在 Cloud Logging 中使用 gcloud CLI 查询工作流结构化日志
前提条件
- 本实验假设您熟悉 Cloud 控制台和 Cloud Shell 环境。
- 具备 GKE 和 Cloud Pub/Sub 方面的经验会有所帮助,但这不是硬性要求。
2. 设置和要求
Cloud 项目设置
- 登录 Google Cloud 控制台,然后创建一个新项目或重复使用现有项目。如果您还没有 Gmail 或 Google Workspace 账号,则必须创建一个。



- 项目名称是此项目参与者的显示名称。它是 Google API 尚未使用的字符串。您可以随时更新。
- 项目 ID 在所有 Google Cloud 项目中是唯一的,并且是不可变的(一经设置便无法更改)。Cloud 控制台会自动生成一个唯一字符串;通常情况下,您无需关注该字符串。在大多数 Codelab 中,您都需要引用项目 ID(通常用
PROJECT_ID标识)。如果您不喜欢生成的 ID,可以再随机生成一个 ID。或者,您也可以尝试自己的项目 ID,看看是否可用。完成此步骤后便无法更改该 ID,并且此 ID 在项目期间会一直保留。 - 此外,还有第三个值,即部分 API 使用的项目编号,供您参考。如需详细了解所有这三个值,请参阅文档。
- 接下来,您需要在 Cloud 控制台中启用结算功能,以便使用 Cloud 资源/API。运行此 Codelab 应该不会产生太多的费用(如果有费用的话)。若要关闭资源以避免产生超出本教程范围的结算费用,您可以删除自己创建的资源或删除整个项目。Google Cloud 的新用户符合参与 $300 USD 免费试用计划的条件。
环境设置
点击搜索栏右侧的图标,激活 Cloud Shell。

克隆代码库并导航到相应目录,将以下命令复制并粘贴到终端中,然后按 Enter 键:
git clone https://github.com/GoogleCloudPlatform/cymbal-eats.git && cd cymbal-eats/customer-service
运行 gke-lab-setup.sh 以部署所需的依赖项
系统将创建以下资源:
- AlloyDB 集群和实例
- GKE Autopilot 集群
./gke-lab-setup.sh
如果系统提示您进行授权,请点击“授权”继续。

设置过程大约需要 10 分钟。
等待脚本运行完毕并看到以下输出后,再运行其他步骤。
NAME: client-instance ZONE: us-central1-c MACHINE_TYPE: e2-medium PREEMPTIBLE: INTERNAL_IP: 10.128.0.9 EXTERNAL_IP: 35.232.109.233 STATUS: RUNNING
3. GKE Autopilot 集群
查看 GKE Autopilot 集群
设置项目环境变量:
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
export PROJECT_NAME=$(gcloud projects describe $PROJECT_ID --format='value(name)')
在初始设置过程中,集群是使用以下命令创建的(您无需运行此命令):
gcloud container clusters create-auto $CLUSTER_NAME --region $REGION
运行命令以查看已创建的 GKE Autopilot 集群:
gcloud container clusters list
示例输出:

运行命令以存储集群的凭据:
CLUSTER_NAME=rewards-cluster
REGION=us-central1
gcloud container clusters get-credentials $CLUSTER_NAME --region=$REGION
部署应用
接下来,您将部署客户服务应用。这是一个基于 Java 的微服务,使用 Quarkus 框架。
前往 cymbal-eats/customer-service 文件夹,然后运行以下命令来构建和上传容器映像:
./mvnw clean package -DskipTests
export CUSTOMER_SERVICE_IMAGE=gcr.io/$PROJECT_ID/customer-service:1.0.0
gcloud builds submit --tag $CUSTOMER_SERVICE_IMAGE .
设置 AlloyDB 专用 IP 地址:
export DB_HOST=$(gcloud beta alloydb instances describe customer-instance \
--cluster=customer-cluster \
--region=$REGION \
--format=json | jq \
--raw-output ".ipAddress")
echo $DB_HOST
运行以下命令,创建 Kubernetes Secret 对象以存储客户服务应用将用于连接到数据库的数据库凭据:
DB_NAME=customers
DB_USER=postgres
DB_PASSWORD=password123
kubectl create secret generic gke-alloydb-secrets \
--from-literal=database=$DB_NAME \
--from-literal=username=$DB_USER \
--from-literal=password=$DB_PASSWORD \
--from-literal=db_host=$DB_HOST
运行命令以替换 deployment.yaml 文件中的 CUSTOMER_SERVICE_IMAGE:
sed "s@CUSTOMER_SERVICE_IMAGE@$CUSTOMER_SERVICE_IMAGE@g" deployment.yaml.tmpl > customer-service-deployment.yaml
运行命令以部署应用:
kubectl apply -f customer-service-deployment.yaml
应用需要过一段时间才能转换为 RUNNING 状态。
查看部署规范文件:
deployment.yaml.tmpl
以下是配置中用于指定运行此应用所需的资源的部分。
spec:
containers:
- name: customer-service
image: CUSTOMER_SERVICE_IMAGE
resources:
requests:
cpu: 250m
memory: 512Mi
ephemeral-storage: 512Mi
limits:
cpu: 500m
memory: 1024Mi
ephemeral-storage: 1Gi
运行命令以创建将在工作流中使用的外部 IP:
SERVICE_NAME=customer-service
kubectl expose deployment $SERVICE_NAME \
--type LoadBalancer --port 80 --target-port 8080
运行命令以验证创建的资源:
kubectl get all
示例输出:

4. 审核工作流程
Workflows 核心概念
工作流由使用 Workflows 语法(YAML 或 JSON)描述的一系列步骤组成。
工作流创建完毕后即会进行部署,这样工作流便可以执行。
执行是指单次运行工作流定义中包含的逻辑。尚未执行的工作流不会产生费用。所有工作流都将独立执行,并且产品的快速扩缩允许执行大量并发执行。
执行控制
- 步骤 - 如需创建工作流,您可以使用 Workflows 语法定义所需的
steps和执行顺序。每个工作流都必须至少有一个步骤。 - 条件 - 您可以使用
switch区块 作为选择机制,以允许表达式的值控制工作流的执行流。 - 迭代 - 您可以使用
for循环遍历一系列数字或通过列表或映射等数据集合。 - 子工作流 - 子工作流的工作方式与编程语言的例程或函数类似,您可以封装工作流将会多次重复执行的一个步骤或一组步骤。
触发执行
- 手动:您可以使用 Google Cloud CLI,通过 Google Cloud 控制台或命令行管理工作流。
- 以编程方式 - Workflows API 的 Cloud 客户端库或 REST API 可用于管理工作流。
- 已安排 - 您可以使用 Cloud Scheduler 按特定时间表运行工作流。
运行时实参
可通过在主工作流中添加 params 字段(放置在主块中)访问在运行时传递的数据。主块接受任何有效的 JSON 数据类型的单个参数。params 字段指定工作流用于存储您传入数据的变量。
工作流逻辑
如果客户不存在,工作流会先通过 API 调用创建客户,然后再更新奖励积分。工作流将根据订单总金额选择一个乘数,以计算客户的奖励积分。如需了解详情,请参阅以下示例。
- calculate_multiplier:
switch:
- condition: ${totalAmount < 10}
steps:
- set_multiplier1:
assign:
- multiplier: 2
- condition: ${totalAmount >= 10 and totalAmount < 25}
steps:
- set_multiplier2:
assign:
- multiplier: 3
- condition: ${totalAmount >= 25}
steps:
- set_multiplier3:
assign:
- multiplier: 5
- calculate_rewards:
assign:
- rewardPoints: ${customerRecord.rewardPoints + multiplier}

5. 配置和部署工作流
运行命令以查看服务的外部 IP 地址:
kubectl get svc
示例输出:

使用上一个输出中的外部 IP 值设置以下环境变量。
CUSTOMER_SERVICE_URL=http://$(kubectl get svc customer-service -o=jsonpath='{.status.loadBalancer.ingress[0].ip}')
替换工作流模板中的客户服务应用网址:
sed "s@CUSTOMER_SERVICE_URL@$CUSTOMER_SERVICE_URL@g" gkeRewardsWorkflow.yaml.tmpl > gkeRewardsWorkflow.yaml
为 Workflows 服务和项目环境变量设置位置:
gcloud config set workflows/location ${REGION}
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
export PROJECT_NAME=$(gcloud projects describe $PROJECT_ID --format='value(name)')
为工作流创建具有以下权限的自定义服务账号:
- 调用 Logging API
- 将消息发布到 Pub/Sub 主题
export WORKFLOW_SERVICE_ACCOUNT=workflows-sa
gcloud iam service-accounts create ${WORKFLOW_SERVICE_ACCOUNT}
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member "serviceAccount:${WORKFLOW_SERVICE_ACCOUNT}@$PROJECT_ID.iam.gserviceaccount.com" \
--role "roles/logging.logWriter"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member "serviceAccount:${WORKFLOW_SERVICE_ACCOUNT}@$PROJECT_ID.iam.gserviceaccount.com" \
--role "roles/pubsub.publisher"
部署工作流。工作流已配置为使用在上一步中创建的服务账号:
export WORKFLOW_NAME=rewardsWorkflow
gcloud workflows deploy ${WORKFLOW_NAME} \
--source=gkeRewardsWorkflow.yaml \
--service-account=${WORKFLOW_SERVICE_ACCOUNT}@$PROJECT_ID.iam.gserviceaccount.com
查看工作流来源和其他详细信息(“触发器”标签页)。目前,尚未配置任何触发器来执行此工作流。您将在下一步中进行设置。

6. 配置 Pub/Sub 主题和 Eventarc 触发器
接下来,您将创建两个 Pub/Sub 主题并配置一个 Eventarc 触发器。
订单服务应用将向 order-topic 发布有关新订单的消息。
工作流将向 order-points-topic 发布包含订单奖励积分和总金额的消息。订单服务(未部署,属于本实验的一部分)公开了一个端点,推送订阅使用该端点来更新每个订单的奖励积分和总金额。order-points-topic,
创建新的 Pub/Sub 主题:
export TOPIC_ID=order-topic
export ORDER_POINTS_TOPIC_ID=order-points-topic
gcloud pubsub topics create $TOPIC_ID --project=$PROJECT_ID
gcloud pubsub topics create $ORDER_POINTS_TOPIC_ID --project=$PROJECT_ID
为 Eventarc 服务设置位置:
gcloud config set eventarc/location ${REGION}
创建一个自定义服务账号,供 Eventarc 触发器用来执行工作流。
export TRIGGER_SERVICE_ACCOUNT=eventarc-workflow-sa
gcloud iam service-accounts create ${TRIGGER_SERVICE_ACCOUNT}
授予服务账号执行工作流的权限。
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${TRIGGER_SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/workflows.invoker"
创建 Eventarc 触发器以监听 Pub/Sub 消息并将其传递给 Workflows。
gcloud eventarc triggers create new-orders-trigger \
--destination-workflow=${WORKFLOW_NAME} \
--destination-workflow-location=${REGION} \
--event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
--service-account="${TRIGGER_SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
--transport-topic=$TOPIC_ID
示例输出:
Creating trigger [new-orders-trigger] in project [qwiklabs-gcp-01-1a990bfcadb3], location [us-east1]...done. Publish to Pub/Sub topic [projects/qwiklabs-gcp-01-1a990bfcadb3/topics/order-topic] to receive events in Workflow [rewardsWorkflow]. WARNING: It may take up to 2 minutes for the new trigger to become active.
查看已创建的 Eventarc 触发器。

查看为触发器创建的订阅。

查看工作流方面的更改。添加了新触发器。

7. 测试工作流

为了模拟订单服务,您将从 Cloud Shell 向 Pub/Sub 主题发送消息,并在 Cloud 控制台中验证客户服务日志。
export TOPIC_ID=order-topic
gcloud pubsub topics publish $TOPIC_ID --message '{"userId":"id1","orderNumber":123456,"name":"Angela Jensen","email":"ajensen9090+eats@gmail.com","address":"1845 Denise St","city":"Mountain View","state":"CA","zip":"94043","orderItems":[{"id":7,"createDateTime":"2022-03-17T21:51:44.968584","itemImageURL":"https://images.unsplash.com/photo-1618449840665-9ed506d73a34?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80","itemName":"Curry Plate","itemPrice":12.5,"itemThumbnailURL":"https://images.unsplash.com/photo-1618449840665-9ed506d73a34?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80","spiceLevel":0,"status":"Ready","tagLine":"Spicy touch for your taste buds","updateDateTime":"2022-03-18T01:30:29.340584","inventory":8,"quantity":1}]}'
示例输出:
messageIds: - '5063709859203105'
查看工作流执行详情和日志。


8. 工作流结构化日志记录
工作流配置为以 JSON 格式写入结构化日志。日志使用 Cloud Logging API、workflows.googleapis.com/Workflow 资源写入,并位于日志名称 projects/${PROJECT_ID}/logs/Workflows 下。
查看下方的日志记录配置。
- log_totalAmount:
call: sys.log
args:
json:
orderNumber: ${order.orderNumber}
totalAmount: ${totalAmount}
multiplier: ${multiplier}
totalRewardPoints: ${rewardPoints}
orderRewardPoints: ${orderRewardPoints}
severity: INFO
在 Cloud 控制台中打开日志浏览器,然后运行查询以查找总金额超过 2 美元的已处理订单。
如需显示搜索查询字段,请点击“显示查询”。

resource.type="workflows.googleapis.com/Workflow" AND
jsonPayload.totalAmount > 2 AND
timestamp >= "2023-01-01T00:00:00Z" AND
timestamp <= "2024-12-31T23:59:59Z"
示例输出:

打开 Cloud Shell 并使用以下命令通过 gcloud CLI 读取日志。
gcloud logging read 'resource.type="workflows.googleapis.com/Workflow" AND jsonPayload.totalAmount > 2 AND timestamp >= "2023-01-01T00:00:00Z" AND timestamp <= "2023-12-31T23:59:59Z"' --limit 10 --format="table(jsonPayload.orderNumber,jsonPayload.totalAmount,jsonPayload.orderRewardPoints,jsonPayload.totalRewardPoints,jsonPayload.multiplier)"
使用 table 格式的示例输出:

运行以下命令,以 JSON 格式返回日志:
gcloud logging read 'resource.type="workflows.googleapis.com/Workflow" AND jsonPayload.totalAmount > 2 AND timestamp >= "2023-01-01T00:00:00Z" AND timestamp <= "2023-12-31T23:59:59Z"' --limit 10 --format=json | jq
使用 json 格式的示例输出:

9. 查看客户记录
(可选步骤)
运行以下命令以设置客户服务网址环境变量。
CUSTOMER_SERVICE_URL=http://$(kubectl get svc customer-service -o=jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl $CUSTOMER_SERVICE_URL/customer | jq
示例输出:
[
{
"address": "1845 Denise St",
"city": "Mountain View",
"createDateTime": "2023-01-31T17:22:08.853644",
"email": "ajensen9090+eats@gmail.com",
"id": "id1",
"name": "Angela Jensen",
"rewardPoints": 4,
"state": "CA",
"updateDateTime": "2023-01-31T17:22:09.652117",
"zip": "94043"
}
]
多次运行命令以发布新订单,并使用 curl 命令验证客户奖励积分。
发布新订单消息:
export TOPIC_ID=order-topic
gcloud pubsub topics publish $TOPIC_ID --message '{"userId":"id1","orderNumber":123456,"name":"Angela Jensen","email":"ajensen9090+eats@gmail.com","address":"1845 Denise St","city":"Mountain View","state":"CA","zip":"94043","orderItems":[{"id":7,"createDateTime":"2022-03-17T21:51:44.968584","itemImageURL":"https://images.unsplash.com/photo-1618449840665-9ed506d73a34?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80","itemName":"Curry Plate","itemPrice":12.5,"itemThumbnailURL":"https://images.unsplash.com/photo-1618449840665-9ed506d73a34?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80","spiceLevel":0,"status":"Ready","tagLine":"Spicy touch for your taste buds","updateDateTime":"2022-03-18T01:30:29.340584","inventory":8,"quantity":1}]}'
验证客户奖励积分:
curl $CUSTOMER_SERVICE_URL/customer | jq
运行以下命令以检查最新日志:
gcloud logging read 'resource.type="workflows.googleapis.com/Workflow" AND jsonPayload.totalAmount > 2 AND timestamp >= "2023-01-01T00:00:00Z" AND timestamp <= "2023-12-31T23:59:59Z"' --limit 10 --format="table(jsonPayload.orderNumber,jsonPayload.totalAmount,jsonPayload.orderRewardPoints,jsonPayload.totalRewardPoints,jsonPayload.multiplier)"
10. 恭喜!
恭喜,您已完成此 Codelab!
所学内容:
- 如何配置 Pub/Sub 主题和 Eventarc 以触发 Workflows
- 如何配置工作流以向在 GKE Autopilot 上运行的应用发出 API 调用
- 如何配置工作流以将消息发布到 Pub/Sub
- 如何在 Cloud Logging 中使用 gcloud CLI 查询工作流结构化日志
后续步骤:
探索其他 Cymbal Eats Codelab:
- 使用 Eventarc 触发 Cloud Workflows
- 触发 Cloud Storage 中的事件处理
- 从 Cloud Run 连接到专用 CloudSQL
- 从 Cloud Run 连接到全托管式数据库
- 使用 Identity-Aware Proxy (IAP) 保护无服务器应用
- 使用 Cloud Scheduler 触发 Cloud Run 作业
- 安全地部署到 Cloud Run
- 保障 Cloud Run 入站流量安全
清理
为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。
删除项目
若要避免产生费用,最简单的方法是删除您为本教程创建的项目。