1. 概览
在本实验中,您将创建 Cymbal Eats 菜单服务,公开 RESTful API 以添加、更新、删除和列出菜单项。您将创建一个 Cloud SQL 数据库作为菜单服务的后端数据库,该服务将在 Cloud Run 中运行。由于 Cloud Run 不与 Cloud SQL 数据库位于同一 VPC 中,因此您需要配置无服务器 VPC 访问通道连接器,以允许 Cloud Run 通过专用 IP 地址与 Cloud SQL 通信。

学习内容
在本实验中,您将学习如何完成以下操作:
- 配置专用 VPC 网络
- 创建专用 Postgres Cloud SQL 数据库
- 将 CloudRun 连接到专用 VPC
- 在 Cloud Run 上部署连接到 Cloud SQL 数据库的服务
2. 设置和要求
自定进度的环境设置
- 登录 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 免费试用计划的条件。
环境设置
- 创建项目和资源相关的环境变量
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)')
export REGION=us-east1
export MENU_SERVICE_NAME=menu-service
export SERVERLESS_VPC_CONNECTOR=cymbalconnector
export DB_INSTANCE_NAME=menu-catalog
export DB_INSTANCE_PASSWORD=password123
export DB_DATABASE=menu-db
export DB_USER=menu-user
export DB_PASSWORD=menupassword123
- 克隆代码库并前往相应目录
git clone https://github.com/GoogleCloudPlatform/cymbal-eats.git && cd cymbal-eats/menu-service
- 启用服务
gcloud services enable \
sqladmin.googleapis.com \
run.googleapis.com \
vpcaccess.googleapis.com \
servicenetworking.googleapis.com
3. 配置专用访问通道
专用服务访问通道是作为您的 VPC 网络与 Cloud SQL 实例所在的底层 Google Cloud VPC 网络之间的 VPC 对等互连链接提供的。通过专用连接,您的 VPC 网络中的虚拟机实例和您使用的服务只能通过内部 IP 地址进行通信。如需访问通过专用服务访问通道提供的服务,虚拟机实例不需要互联网连接或外部 IP 地址。
- 分配 IP 地址范围
gcloud compute addresses create google-managed-services-default \
--global \
--purpose=VPC_PEERING \
--prefix-length=20 \
--network=projects/$PROJECT_ID/global/networks/default
输出示例
Created [https://www.googleapis.com/compute/v1/projects/cymbal-eats-2-348215/global/addresses/google-managed-services-default].
- 创建专用连接。
gcloud services vpc-peerings connect \
--service=servicenetworking.googleapis.com \
--ranges=google-managed-services-default \
--network=default \
--project=$PROJECT_ID
输出示例
Operation "operations/pssn.p24-528514492617-2f2b507f-e4e5-4d53-a4de-9ddaceb4e92f" finished successfully.
4. 设置 Cloud SQL
Cloud SQL 是一种全托管式数据库服务,可让您轻松地在云端设置、维护、管理和控制关系型 PostgreSQL 及 MySQL 数据库。每个 Cloud SQL 实例都由一个在 Google Cloud 主机服务器上运行的虚拟机 (VM) 提供支持。高可用性选项还在另一个可用区中提供备用虚拟机,其设置与主虚拟机相同。该数据库存储在可连接到虚拟机的可扩缩、持久的网络存储设备(称为永久性磁盘)中。每个虚拟机都会分配一个静态 IP 地址,以确保应用连接到的 IP 地址在 Cloud SQL 实例的整个生命周期中都保持不变。

您将创建一个使用专用 IP 地址的 Postgres Cloud SQL 数据库。
创建数据库和用户
- 创建使用专用 IP 的 Postgres Cloud SQL 实例
gcloud sql instances create $DB_INSTANCE_NAME \
--project=$PROJECT_ID \
--network=projects/$PROJECT_ID/global/networks/default \
--no-assign-ip \
--database-version=POSTGRES_12 \
--cpu=2 \
--memory=4GB \
--region=$REGION \
--root-password=${DB_INSTANCE_PASSWORD}
输出示例
Created [https://sqladmin.googleapis.com/sql/v1beta4/projects/cymbal1/instances/menu-instance]. NAME: menu-instance DATABASE_VERSION: POSTGRES_12 LOCATION: us-east1-a TIER: db-custom-2-4096 PRIMARY_ADDRESS: - PRIVATE_ADDRESS: 10.8.80.5 STATUS: RUNNABLE
- 向数据库实例添加数据库
gcloud sql databases create $DB_DATABASE --instance=$DB_INSTANCE_NAME
输出示例
Created database [menu-db]. instance: menu-catalog name: menu-db project: cymbal1
- 创建 SQL 用户
gcloud sql users create ${DB_USER} \
--password=$DB_PASSWORD \
--instance=$DB_INSTANCE_NAME
输出示例
Created user [menu-user].
- 存储数据库 IP 地址
export DB_INSTANCE_IP=$(gcloud sql instances describe $DB_INSTANCE_NAME \
--format=json | jq \
--raw-output ".ipAddresses[].ipAddress")
- 向 Compute Engine 服务账号添加 Cloud SQL Client 角色
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
--role="roles/cloudsql.client"
输出示例
Updated IAM policy for project [cymbal1]. [...]
5. 无服务器 VPC
通过无服务器 VPC 访问通道,您可以从无服务器环境(例如 Cloud Run、App Engine 或 Cloud Functions)直接连接到虚拟私有云网络。通过配置无服务器 VPC 访问通道,无服务器环境可以使用内部 DNS 和内部 IP 地址(如 RFC 1918 和 RFC 6598 所定义)向 VPC 网络发送请求。对这些请求的响应也使用您的内部网络。
您将创建一个无服务器 VPC 访问通道连接器,以便 Cloud Run 服务连接到 Cloud SQL。

- 在 Cloud SQL 实例所在的同一 VPC 网络中创建无服务器 VPC 访问通道连接器。
gcloud compute networks vpc-access connectors create ${SERVERLESS_VPC_CONNECTOR} \
--region=${REGION} \
--range=10.8.0.0/28
输出示例
Created connector [cymbalconnector].
6. 部署到 Cloud Run
您将构建 Docker 映像并将其部署到 Cloud Run,然后将 Cloud Run 连接到无服务器 VPC 连接器,以访问 Cloud SQL 数据库。
- 使用 Maven 编译应用
./mvnw package -DskipTests
输出示例
[...] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 42.864 s [INFO] Finished at: 2022-04-28T16:15:33Z [INFO] ------------------------------------------------------------------------
- 构建 Docker 映像:
docker build -f src/main/docker/Dockerfile.jvm \
--tag gcr.io/$PROJECT_NAME/menu-service .
输出示例
[...] Successfully built 4ef5d7a3befc Successfully tagged gcr.io/cymbal1/menu-service:latest
- 将 Docker 映像推送到容器注册表:
docker push gcr.io/$PROJECT_NAME/menu-service
输出示例
Using default tag: latest The push refers to repository [gcr.io/cymbalsql/menu-service] 17b374963800: Pushed d9a51c06430d: Pushed fff5d2a2cfc9: Pushed f21fceb558c6: Pushed 5ffbbbf218dd: Pushed 60609ec85f86: Layer already exists f2c4302f03b8: Layer already exists latest: digest: sha256:f64cb7c288dbf4ad9b12bd210c23c5aec1048dee040450ff2d9dbdf96e83a426 size: 1789
- 部署菜单服务:
gcloud run deploy $MENU_SERVICE_NAME \
--image=gcr.io/$PROJECT_NAME/menu-service:latest \
--region $REGION \
--allow-unauthenticated \
--set-env-vars DB_USER=$DB_USER \
--set-env-vars DB_PASS=$DB_PASSWORD \
--set-env-vars DB_DATABASE=$DB_DATABASE \
--set-env-vars DB_HOST=$DB_INSTANCE_IP \
--vpc-connector $SERVERLESS_VPC_CONNECTOR \
--project=$PROJECT_ID \
--quiet
输出示例
[...] Done. Service [menu-service] revision [menu-service-00002-xox] has been deployed and is serving 100 percent of traffic. Service URL: https://menu-service-g2mfphytdq-uk.a.run.app
Google 建议您使用 Secret Manager 存储 SQL 凭据等敏感信息。您可以使用 Cloud Run 将 Secret 作为环境变量传递或装载为卷。
- 商店菜单服务网址:
MENU_SERVICE_URL=$(gcloud run services describe menu-service \
--platform managed \
--region $REGION \
--format=json | jq \
--raw-output ".status.url")
- 验证菜单服务网址
echo $MENU_SERVICE_URL
输出示例
https://menu-service-g2mfphytdq-uk.a.run.app
7. 测试服务
- 通过发送 POST 请求创建新的菜单项:
curl -X POST "${MENU_SERVICE_URL}/menu" \
-H 'Content-Type: application/json' \
-d '{
"itemImageURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
"itemName": "Curry Plate",
"itemPrice": 12.5,
"itemThumbnailURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
"spiceLevel": 3,
"status": "Ready",
"tagLine": "Spicy touch for your taste buds!!"
}'
输出示例
{
"id": 16,
"createDateTime": "2022-04-28T18:14:04.17225",
"itemImageURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
"itemName": "Curry Plate",
"itemPrice": 12.5,
"itemThumbnailURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
"spiceLevel": 3,
"status": "Processing",
"tagLine": "Spicy touch for your taste buds!!",
"updateDateTime": "2022-04-28T18:14:04.172298"
}
- 通过发送 PUT 请求来更改菜单项的状态:
curl -X PUT "${MENU_SERVICE_URL}/menu/1" \
-H 'Content-Type: application/json' \
-d '{"status": "Ready"}'
输出示例
{
"id": 1,
"createDateTime": "2022-04-28T17:21:02.369093",
"itemImageURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
"itemName": "Curry Plate",
"itemPrice": 12.50,
"itemThumbnailURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
"spiceLevel": 0,
"status": "Ready",
"tagLine": "Spicy touch for your taste buds!!",
"updateDateTime": "2022-04-28T17:21:02.657636"
}
8. 恭喜!
恭喜,您已完成此 Codelab!
后续步骤:
探索其他 Cymbal Eats Codelab:
- 使用 Eventarc 触发 Cloud Workflows
- 触发 Cloud Storage 中的事件处理
- 从 Cloud Run 连接到全代管式数据库
- 使用 Identity Aware Proxy (IAP) 保护无服务器应用
- 使用 Cloud Scheduler 触发 Cloud Run 作业
- 安全地部署到 Cloud Run
- 保护 Cloud Run 入站流量的安全
- 从 GKE Autopilot 连接到专用 AlloyDB
清理
为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。
删除项目
若要避免产生费用,最简单的方法是删除您为本教程创建的项目。