在 Google 云上从云 运行 访问云 SQL

Accessing Cloud SQL from Cloud Run on Google Cloud

我有一个云 运行 服务,它通过 SQLAlchemy 访问云 SQL 实例。但是,在 Cloud 运行 的日志中,我看到 CloudSQL connection failed. Please see https://cloud.google.com/sql/docs/mysql/connect-run for additional details: ensure that the account has access to "<connection_string>"。转到 link,它说:

“默认情况下,您的应用将使用云 运行(完全托管)服务帐户授权您的连接。服务帐户的格式为 PROJECT_NUMBER-compute@developer.gserviceaccount.com。”

然而,下面的 (https://cloud.google.com/run/docs/securing/service-identity) 表示:

”默认情况下,Cloud 运行 修订版使用 Compute Engine 默认服务帐户 (PROJECT_NUMBER-compute@developer.gserviceaccount.com),该帐户具有项目 > 编辑 IAM 角色。这意味着默认情况下,您的 Cloud 运行 修订版具有对 Google Cloud 项目中所有资源的读写权限。"

那么这不应该意味着 Cloud 运行 已经可以访问 SQL 了吗?我已经在云 运行 部署页面中设置了云 SQL 连接。您建议我如何允许从 Cloud 运行 访问 Cloud SQL?

编辑:我必须启用云 SQL API。

否,云 运行 默认无法访问云 SQL。您需要遵循两条路径之一。

  1. 使用本地 unix 套接字文件连接到 SQL:您需要像您所说的那样配置权限,并使用指示连接到数据库的意图的标志进行部署。关注 https://cloud.google.com/sql/docs/mysql/connect-run

  2. 使用私有 IP 连接到 SQL:这涉及将 Cloud SQL 实例部署到 VPC 网络中,并因此获得私有 IP 地址。然后使用 Cloud 运行 VPC Access Connector(目前为测试版)允许 Cloud 运行 容器能够连接到该 VPC 网络,其中直接包括 SQL 数据库的 IP 地址(无 IAM 权限)需要)。关注 https://cloud.google.com/vpc/docs/configure-serverless-vpc-access

云SQL代理解决方案

我使用cloud-sql-proxy在Cloud Build提供的workspace目录下创建本地unix socket文件

主要步骤如下:

  1. 拉取一个 Berglas 容器,用 _VAR1 替换填充它的调用,这是一个我使用 Berglas 加密的环境变量,名为 CMCREDENTIALS。您应该根据需要添加任意数量的 _VAR{n}
  2. 通过 wget 安装云sql代理。
  3. 运行 一个中间步骤(针对此构建的测试)。此步骤使用存储在提供的临时 /workspace 目录中的变量。
  4. 建立你的形象。
  5. 推送你的图片。
  6. 使用云 运行,部署并包含标志 --set-environment-variables

完整cloudbuild.yaml

# basic cloudbuild.yaml
steps:
# pull the berglas container and write the secrets to temporary files 
# under /workspace
  - name: gcr.io/berglas/berglas
    id: 'Install Berglas'
    env:
    - '${_VAR1}=berglas://${_BUCKET_ID_SECRETS}/${_VAR1}?destination=/workspace/${_VAR1}'

    args: ["exec", "--", "/bin/sh"]

# install the cloud sql proxy
  - id: 'Install Cloud SQL Proxy'
    name: alpine:latest
    entrypoint: sh
    args:
      - "-c"
      - "\
      wget -O /workspace/cloud_sql_proxy \
      https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 && \
      sleep 2 && \
      chmod +x /workspace/cloud_sql_proxy"
    waitFor: ['-']

# using the secrets from above, build and run the test suite
  - name: 'python:3.8.3-slim'
    id: 'Run Unit Tests'
    entrypoint: '/bin/bash'
    args: 
      - "-c"
      - "\
      (/workspace/cloud_sql_proxy -dir=/workspace/${_SQL_PROXY_PATH} -instances=${_INSTANCE_NAME1} & sleep 2) && \
      apt-get update && apt-get install -y --no-install-recommends \
      build-essential libssl-dev libffi-dev libpq-dev python3-dev wget && \
      rm -rf /var/lib/apt/lists/* && \
      export ${_VAR1}=$(cat /workspace/${_VAR1}) && \ 
      export INSTANCE_NAME1=${_INSTANCE_NAME1} && \
      export SQL_PROXY_PATH=/workspace/${_SQL_PROXY_PATH} && \
      pip install -r dev-requirements.txt && \
      pip install -r requirements.txt && \
      python -m pytest -v && \
      rm -rf /workspace/${_SQL_PROXY_PATH} && \
      echo 'Removed Cloud SQL Proxy'"
    
    waitFor: ['Install Cloud SQL Proxy', 'Install Berglas']
    dir: '${_APP_DIR}'

# Using the application/Dockerfile build instructions, build the app image
  - name: 'gcr.io/cloud-builders/docker'
    id: 'Build Application Image'
    args: ['build',
           '-t',
           'gcr.io/$PROJECT_ID/${_IMAGE_NAME}',
           '.',
          ]
    dir: '${_APP_DIR}'

# Push the application image
  - name: 'gcr.io/cloud-builders/docker'
    id: 'Push Application Image'
    args: ['push',
           'gcr.io/$PROJECT_ID/${_IMAGE_NAME}',
          ]

# Deploy the application image to Cloud Run
# populating secrets via Berglas exec ENTRYPOINT for gunicorn
  - name: 'gcr.io/cloud-builders/gcloud'
    id: 'Deploy Application Image'
    args: ['beta', 
           'run',
           'deploy', 
           '${_IMAGE_NAME}',
           '--image',
           'gcr.io/$PROJECT_ID/${_IMAGE_NAME}',
           '--region',
           'us-central1',
           '--platform', 
           'managed',
           '--quiet',
           '--add-cloudsql-instances',
           '${_INSTANCE_NAME1}',
           '--set-env-vars',
           'SQL_PROXY_PATH=/${_SQL_PROXY_PATH},INSTANCE_NAME1=${_INSTANCE_NAME1},${_VAR1}=berglas://${_BUCKET_ID_SECRETS}/${_VAR1}',
           '--allow-unauthenticated',
           '--memory',
           '512Mi'
          ]

# Use the defaults below which can be changed at the command line
substitutions:
  _IMAGE_NAME: your-image-name
  _BUCKET_ID_SECRETS: your-bucket-for-berglas-secrets
  _INSTANCE_NAME1: project-name:location:dbname
  _SQL_PROXY_PATH: cloudsql
  _VAR1: CMCREDENTIALS


# The images we'll push here
images: [
  'gcr.io/$PROJECT_ID/${_IMAGE_NAME}'
]

Dockerfile 利用

下面从包含 inside 目录 <myrepo>/application 的源构建了一个 Python 应用程序。这个 dockerfile 位于 application/Dockerfile.

# Use the official lightweight Python image.
# https://hub.docker.com/_/python
FROM python:3.8.3-slim

# Add build arguments
# Copy local code to the container image.
ENV APP_HOME /application

WORKDIR $APP_HOME

# Install production dependencies.
RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential \
    libpq-dev \
    python3-dev \
    libssl-dev \
    libffi-dev \
    && rm -rf /var/lib/apt/lists/*

# Copy the application source
COPY . ./

# Install Python dependencies
RUN pip install -r requirements.txt --no-cache-dir

# Grab Berglas from Google Cloud Registry
COPY --from=gcr.io/berglas/berglas:latest /bin/berglas /bin/berglas

# Run the web service on container startup. Here we use the gunicorn
# webserver, with one worker process and 8 threads.
# For environments with multiple CPU cores, increase the number of workers
# to be equal to the cores available.
ENTRYPOINT exec /bin/berglas exec -- gunicorn --bind :$PORT --workers 1 --threads 8 app:app 

希望这对某人有所帮助,尽管对于原始 OP 来说可能过于具体 (Python + Berglas)。