【问题标题】:Run node.js database migrations on Google Cloud SQL during Google Cloud Build在 Google Cloud Build 期间在 Google Cloud SQL 上运行 node.js 数据库迁移
【发布时间】:2019-02-20 10:55:33
【问题描述】:

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

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

【问题讨论】:

    标签: google-cloud-platform google-cloud-sql google-cloud-build


    【解决方案1】:

    Cloud SQLNode.js 的情况下,它看起来像这样:

    steps:
      # Install Node.js dependencies
      - id: yarn-install
        name: gcr.io/cloud-builders/yarn
        waitFor: ["-"]
    
      # Install Cloud SQL proxy
      - id: proxy-install
        name: gcr.io/cloud-builders/yarn
        entrypoint: sh
        args:
          - "-c"
          - "wget https://storage.googleapis.com/cloudsql-proxy/v1.20.1/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy && chmod +x cloud_sql_proxy"
        waitFor: ["-"]
    
      # Migrate database schema to the latest version
      # https://knexjs.org/#Migrations-CLI
      - id: migrate
        name: gcr.io/cloud-builders/yarn
        entrypoint: sh
        args:
          - "-c"
          - "(./cloud_sql_proxy -dir=/cloudsql -instances=<CLOUD_SQL_CONNECTION> & sleep 2) && yarn run knex migrate:latest"
        timeout: "1200s"
        waitFor: ["yarn-install", "proxy-install"]
    
    timeout: "1200s"
    

    您将同时启动yarn install 并下载Cloud SQL Proxy。完成这两个步骤后,运行启动代理,等待 2 秒,最后运行 yarn run knex migrate:latest

    为此,您需要在 GCP 项目中启用 Cloud SQL Admin API

    &lt;CLOUD_SQL_INSTANCE&gt; 是您的 Cloud SQL 实例连接名称,可以在 here 中找到。 SQL 连接设置中将使用相同的名称,例如host=/cloudsql/example:us-central1:pg13.

    另外,请确保 Cloud Build 服务帐号在数据库实例所在的 GCP 项目中具有“Cloud SQL Client”角色。

    【讨论】:

    • 这看起来很完美,干杯伙伴。今晚我会试一试,然后告诉你进展如何。
    • 效果很好!对于那些没有阅读 Konstantin 总结的人来说,这个技巧是 Google Cloud SQL 代理的安装和迁移以异步方式发生,因为一旦您启动 Cloud SQL 代理,它就会保持打开状态。不过要提一件事,请记住将 Google Cloud SQL 客户端 IAM 权限添加到 Google Cloud Build IAM 服务帐户。
    • 您是否遇到了无法连接到本地主机的问题?我遇到了一个问题,看起来云 sql 代理成功连接,它甚至说“接受 127.0.0.1:5432 上的连接”,但是当我尝试连接时,它显示“ECONNREFUSED 127.0.0.1:5432”。这在我的本地机器上完美运行。它们都是同一卷的一部分。
    • 对 SO 的支持不足!请注意,对于运行 django 测试等类似用例,您可能需要的不仅仅是 Cloud SQL 客户端角色,因为测试可能涉及创建数据库。
    • 不适用于最新的镜像 gcr.io/cloudsql-docker/gce-proxy v1.16,因为切换到没有 shell 的 distroless 镜像。更多信息在官方问题github.com/GoogleCloudPlatform/cloudsql-proxy/issues/317。现在您可以使用 v1.15 或替代方法:github.com/GoogleCloudPlatform/cloudsql-proxy/issues/…
    【解决方案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 设置代理目标。

    【讨论】:

    • 如果您在“-i”参数中指定的内部容器内运行脚本。嵌套内部容器的主机是什么。 127.0.0.1 似乎不起作用。我正在尝试使用这种方法在 exec-wrapper 容器中运行 flyway 容器。
    【解决方案3】:

    以下是 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]
    

    因为我们的 db 操作是在 Docker 容器中进行的,所以我找到了通过指定 Unix 套接字 -dir/workspace 而不是暴露 TCP 端口 5432 来提供对 Cloud SQL 的访问的最佳方法。

    注意:对于 Cloud Build,我建议使用目录 /workspace 而不是 /cloudsql

    然后我们将/workspace 目录挂载到Docker 容器的/root 目录,这是您的应用程序代码所在的默认目录。当我尝试将其挂载到 /root 以外的位置时,似乎什么也没发生(可能是权限问题,没有错误输出)。

    另外:我注意到代理版本 1.15 运行良好。我遇到了新版本的问题。您的里程可能会有所不同。

    【讨论】:

    • 我花了几天时间试图完成这项工作......正如你所说,当复制到根目录时它神奇地工作 - 否则,它不会。谢谢你的提示......我希望我知道为什么会这样。
    【解决方案4】:

    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]'
    

    一旦主进程退出,代理将自动退出。此外,如果代理或给定的命令失败,它将将该步骤标记为“错误”。

    这确实要求二进制文件位于 /workspace 卷中,但这可以手动提供,也可以通过如下的 prereq 步骤提供:

      - 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,因为代理将与命令位于同一容器中。

    【讨论】:

      【解决方案5】:

      Cloud Build 使用服务帐号运行,您似乎需要为此帐号授予对 Cloud SQL 的访问权限。 您可以找到有关设置服务帐户权限的更多信息here

      【讨论】:

      • 我尝试了类似的方法,将 Cloud SQL 角色添加到 Cloud Build IAM。运气不太好。
      • 您是否尝试在本地运行构建? cloud.google.com/cloud-build/docs/build-debug-locally。它在您的帐户下运行,如果它可以正常工作 - 权限问题,如果没有 - 其他地方的问题。
      • 这不是一个坏主意。我很快就会试一试,肯定是一种更简单的调试方法。
      猜你喜欢
      • 2021-11-24
      • 2020-10-25
      • 2021-08-27
      • 2021-03-27
      • 1970-01-01
      • 2021-05-22
      • 1970-01-01
      • 2021-09-01
      • 2017-11-21
      相关资源
      最近更新 更多