从 Cloud Run 连接到 Private CloudSQL

从 Cloud Run 连接到 Private CloudSQL

关于此 Codelab

subject上次更新时间:1月 24, 2023
account_circleameenahb 编写

1. 概览

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

19c7b05f35789fda

学习内容

在本实验中,您将学习如何完成以下操作:

  • 配置专用 VPC 网络
  • 创建专用 Postgres Cloud SQL 数据库
  • 将 CloudRun 连接到专用 VPC
  • 在 Cloud Run 上部署一项连接到 Cloud SQL 数据库的服务

2. 设置和要求

自定进度的环境设置

  1. 登录 Google Cloud 控制台,然后创建一个新项目或重复使用现有项目。如果您还没有 Gmail 或 Google Workspace 账号,则必须创建一个

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

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

环境设置

  1. 创建与项目和资源相关的环境变量
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
  1. 克隆代码库并导航到相应目录
git clone https://github.com/GoogleCloudPlatform/cymbal-eats.git && cd cymbal-eats/menu-service
  1. 启用服务
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 地址。

  1. 分配 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].
  1. 创建专用连接。
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 实例的生命周期内保持不变。

219cb722c2dd1b82

您将创建一个具有专用 IP 地址的 Postgres Cloud SQL 数据库。

创建数据库和用户

  1. 创建 Postgres Cloud SQL 实例以使用专用 IP
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
  1. 向数据库实例添加数据库
gcloud sql databases create $DB_DATABASE --instance=$DB_INSTANCE_NAME

输出示例

Created database [menu-db].
instance: menu-catalog
name: menu-db
project: cymbal1
  1. 创建 SQL 用户
gcloud sql users create ${DB_USER} \
   
--password=$DB_PASSWORD \
   
--instance=$DB_INSTANCE_NAME

输出示例

Created user [menu-user].
  1. 存储数据库 IP 地址
export DB_INSTANCE_IP=$(gcloud sql instances describe $DB_INSTANCE_NAME \
   
--format=json | jq \
   
--raw-output ".ipAddresses[].ipAddress")
  1. 将 Cloud SQL Client 角色添加到 Compute Engine 服务账号
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 等无服务器环境直接连接到 Virtual Private Cloud 网络。通过配置无服务器 VPC 访问通道,您的无服务器环境可以使用内部 DNS 和内部 IP 地址(如 RFC 1918 和 RFC 6598 所定义)向您的 VPC 网络发送请求。对这些请求的响应也会使用您的内部网络。

您将为 Cloud Run 服务创建一个无服务器 VPC 访问通道连接器,以连接到 Cloud SQL。

19c7b05f35789fda

  1. 在 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 数据库。

  1. 使用 Maven 编译应用
./mvnw package -DskipTests

输出示例

[...]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  42.864 s
[INFO] Finished at: 2022-04-28T16:15:33Z
[INFO] ------------------------------------------------------------------------
  1. 构建 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
  1. 将 Docker 映像推送到 Container Registry:
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
  1. 部署菜单服务:
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 作为环境变量传递或作为卷装载

  1. 商店菜单服务网址:
MENU_SERVICE_URL=$(gcloud run services describe menu-service \
 
--platform managed \
 
--region $REGION \
 
--format=json | jq \
 
--raw-output ".status.url")
  1. 验证菜单服务网址
echo $MENU_SERVICE_URL

输出示例

https://menu-service-g2mfphytdq-uk.a.run.app

7. 测试服务

  1. 通过发送 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"
}
  1. 通过发送 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:

清理

为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

删除项目

若要避免产生费用,最简单的方法是删除您为本教程创建的项目。