将 env 变量从 Google 的 Secret Manager 加载到在 Google Cloud Run 上运行但未通过 Cloud Build 部署的 Docker 容器中?
Posted
技术标签:
【中文标题】将 env 变量从 Google 的 Secret Manager 加载到在 Google Cloud Run 上运行但未通过 Cloud Build 部署的 Docker 容器中?【英文标题】:Load env variables from Google's Secret Manager into Docker container that runs on Google Cloud Run, but not deployed via Cloud Build? 【发布时间】:2021-06-07 05:05:01 【问题描述】:我目前正在使用 Google 的 Cloud Run 作为 docker 容器交付 node + nestjs 应用程序。
我正在使用机密管理器来管理机密,并将项目用于开发/登台/生产,并且我正在尝试使机密可用于我在云中的容器。
当前进程由触发一系列 bash 脚本的“yarn docker:auth”触发:
docker build -t gcr.io/my_project_id_dev/auth-service -f .docker/auth.DockerFile . &&
gcloud auth activate-service-account abc@my_project_id_dev.iam.gserviceaccount.com --key-file=gcloud-sa.json &&
gcloud auth configure-docker &&
docker push gcr.io/my_project_id_dev/auth-service &&
gcloud beta run services replace .gcp/cloud_run/auth.yaml &&
gcloud run deploy auth ... --allow-unauthenticated --platform managed --region europe-west2
最后一个命令的参数/标志也不起作用,每次运行时都会提示我选择平台和区域。
我已尝试将标志添加到我的 auth.yaml 文件以及 Google Cloud Build 文档中举例说明的秘密,但由于语法错误,每次都失败。
在yaml文件中,我在yaml文件的底部添加了以下内容,嵌套在no属性下:
availableSecrets:
secretManager:
- versionName: projects/my_project_id/secrets/mongo_uri/versions/latest
env: 'mongo_uri'
我的问题是:
是否有可能通过 YAML 做到这一点?我还在我的 nodejs 应用程序中添加了一个启动功能,它尝试使用来自 npmjs 的@google-cloud/secret-manager
将机密加载到环境中。使用默认凭据在本地执行此操作没有问题,但是:
我试图解决的基本问题是将这些秘密放入容器环境中。
谢谢。
编辑:
想要添加我将服务帐户分配给云运行容器的 YAML 部分:
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/maxScale: '2'
run.googleapis.com/client-name: cloud-console
run.googleapis.com/sandbox: gvisor
spec:
containerConcurrency: 2
containers:
- image: gcr.io/my_project_id/auth-service
ports:
- containerPort: 3000
resources:
limits:
cpu: 1000m
memory: 512Mi
serviceAccountName: abc@my_project_id.iam.gserviceaccount.com
timeoutSeconds: 300
但遗憾的是,这仍然会导致这个一般错误:
(gcloud.beta.run.services.replace) Cloud Run error: Container failed to start. Failed to start and then listen on the port defined by the PORT environment variable.
日志本身绝对没有更多细节,空白!由于没有注入服务帐户,容器不会在本地启动,但是如果没有处理秘密加载的那段代码,容器在本地启动就好了。
【问题讨论】:
我不确定这是否有用。您的 YAML 看起来与 these cloud run docs 中的 YAML 略有不同。文档还讨论了一些权限问题。 您可以运行命令gcloud run deploy --service-account=SERVICE_ACCOUNT
,其中服务帐户代表正在运行的修订版的身份,并确定该修订版具有哪些权限gcloud command
不确定您想要实现什么。您想使用服务的 YAML 定义将密钥从 Secret Manager 直接加载到您的容器中,对吗?我不明白 Cloud Build 和服务帐号的关系!!
@Paul 将 YAML 修复为仅具有有限的设置集,因为托管云运行不支持它我正在尝试根据默认凭据在启动时将机密加载到节点环境中,这似乎如果我通过 YAML 手动部署容器映像,则此时可以工作。
@marian.vladoi 很奇怪,这不起作用,我仍然会收到平台和区域提示,但是使用 gcloud config set run/platform managed 可以工作。
【参考方案1】:
这里有一点需要解压。简而言之,我认为您可能会将 构建时间 与 运行时 机密以及它们的访问方式混淆。
如果您在编译或测试阶段不需要访问机密,则可以从 cloudbuild.yaml
中省略 availableSecrets
节。这会在构建时引入秘密。例如,假设您想在 Cloud Build 中运行测试,并且需要 API 密钥或数据库密码来执行测试。那时你会使用Cloud Build + Secret Manager integration。
gcloud auth activate-service-account abc@my_project_id_dev.iam.gserviceaccount.com --key-file=gcloud-sa.json
如果您在本地使用 gcloud,则不需要服务帐号。您可以通过以下方式对 gcloud 进行身份验证:
gcloud auth login && gcloud auth application-default login
作为安装 gcloud 的一部分,您通常会执行一次这些步骤。 configure-docker
也是如此。您通常只运行一次此命令
Cloud Run + Secret Manager 集成目前处于预览阶段。你可以request access using this Google Form。 (对于未来的读者,如果该表单不再存在,则意味着集成是公开的,无需注册。)
Cloud run 中的 docker 容器是否有任何类型的“默认”凭据?如果没有,注入它的最佳方法是什么?使用服务帐户密钥文件构建或发布容器似乎是一种不好的做法。
是的,默认情况下,Cloud Run 容器将作为默认的 Compute Engine 服务帐号执行。此服务帐户具有广泛的权限,但它没有有权访问机密。
我们建议您为此工作负载和grant access to only the specific secrets it needs 创建一个新的服务帐户。然后,您可以使用带有 --service-account
标志的自定义服务帐户运行 Cloud Run 容器:
gcloud run deploy auth --service-account "...@...iam.gserviceaccount.com"
最后一个命令的参数/标志也不起作用,每次运行时都会提示我选择平台和区域。
我们需要查看完整的命令以了解失败的原因,特别是 ...
是什么。
日志本身绝对没有更多细节,空白!由于没有注入服务帐户,容器不会在本地启动,但是如果没有处理秘密加载的那段代码,容器在本地启动就好了。
您可以从侧边栏中查看 Cloud Logging 中容器的日志。
【讨论】:
感谢@sethvargo 的详细回复,它确实涵盖了我所有的问题,并且通过手动流程进行的进一步测试表明,围绕秘密检索的所有逻辑和权限流程确实按照记录的方式工作,我做了错误地假设容器部署失败是由于这个原因。我在这个单独的线程中详细阐述了我的次要问题:***.com/questions/66552705/…以上是关于将 env 变量从 Google 的 Secret Manager 加载到在 Google Cloud Run 上运行但未通过 Cloud Build 部署的 Docker 容器中?的主要内容,如果未能解决你的问题,请参考以下文章
从 Google Cloud Build 访问存储在 Google Secret Manager 中的环境变量
找不到满足 env:PRISMA_SECRET 的有效环境变量
带有 laravel 的 Paypal sdk - 从 env 文件中获取 Client_id/secret
如何使用 Spring Boot 将来自 Google Secret Manager 的秘密作为环境变量注入 Kubernetes Pod?