如何在 Google App Engine 标准环境中使用 Google Cloud Build 或其他方法设置环境变量?
Posted
技术标签:
【中文标题】如何在 Google App Engine 标准环境中使用 Google Cloud Build 或其他方法设置环境变量?【英文标题】:How to set environment variables using Google Cloud Build or other method in Google App Engine Standard Environment? 【发布时间】:2019-03-21 06:22:42 【问题描述】:是否可以将 Cloud Build 中的环境变量注入 App Engine 标准环境?
我不想将我的环境变量推送到app.yaml
或.env
内的GitHub。因此,当 Cloud Build 拉取和部署时,它会丢失 .env
文件,并且服务器无法完成某些请求。
我试图避免使用 Datastore,因为 Datastore 的异步特性会使代码更加混乱。我尝试使用找到 here 的加密机密,但这似乎不起作用,因为我将机密添加到应用程序部署并且它们没有进入部署,所以我认为这不是 Cloud Build 的用例.
我还尝试了教程here,将.env
文件从存储导入App Engine Standard,但由于Standard 没有本地存储,我认为它会失效。
那么有没有办法在不使用 Datastore 或提交 app.yaml
或 .env
来更改控制的情况下将 .env
注入 App Engine 标准环境?可能使用 Cloud Build、KMS 或某种类型的存储?
这是我为cloudbuild.yaml
尝试的:
steps:
- name: "gcr.io/cloud-builders/gcloud"
args: ["app", "deploy"]
secretEnv: ['SECRET1', 'SECRET2', 'SECRET3', 'SECRET4', 'SECRET5']
timeout: "1600s"
secrets:
- kmsKeyName: projects/<Project-Name>/locations/global/keyRings/<Key-Ring-Name>/cryptoKeys/<Key-Name>
secretEnv:
SECRET1: <encrypted-key-base64 here>
SECRET2: <encrypted-key-base64 here>
SECRET3: <encrypted-key-base64 here>
SECRET4: <encrypted-key-base64 here>
SECRET5: <encrypted-key-base64 here>
【问题讨论】:
【参考方案1】:这里有一个tutorial,介绍如何在您的云构建(触发器)设置中安全地存储环境变量并将它们导入到您的应用中。
基本上分为三个步骤:
将您的环境变量添加到您的构建触发器设置之一中的“变量”部分
Screenshot of where to add variables in build triggers
按照惯例,在构建触发器中设置的变量必须以下划线 (_) 开头
配置cloudbuild.yaml
(在代码示例的第二步中)从构建触发器中读取变量,将它们设置为环境变量,并将所有环境变量写入本地 .env 文件中
将couldbuild.yaml
(下)添加到您的项目根目录
steps:
- name: node:10.15.1
entrypoint: npm
args: ["install"]
- name: node:10.15.1
entrypoint: npm
args: ["run", "create-env"]
env:
- 'MY_SECRET_KEY=$_MY_SECRET_KEY'
- name: "gcr.io/cloud-builders/gcloud"
args: ["app", "deploy"]
timeout: "1600s"
将create-env
脚本添加到package.json
"scripts":
"create-env": "printenv > .env"
,
将环境变量从 .env 读取到您的应用 (config.js)
安装 dotenv 包
npm i dotenv -S
在您的应用中添加config.js
// Import all env vars from .env file
require('dotenv').config()
export const MY_SECRET_KEY = process.env.MY_SECRET_KEY
console.log(MY_SECRET_KEY) // => Hello
完成!现在您可以通过触发云构建来部署您的应用,您的应用将可以访问环境变量。
【讨论】:
工作太棒了!谢谢!你的文章也很适合跟随。你是一个真正的英雄。 @AlexSupkay 很高兴您喜欢这个解决方案。非常感谢!! 我正在尝试此解决方案,但 gcloud 中 .env 文件中的替代 var 为空。有什么想法吗? 这个解决方案我遇到了问题,但那是因为我没有很好地理解步骤,在第2步我不明白我必须手动编辑package.json文件并添加句子“”正确执行此操作后,create-env ":" printenv> .env "" 完美运行。 看起来这个解决方案不再起作用了。与 Medium 上的其他评论者一样有问题。最终使用 CloudBuild 触发器变量和单独的 app.yaml 文件【参考方案2】:如果有人仍然对此感兴趣,我还有另一个解决方案。这应该适用于所有语言,因为环境变量直接添加到 app.yaml
文件中
在构建触发器中添加替换变量(如answer 中所述)。
将环境变量添加到app.yaml
,以便它们可以轻松地替换为构建触发器变量。像这样:
env_variables:
SECRET_KEY: %SECRET_KEY%
-
在
cloudbuild.yaml
中添加一个步骤,将app.yaml
中的所有%XXX%
变量替换为其来自构建触发器的值。
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: bash
args:
- '-c'
- |
sed -i 's/%SECRET_KEY%/'$_SECRET_KEY'/g' app.yaml
gcloud app deploy app.yaml
【讨论】:
奇怪,我在运行这个 sed -i 's/%SECRET_KEY%/'$_SECRET_KEY'/g' app.yaml 时没有得到这样的文件【参考方案3】:highfivebrian answer 很棒,但我添加的解决方案略有不同。
1). 在根项目文件夹中,我们需要 cloudbuild.yaml 文件,但我将其命名为 buildsetttings.yaml
,因为
第一个名字有一个problem
在 buildsetttings.yaml 我添加了这段代码:
steps:
- name: node
entrypoint: npm
args: ['install']
- name: node
entrypoint: npm
env:
- 'DB_URL=$_DB_URL'
- 'SENDGRID_API_KEY=$_SENDGRID_API_KEY'
- 'CLIENT_ID=$_CLIENT_ID'
args: ['run', 'create-app-yaml']
- name: 'gcr.io/cloud-builders/gcloud'
args: ['app', 'deploy']
buildsetttings.yaml 将使用 npm create-app-yaml
命令在 Cloud Build 中创建 app.yaml 文件。
提示: app.yaml 文件,然后我们将使用该文件将我们的应用部署到 GCP App Engine。
2). 在根文件夹(靠近 buildsetttings.yaml)中,我们需要创建 create-app-yaml.js
,它会在从 buildsetttings.yaml 调用后在 Cloud Build 中运行。
在 buildsetttings.yaml 我添加了这段代码:
require('dotenv').config();
const fs = require('fs');
const appYamlContent = `runtime: nodejs14
env_variables:
DB_URL: $process.env.DB_URL
SENDGRID_API_KEY: $process.env.SENDGRID_API_KEY
CLIENT_ID: $process.env.CLIENT_ID`;
fs.writeFileSync('./app.yaml', appYamlContent);
此代码使用 npm 包 dotenv
(将其添加到 package.json)并从 Cloud Build 触发器变量中获取变量并使用它们创建 app.yaml 文件。
3). app.yaml 文件是在 Cloud 构建中创建的,我们的最后一步(名称:'gcr.io/cloud-builders/gcloud')在 buildsetttings.yaml 中使用 app .yaml 文件,将项目部署到 Google Cloud App Engine。
成功了!
简而言之,它的工作原理是这样的:buildsetttings.yaml 在 Cloud Build 中运行“create-app-yaml.js”,然后通过从 Cloud 添加变量来动态创建 app.yaml 文件构建触发器变量,然后在 App Engine 中进行部署。
注意事项:
从您的项目中删除文件 app.yamlin,因为它将在 Cloud Build 中动态创建。同时删除 cloudbuild.yaml 文件,因为我们使用的是 buildsetttings.yaml。
package.json:
Cloud Build 触发变量:【讨论】:
【参考方案4】:根据您突出显示的偏好(Cloud Build、KMS)。您提到的 Google Secrets 链接涉及使用Cloud KMS:KeyRing 和 CryptoKey 在构建或运行时存储敏感数据。不过,Google 也提供其他使用 Cloud KMS 的秘密管理解决方案。
您可以在storing Secrets 时使用以下几个其他选项:
选项 1:您可以将 Secrets 存储在代码中,并使用来自 Cloud KMS 的密钥加密。 (这通常用于在应用层加密您的秘密。)
好处:提供了一层安全以防止内部威胁,因为它限制访问代码具有相应的密钥强>。
[您可以在 Google 文档here 上找到有关这些选项的更多信息。]
选项 2:您可以在 Google 存储 Bucket 中存储机密,您的数据位于 rest encryption.(与选项 1 类似,它可以将机密访问权限限制为一小部分开发人员。)
好处:将您的机密存储在单独的位置可确保如果您的代码存储库发生泄露发生,您的秘密可能仍然受到保护。)
[注意:Google 建议您将两个项目用于正确的separation of duties。一个项目将使用 Cloud KMS 管理密钥,另一个项目将使用 Cloud Storage 存储机密。]
如果上面列出的选项仍然不能满足您的需求,我找到了一个与您的项目具有相似目标的*** question。 (即:在 GAE 中存储环境变量没有数据存储)
link 上提供的解决方案说明了将密钥存储在 client_secrets.json 文件中的使用,该文件在上传到 git 时被排除在 .gitignore 中。您可以找到usage here 的一些 Google 示例 (Python)。
【讨论】:
我觉得这是一个通用的复制意大利面类型的答案,它没有解决特定问题,因为它适用于使用 Node 的多环境设置以上是关于如何在 Google App Engine 标准环境中使用 Google Cloud Build 或其他方法设置环境变量?的主要内容,如果未能解决你的问题,请参考以下文章
Google App Engine 标准 Python 云构建
我如何从Google App Engine中触发一个HTTP云函数?
使用 Google APP Engine 的 Cloud SQL 连接限制
将 Nuxt JS s-s-r 应用程序部署到 Google Cloud App Engine 标准