如何将 appengine 连接到 vpc-connector

发布于 2025-01-15 05:44:34 字数 4827 浏览 6 评论 0原文

我有一个部署到 Cloud Run 的 django 项目。它使用两个 GCP 资源 - 一个 Postgres 数据库和一个用于缓存的 Redis MemoryStore 实例。

Redis 实例只能连接到 Serverless VPC,这是一项需要额外费用的额外服务。因此,为了最大限度地降低成本,我设置了一个共享 VPC,并在多个项目之间共享 Redis 实例(每个项目都有自己唯一的键前缀,以防止键冲突)。

我已经成功让我的 Cloud Run 容器连接到 Redis,但我还没有弄清楚如何让 Cloud Build 过程中的 appengine 运行程序连接到 Redis。在更新代码时,您总是希望 Django 首先进行迁移以应用数据库架构更改。随后还应该清除 redis。因此,我需要为 appengine 运行程序提供对我的 vpc 连接器的访问权限。

我的 cloudbuild.yml 文件(在我成功将 redis 连接到迁移/清除 redis 步骤之前):

steps:
  - id: "build image"
    name: "gcr.io/cloud-builders/docker"
    args: ["build", "-t", "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}:$COMMIT_SHA", "."]

  - id: "push image"
    name: "gcr.io/cloud-builders/docker"
    args: ["push", "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}:$COMMIT_SHA"]

  - id: "apply migrations, purge redis"
    name: "gcr.io/google-appengine/exec-wrapper"
    vpc_access_connector:
      name: projects/<my-project>/locations/us-central1/connectors/redis
    args:
      [
        "-i",
        "gcr.io/$PROJECT_ID/${_SERVICE_NAME}:$COMMIT_SHA",
        "-s",
        "${PROJECT_ID}:${_DEPLOY_REGION}:${_DATABASE_INSTANCE}",
        "-e",
        "SETTINGS_NAME=${_SECRET_SETTINGS_NAME},REDISHOST=${_REDIS_HOST},REDISPORT=${_REDIS_PORT},BUILD_ID=$BUILD_ID,CLOUD_RUN_INSTANCE=1",
        # '--vpc-connector', 
        # 'projects/<my-project>/locations/us-central1/connectors/redis', # shared VPC connector belonging to host project <my-project> 
        "--",
        "python",
        "manage.py",
        "migrate_and_purge_redis", # I made a custom django command that does a migration, then purges redis. Saves having to boot up two separate appengine instances
      ]

  # Deploy container image to Cloud Run
  - id: "deploy"
    name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args:
      - 'run'
      - 'deploy'
      - '${_SERVICE_NAME}'
      - '--image'
      - 'gcr.io/$PROJECT_ID/${_SERVICE_NAME}:$COMMIT_SHA'
      - '--platform=managed'
      - '--region=${_DEPLOY_REGION}'
      - '--vpc-connector' 
      - 'projects/<my-project>/locations/us-central1/connectors/redis' # shared VPC connector belonging to host project <my-project> 
      - '--set-env-vars' 
      - 'REDISHOST=${_REDIS_HOST},REDISPORT=${_REDIS_PORT},BUILD_ID=$BUILD_ID,CLOUD_RUN_INSTANCE=1'

images:
  - "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}:$COMMIT_SHA"

timeout: 1800s

尝试 1

我尝试为适用于云运行的 appengine 添加相同的标志和变量。因此中间步骤改为:

  - id: "apply migrations, purge redis"
    name: "gcr.io/google-appengine/exec-wrapper"
    args:
      [
        "-i",
        "gcr.io/$PROJECT_ID/${_SERVICE_NAME}:$COMMIT_SHA",
        "-s",
        "${PROJECT_ID}:${_DEPLOY_REGION}:${_DATABASE_INSTANCE}",
        "-e",
        "SETTINGS_NAME=${_SECRET_SETTINGS_NAME},REDISHOST=${_REDIS_HOST},REDISPORT=${_REDIS_PORT},BUILD_ID=$BUILD_ID,CLOUD_RUN_INSTANCE=1",
        '--vpc-connector', 
        'projects/<my-project>/locations/us-central1/connectors/redis', # shared VPC connector belonging to host project <my-project> 
        "--",
        "python",
        "manage.py",
        "migrate_and_purge_redis",
      ]

这产生了以下错误:

Step #3 - "apply migrations, purge redis": Status: Downloaded newer image for gcr.io/google-appengine/exec-wrapper:latest
Step #3 - "apply migrations, purge redis": gcr.io/google-appengine/exec-wrapper:latest
Step #3 - "apply migrations, purge redis": Invalid option: --
Finished Step #3 - "apply migrations, purge redis"

所以我不太明白 -- 的用法,但它似乎表示新行/命令?

尝试 2

遵循 https://cloud.google.com 的建议/appengine/docs/standard/python3/connecting-vpc#configuring 了解如何修改 appengine 的 app.yaml 文件,接下来我尝试了以下操作:

  - id: "apply migrations, purge redis"
    name: "gcr.io/google-appengine/exec-wrapper"
    vpc_access_connector:
      name: projects/<my-project>/locations/us-central1/connectors/redis
    args:
      [
        "-i",
        "gcr.io/$PROJECT_ID/${_SERVICE_NAME}:$COMMIT_SHA",
        "-s",
        "${PROJECT_ID}:${_DEPLOY_REGION}:${_DATABASE_INSTANCE}",
        "-e",
        "SETTINGS_NAME=${_SECRET_SETTINGS_NAME},REDISHOST=${_REDIS_HOST},REDISPORT=${_REDIS_PORT},BUILD_ID=$BUILD_ID,CLOUD_RUN_INSTANCE=1",
        "--",
        "python",
        "manage.py",
        "migrate_and_purge_redis",
      ]

这生成了以下错误

Your build failed to run: failed unmarshalling build config cloudbuild.yaml: unknown field "vpc_access_connector" in google.devtools.cloudbuild.v1.BuildStep

vpc_access_connector: 字段似乎在 app.yaml 文件中起作用,但在 cloudbuild.yml 文件中无法识别。

I have a django project that I deploy to Cloud Run. It uses two GCP resources - a Postgres database, and a Redis MemoryStore instance for caching.

Redis instances can only be connected to with serverless VPC, an extra service with extra costs. So in order to minimize costs, I've set up a shared VPC and share the Redis instance between multiple of my projects (each with their own unique key prefix to prevent key clashes).

I have been successful in getting my Cloud Run containers to connect to Redis, but I haven't yet figured out how to get my appengine runners in the Cloud Build process to connect to redis. On an update of code, you always want Django to do a migrate first to apply database schema changes. This should also be followed by a purge of redis. Hence my need to provide the appengine runner access to my vpc-connector.

My cloudbuild.yml file (before I succeed to connect redis to the migrate/purge redis step):

steps:
  - id: "build image"
    name: "gcr.io/cloud-builders/docker"
    args: ["build", "-t", "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}:$COMMIT_SHA", "."]

  - id: "push image"
    name: "gcr.io/cloud-builders/docker"
    args: ["push", "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}:$COMMIT_SHA"]

  - id: "apply migrations, purge redis"
    name: "gcr.io/google-appengine/exec-wrapper"
    vpc_access_connector:
      name: projects/<my-project>/locations/us-central1/connectors/redis
    args:
      [
        "-i",
        "gcr.io/$PROJECT_ID/${_SERVICE_NAME}:$COMMIT_SHA",
        "-s",
        "${PROJECT_ID}:${_DEPLOY_REGION}:${_DATABASE_INSTANCE}",
        "-e",
        "SETTINGS_NAME=${_SECRET_SETTINGS_NAME},REDISHOST=${_REDIS_HOST},REDISPORT=${_REDIS_PORT},BUILD_ID=$BUILD_ID,CLOUD_RUN_INSTANCE=1",
        # '--vpc-connector', 
        # 'projects/<my-project>/locations/us-central1/connectors/redis', # shared VPC connector belonging to host project <my-project> 
        "--",
        "python",
        "manage.py",
        "migrate_and_purge_redis", # I made a custom django command that does a migration, then purges redis. Saves having to boot up two separate appengine instances
      ]

  # Deploy container image to Cloud Run
  - id: "deploy"
    name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args:
      - 'run'
      - 'deploy'
      - '${_SERVICE_NAME}'
      - '--image'
      - 'gcr.io/$PROJECT_ID/${_SERVICE_NAME}:$COMMIT_SHA'
      - '--platform=managed'
      - '--region=${_DEPLOY_REGION}'
      - '--vpc-connector' 
      - 'projects/<my-project>/locations/us-central1/connectors/redis' # shared VPC connector belonging to host project <my-project> 
      - '--set-env-vars' 
      - 'REDISHOST=${_REDIS_HOST},REDISPORT=${_REDIS_PORT},BUILD_ID=$BUILD_ID,CLOUD_RUN_INSTANCE=1'

images:
  - "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}:$COMMIT_SHA"

timeout: 1800s

Attempt 1

I tried adding in the same flag and variable for appengine that works for cloud run. Hence the middle step changed to this:

  - id: "apply migrations, purge redis"
    name: "gcr.io/google-appengine/exec-wrapper"
    args:
      [
        "-i",
        "gcr.io/$PROJECT_ID/${_SERVICE_NAME}:$COMMIT_SHA",
        "-s",
        "${PROJECT_ID}:${_DEPLOY_REGION}:${_DATABASE_INSTANCE}",
        "-e",
        "SETTINGS_NAME=${_SECRET_SETTINGS_NAME},REDISHOST=${_REDIS_HOST},REDISPORT=${_REDIS_PORT},BUILD_ID=$BUILD_ID,CLOUD_RUN_INSTANCE=1",
        '--vpc-connector', 
        'projects/<my-project>/locations/us-central1/connectors/redis', # shared VPC connector belonging to host project <my-project> 
        "--",
        "python",
        "manage.py",
        "migrate_and_purge_redis",
      ]

This produced the following error:

Step #3 - "apply migrations, purge redis": Status: Downloaded newer image for gcr.io/google-appengine/exec-wrapper:latest
Step #3 - "apply migrations, purge redis": gcr.io/google-appengine/exec-wrapper:latest
Step #3 - "apply migrations, purge redis": Invalid option: --
Finished Step #3 - "apply migrations, purge redis"

So I don't quite understand the use of --, but it appears to signify a new line/command?

Attempt 2

Following advice from https://cloud.google.com/appengine/docs/standard/python3/connecting-vpc#configuring of how to modify an appengine's app.yaml file, I tried this next:

  - id: "apply migrations, purge redis"
    name: "gcr.io/google-appengine/exec-wrapper"
    vpc_access_connector:
      name: projects/<my-project>/locations/us-central1/connectors/redis
    args:
      [
        "-i",
        "gcr.io/$PROJECT_ID/${_SERVICE_NAME}:$COMMIT_SHA",
        "-s",
        "${PROJECT_ID}:${_DEPLOY_REGION}:${_DATABASE_INSTANCE}",
        "-e",
        "SETTINGS_NAME=${_SECRET_SETTINGS_NAME},REDISHOST=${_REDIS_HOST},REDISPORT=${_REDIS_PORT},BUILD_ID=$BUILD_ID,CLOUD_RUN_INSTANCE=1",
        "--",
        "python",
        "manage.py",
        "migrate_and_purge_redis",
      ]

This generated the following error:

Your build failed to run: failed unmarshalling build config cloudbuild.yaml: unknown field "vpc_access_connector" in google.devtools.cloudbuild.v1.BuildStep

So while the vpc_access_connector: field appears to work in app.yaml files, it is not recognized in cloudbuild.yml files.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧夏天 2025-01-22 05:44:34

Cloud Build 不存在 VPC 连接器。还有另一种解决方案:私人池。专用池是根据需要在专用于该 VM 的网络上为您创建的 VM。当然,所有这些事情都由 Google 管理,您在项目中看不到任何内容,但是,因为网络和虚拟机专用于您的项目,Google Cloud 可以将此网络与您的 VPC 对等,并使那些起作用的东西。

不好的一面是,因为 VM 是根据您的构建需求创建的,所以在执行管道之前需要 30 到 60 秒的预热(启动 VM)。因此,测试过程比托管池慢

VPC connectors doesn't exist for Cloud Build. There is another solution: private pool. The private pools are VM created for you on demand and on a network dedicated to this VMs. Of course, all of those things are managed by Google and you see nothing in your project, BUT, because the network and the VM are dedicated your project, Google Cloud can peer this network with your VPC and make the things working.

The bad side is, because the VM are created on demand for your build, it takes 30s to 60s of warmup (starting the VM) before executing your pipeline. Therefore, the test process is slower that the managed pools

尐偏执 2025-01-22 05:44:34

我知道已经晚了,但希望这能节省某人的时间。这就是我按照建议所做的 在这里

  - id: "make migrations"
    name: "gcr.io/google-appengine/exec-wrapper"
    args:
      [
        "-i",
        "gcr.io/$PROJECT_ID/${_SERVICE_NAME}",
        "-s",
        "${PROJECT_ID}:${_REGION}:${_INSTANCE_NAME}",
        "-e",
        "SETTINGS_NAME=${_SECRET_SETTINGS_NAME}",
        "-e",
        "DJANGO_SETTINGS=dev",
        "-e",
        "INSTANCE_UNIX_SOCKET=/cloudsql/${PROJECT_ID}:${_REGION}:${_INSTANCE_NAME}",
        "--",
        "python",
        "manage.py",
        "makemigrations",
      ] 


substitutions:
  _INSTANCE_NAME: postgresql-server # The Cloud SQL instance name.

然后在我的 settings.py 文件中

DB_STRING = f"postgres://{os.environ.get('POSTGRES_USER')}:{os.environ.get('POSTGRES_PASSWORD')}@/{os.environ.get('POSTGRES_DATABASE')}?host={os.environ['INSTANCE_UNIX_SOCKET']}"

DATABASES = {'default': dj_database_url.parse(DB_STRING)}

I know its late but hoping this would save somebody's time. This is what I have done as suggested here.

  - id: "make migrations"
    name: "gcr.io/google-appengine/exec-wrapper"
    args:
      [
        "-i",
        "gcr.io/$PROJECT_ID/${_SERVICE_NAME}",
        "-s",
        "${PROJECT_ID}:${_REGION}:${_INSTANCE_NAME}",
        "-e",
        "SETTINGS_NAME=${_SECRET_SETTINGS_NAME}",
        "-e",
        "DJANGO_SETTINGS=dev",
        "-e",
        "INSTANCE_UNIX_SOCKET=/cloudsql/${PROJECT_ID}:${_REGION}:${_INSTANCE_NAME}",
        "--",
        "python",
        "manage.py",
        "makemigrations",
      ] 


substitutions:
  _INSTANCE_NAME: postgresql-server # The Cloud SQL instance name.

and then in my settings.py file

DB_STRING = f"postgres://{os.environ.get('POSTGRES_USER')}:{os.environ.get('POSTGRES_PASSWORD')}@/{os.environ.get('POSTGRES_DATABASE')}?host={os.environ['INSTANCE_UNIX_SOCKET']}"

DATABASES = {'default': dj_database_url.parse(DB_STRING)}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文