在Google Cloud Build期间在Google Cloud SQL上运行Node.js数据库迁移

21

我希望在Cloud Build过程中运行用Node.js编写的数据库迁移。

目前,虽然正在执行数据库迁移命令,但似乎Cloud Build过程无法通过用户名/密码连接到Cloud SQL的IP地址。

5个回答

38
在使用Cloud SQLNode.js的情况下,它会看起来像这样:
steps:
  # Install Node.js dependencies
  - id: yarn-install
    name: node:18
    entrypoint: yarn
    args: ["install", "--frozen-lockfile"]
    waitFor: ["-"]

  # Install Cloud SQL proxy
  - id: proxy-install
    name: node:18
    entrypoint: sh
    args:
      - "-c"
      - "wget https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.4.0/cloud-sql-proxy.linux.amd64 -O cloud_sql_proxy && chmod +x cloud_sql_proxy"
    waitFor: ["-"]

  # Migrate database schema to the latest version
  - id: migrate
    name: node:18
    entrypoint: sh
    args:
      - "-c"
      - "mkdir /cloudsql; chmod 777 /cloudsql; (./cloud_sql_proxy --unix-socket /cloudsql <CLOUD_SQL_CONNECTION> & sleep 2) && yarn knex migrate:latest"
    timeout: "1200s"
    waitFor: ["yarn-install", "proxy-install"]
timeout: "1200s"

你需要同时运行yarn install和下载Cloud SQL Proxy。完成这两个步骤后,你可以启动代理,等待2秒钟,最后运行yarn knex migrate:latest
为了使其正常工作,你需要在GCP项目中启用Cloud SQL Admin API
其中<CLOUD_SQL_INSTANCE>是你的Cloud SQL实例连接名称,可以在此处找到here。相同的名称将用于你的SQL连接设置,例如host=/cloudsql/example:us-central1:pg13
另外,请确保Cloud Build服务帐号在所在的GCP项目中具有"Cloud SQL Client"角色,该项目中包含数据库实例。

1
那看起来非常完美,感谢伙计。我今晚会试一下并告诉你结果。 - Francis Malloch
1
运行良好!对于那些没有阅读Konstantin总结的人来说,诀窍在于Google Cloud SQL代理和迁移的挂载是异步进行的,因为一旦启动Cloud SQL代理,它就会保持打开状态。不过需要注意的是,请记得将Google Cloud SQL客户端IAM权限添加到Google Cloud Build IAM服务帐户中。 - Francis Malloch
3
你遇到了连接本地主机的问题吗?我也遇到了一个问题,似乎云SQL代理已成功连接,并显示“正在接受127.0.0.1:5432的连接”,但当我尝试连接时,出现“ECONNREFUSED 127.0.0.1:5432”的错误信息。在我的本地机器上,这个操作完全正常。它们都是同一个卷的一部分。 - clive alton
1
SO上的点赞不够!请注意,对于类似运行Django测试的用例,您可能需要更多的Cloud SQL客户端角色,因为测试可能涉及创建数据库。 - thclark
1
不适用于最新的镜像 gcr.io/cloudsql-docker/gce-proxy v1.16,因为切换到了没有 shell 的 distroless 镜像。更多信息请参阅官方问题 https://github.com/GoogleCloudPlatform/cloudsql-proxy/issues/317。目前您可以使用 v1.15 或替代方法:https://github.com/GoogleCloudPlatform/cloudsql-proxy/issues/317#issuecomment-542847036。 - pufface
显示剩余3条评论

11

截至gcr.io/cloudsql-docker/gce-proxy的标签1.16,目前接受的答案不再适用。这里有一种不同的方法,可以使代理与需要它的命令保持在同一步骤中:

  - id: cmd-with-proxy
    name: [YOUR-CONTAINER-HERE]
    timeout: 100s
    entrypoint: sh
    args:
      - -c
      - '(/workspace/cloud_sql_proxy -dir=/workspace -instances=[INSTANCE_CONNECTION_NAME] & sleep 2) && [YOUR-COMMAND-HERE]'

主进程退出后,代理将自动退出。另外,如果代理或给定的命令失败,它将将步骤标记为“ERROR”。

这要求二进制文件在 /workspace 卷中,但可以通过手动提供或通过类似以下的先决步骤来提供:

  - id: proxy-install
    name: alpine:3.10
    entrypoint: sh
    args:
      - -c
      - 'wget -O /workspace/cloud_sql_proxy https://storage.googleapis.com/cloudsql-proxy/v1.16/cloud_sql_proxy.linux.386 &&  chmod +x /workspace/cloud_sql_proxy'

此外,由于代理与命令在同一个容器中,因此应该可以使用TCP。


Cloud SQL Proxy v2 更改了参数,因此此示例将改为 '(/workspace/cloud_sql_proxy INSTANCE_CONNECTION_NAME & sleep 2) && [YOUR-COMMAND-HERE]',否则步骤保持不变,并按照描述的方式工作。 - anothermh

2

使用google-appengine/exec-wrapper。它是一个专门用于此目的的镜像。使用方法(请参见链接中的README):

steps:
- name: "gcr.io/google-appengine/exec-wrapper"
  args: ["-i", "gcr.io/my-project/appengine/some-long-name",
         "-e", "ENV_VARIABLE_1=value1", "-e", "ENV_2=value2",
         "-s", "my-project:us-central1:my_cloudsql_instance",
         "--", "bundle", "exec", "rake", "db:migrate"]
-s参数设置代理目标。

2
如果您正在内部容器中运行指定为“-i”参数的脚本,那么嵌套内部容器的主机将是什么?127.0.0.1似乎不起作用。我正在尝试使用此方法在exec-wrapper容器中运行flyway容器。 - Kavi Sek

1

Cloud Build使用服务帐户运行,看起来您需要为此帐户授予访问Cloud SQL的权限。您可以在此处找到有关设置服务帐户权限的其他信息。


我尝试着按照这个思路去做,将 Cloud SQL 角色添加到 Cloud Build IAM 中。但是不太成功。 - Francis Malloch
你尝试在本地运行构建了吗?https://cloud.google.com/cloud-build/docs/build-debug-locally。它在您的帐户下运行,如果它能正常工作 - 问题可能是权限,否则可能是其他地方的问题。 - Roman Patutin
这不是一个坏主意。我很快就会尝试一下,这肯定是一种更容易调试的方法。 - Francis Malloch

1
这里是如何结合Cloud Build + Cloud SQL Proxy + Docker的方法。
如果您在Cloud Build中的Docker容器中运行数据库迁移/操作,它将无法直接访问您的代理,因为Docker容器与主机隔离。
以下是我成功实现的内容:
  - id: build
    # Build your application
    waitFor: ['-']

  - id: install-proxy
    name: gcr.io/cloud-builders/wget
    entrypoint: bash
    args:
      - -c
      - wget -O /workspace/cloud_sql_proxy https://storage.googleapis.com/cloudsql-proxy/v1.15/cloud_sql_proxy.linux.386 && chmod +x /workspace/cloud_sql_proxy
    waitFor: ['-']

  - id: migrate
    name: gcr.io/cloud-builders/docker
    entrypoint: bash
    args:
      - -c
      - |
        /workspace/cloud_sql_proxy -dir=/workspace -instances=projectid:region:instanceid & sleep 2 && \
        docker run -v /workspace:/root \
        --env DATABASE_HOST=/root/projectid:region:instanceid \
        # Pass other necessary env variables like db username/password, etc.
        $_IMAGE_URL:$COMMIT_SHA
    timeout: '1200s'
    waitFor: [build, install-proxy]

因为我们的数据库操作是在Docker容器内进行的,我发现提供访问Cloud SQL的最佳方式是通过指定Unix套接字-dir/workspace而不是暴露TCP端口5432。
注意:我建议在Cloud Build中使用目录/workspace而不是/cloudsql
然后,我们将/workspace目录挂载到Docker容器的/root目录,这是您的应用程序代码所在的默认目录。当我尝试将其挂载到除/root以外的其他目录时,似乎什么也没有发生(可能是权限问题,没有错误输出)。
另外:我注意到代理版本1.15效果很好。我在更新版本中遇到了问题。你的情况可能有所不同。

我花了几天时间尝试让这个工作......就像你说的一样,当复制到根目录时,它会神奇地工作 - 否则就不行。感谢你的提示...我希望我知道为什么会这样。 - bengro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接