如何将 Cloud Run 上的 Node.js 应用连接到 Cloud SQL for PostgreSQL 数据库

1. 概览

Cloud SQL Node.js 连接器是安全地将 Node.js 应用连接到 Cloud SQL 数据库的最简单方式。Cloud Run 是一个完全托管的无服务器平台,供您运行可通过 HTTP 请求调用的无状态容器。此 Codelab 将演示如何使用 IAM 身份验证通过服务账号将 Cloud Run 上的 Node.js 应用安全地连接到 Cloud SQL for PostgreSQL 数据库。

学习内容

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

  • 创建 Cloud SQL 实例以用于 PostgreSQL 数据库
  • 将 Node.js 应用部署到 Cloud Run
  • 使用 Cloud SQL Node.js 连接器库将应用连接到数据库

前提条件

  • 本实验假设您熟悉 Cloud 控制台和 Cloud Shell 环境。

2. 准备工作

Cloud 项目设置

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

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 免费试用计划的条件。

环境设置

点击搜索栏右侧的图标,激活 Cloud Shell。

ecdc43ada29e91b.png

在 Cloud Shell 中,启用以下 API:

gcloud services enable compute.googleapis.com sqladmin.googleapis.com \
  run.googleapis.com artifactregistry.googleapis.com \
  cloudbuild.googleapis.com servicenetworking.googleapis.com

如果系统提示您进行授权,请点击“授权”以继续。

6356559df3eccdda.png

此命令可能需要几分钟时间才能完成,但最终应会生成类似如下所示的成功消息:

Operation "operations/acf.p2-327036483151-73d90d00-47ee-447a-b600-a6badf0eceae" finished successfully.

3. 设置服务账号

创建并配置供 Cloud Run 使用的 Google Cloud 服务账号,使其具有连接到 Cloud SQL 的相应权限。

  1. 按照以下方式运行 gcloud iam service-accounts create 命令来创建新的服务账号:
    gcloud iam service-accounts create quickstart-service-account \
      --display-name="Quickstart Service Account"
    
  2. 运行 gcloud projects add-iam-policy-binding 命令,将 Cloud SQL Client 角色添加到您刚创建的 Google Cloud 服务账号,如下所示。在 Cloud Shell 中,表达式 ${GOOGLE_CLOUD_PROJECT} 将替换为您的项目名称。如果您更喜欢手动替换,也可以这样做。
    gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
      --member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
      --role="roles/cloudsql.client"
    
  3. 运行以下 gcloud projects add-iam-policy-binding 命令,将 Cloud SQL Instance User 角色添加到您刚创建的 Google Cloud 服务账号。
    gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
      --member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
      --role="roles/cloudsql.instanceUser"
    
  4. 按如下所示运行 gcloud projects add-iam-policy-binding 命令,将 Log Writer 角色添加到您刚刚创建的 Google Cloud 服务账号。
    gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
      --member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
      --role="roles/logging.logWriter"
    

4. 设置 Cloud SQL

运行 gcloud sql instances create 命令以创建 Cloud SQL 实例。

  • --database-version:数据库引擎类型和版本。如果未指定,则使用 API 默认值。请参阅 gcloud 数据库版本文档,以查看当前可用版本。
  • --cpu:机器中所需的核心数。
  • --memory:表示机器所需内存数量的整数值。应该提供大小单位(例如 3072MB 或 9GB)。如果未指定单位,则假定为 GB。
  • --region:实例的区域位置(例如:us-central1、asia-east1、us-east1)。
  • --database-flags:允许设置标志。在本例中,我们开启了 cloudsql.iam_authentication,以使 Cloud Run 能够使用之前创建的服务账号连接到 Cloud SQL。
    gcloud sql instances create quickstart-instance \
      --database-version=POSTGRES_18 \
      --tier=db-custom-1-3840 \
      --region=us-central1 \
      --edition=ENTERPRISE \
      --database-flags=cloudsql.iam_authentication=on
    

此命令可能需要几分钟时间才能完成。

运行 gcloud sql databases create 命令以在 quickstart-instance 中创建 Cloud SQL 数据库。

gcloud sql databases create quickstart_db \
  --instance=quickstart-instance

为之前创建的服务账号创建一个 PostgreSQL 数据库用户,以便访问数据库。

gcloud sql users create quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam \
  --instance=quickstart-instance \
  --type=cloud_iam_service_account \
  --database-roles=postgres

警告:请勿在生产应用中使用 --database-roles=postgres。我们使用此权限来提供以编程方式创建和删除本实验中代码所需的表所需的权限。

5. 准备应用

准备一个可响应 HTTP 请求的 Node.js 应用。

  1. 在 Cloud Shell 中,创建一个名为 helloworld 的新目录,然后切换到该目录:
    mkdir helloworld
    cd helloworld
    
  2. package.json 文件初始化为模块。
    npm init -y
    npm pkg set type="module"
    npm pkg set main="index.mjs"
    npm pkg set scripts.start="node index.mjs"
    
  3. 安装 Cloud SQL Node.js 连接器依赖项。
    npm install @google-cloud/cloud-sql-connector
    
  4. 安装 pg 以与 PostgreSQL 数据库进行交互。
    npm install pg
    
  5. 安装 express 以接受传入的 HTTP 请求。
    npm install express
    
  6. 创建一个包含应用代码的 index.mjs 文件。此代码能够:
    • 接受 HTTP 请求
    • 连接到数据库
    • 将 HTTP 请求的时间存储在数据库中
    • 返回最近 5 次请求的时间
    在 Cloud Shell 中运行以下命令:
    cat > index.mjs << "EOF"
    import express from 'express';
    import pg from 'pg';
    import {Connector} from '@google-cloud/cloud-sql-connector';
    
    const {Pool} = pg;
    
    const connector = new Connector();
    const clientOpts = await connector.getOptions({
        instanceConnectionName: process.env.INSTANCE_CONNECTION_NAME,
        authType: 'IAM'
    });
    
    const pool = new Pool({
        ...clientOpts,
        user: process.env.DB_USER,
        database: process.env.DB_NAME
    });
    
    const app = express();
    
    app.get('/', async (req, res) => {
      await pool.query('INSERT INTO visits(created_at) VALUES(NOW())');
      const {rows} = await pool.query('SELECT created_at FROM visits ORDER BY created_at DESC LIMIT 5');
      console.table(rows); // prints the last 5 visits
      res.send(rows);
    });
    
    const port = parseInt(process.env.PORT) || 8080;
    app.listen(port, async () => {
      console.log('process.env: ', process.env);
      await pool.query(`CREATE TABLE IF NOT EXISTS visits (
        id SERIAL NOT NULL,
        created_at timestamp NOT NULL,
        PRIMARY KEY (id)
      );`);
      console.log(`helloworld: listening on port ${port}`);
    });
    
    EOF
    

这段代码会创建一个基本 Web 服务器,监听由 PORT 环境变量定义的端口。应用现已准备就绪,可以进行部署。

6. 部署 Cloud Run 应用

运行以下命令,将应用部署到 Cloud Run:

  • --region:实例的区域位置(例如:us-central1、asia-east1、us-east1)。
  • --source:要部署的源代码。在这种情况下,. 指的是当前文件夹 helloworld 中的源代码。
  • --set-env-vars:设置应用使用的环境变量,以将应用定向到 Cloud SQL 数据库。
  • --service-account:将 Cloud Run 部署与有权连接到本 Codelab 开头创建的 Cloud SQL 数据库的服务账号相关联。
  • --allow-unauthenticated:允许未经身份验证的请求,以便从互联网访问应用。
gcloud run deploy helloworld \
  --region=us-central1 \
  --source=. \
  --set-env-vars INSTANCE_CONNECTION_NAME="${GOOGLE_CLOUD_PROJECT}:us-central1:quickstart-instance" \
  --set-env-vars DB_NAME="quickstart_db" \
  --set-env-vars DB_USER="quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam" \
  --service-account="quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
  --allow-unauthenticated

如果系统提示您确认是否要继续,请按 yEnter

Do you want to continue (Y/n)? y

几分钟后,应用应会提供一个供您访问的网址。

前往相应网址,查看您的应用的实际效果。每次访问该网址或刷新页面时,您都会看到以 JSON 格式返回的最近 5 次访问记录。

7. 恭喜

您已在 Cloud Run 上部署了一个 Node.js 应用,该应用能够连接到在 Cloud SQL 上运行的 PostgreSQL 数据库。

所学内容:

  • 创建 Cloud SQL for PostgreSQL 数据库
  • 将 Node.js 应用部署到 Cloud Run
  • 使用 Cloud SQL Node.js 连接器将应用连接到 Cloud SQL

清理

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

gcloud projects delete ${GOOGLE_CLOUD_PROJECT}