【问题标题】:GAE : How to deploy various environments with secrets?GAE:如何部署各种带秘密的环境?
【发布时间】:2018-10-05 04:52:23
【问题描述】:

我在 App Engine 上有一个暂存项目和一个生产项目,每个项目都有 6 个服务。

目前,我们从开发人员计算机部署,使用 gcloud app deploy app.staging.yaml --project staging-project

gcloud app deploy app.production.yaml --project production-project

它可以工作,但会导致环境变量出现问题,尤其是机密问题。

我们的应用程序从环境变量中获取其 Api 密钥、数据库凭据和其他内容 - 这使我们能够在本地、Docker 容器或 App Engine 中运行完全相同的应用程序,而无需知道它的部署位置。

如果我按照文档的方式进行部署,我们的 app.yaml 文件将如下所示:

app.production.yaml

runtime: nodejs
env: flex

manual_scaling:
  instances: 1
env_variables:
  DATABASE_PASSWORD: "topsecret"
  MY_API_KEY: "ultrasecret"

我想每个人都很容易理解为什么将它存储在 Git 存储库中是个坏主意。

目前,我们有这个影子文件,每个开发人员都必须在部署前填写

app.production.yaml.shadow

runtime: nodejs
env: flex

manual_scaling:
  instances: 1
env_variables:
  DATABASE_PASSWORD: "set me"
  MY_API_KEY: "set me"

但是随着团队的发展,我们希望每个人都能够在 staging 上进行部署,为每个开发人员和每个服务设置正确的设置变得越来越困难。

我发现了 3 个解决方法,以及不使用它们的原因:

  • 使用Google KMS - 允许我们将加密的秘密直接放入项目中,但它需要我们将自定义代码放入我们的应用程序中以对其进行解密。它在本地、暂存和生产之间创建了不同的环境管理。由于复杂性,它增加了出现错误的风险。
  • Store secrets in Google Datastore - 我试过了,我创建了一个帮助程序,它在 proccess.ENV 中搜索环境变量,然后在缓存中,最终在 Datastore 中。但与 KMS 一样,它大大增加了复杂性。
  • 将机密存储在 JSON file and put in on Google Cloud Storage 中:再次,它需要通过检查环境变量的助手加载环境变量,然后加载文件等...

最终,我们正在探索使用部署服务器的可行性,该服务器将由开发人员或持续集成触发并在部署到 App Engine 时处理所有秘密注入。但是像 Ansible、Salt、P​​uppet、Chef 这样的工具只有 Compute Engine 的插件,不支持 App Engine。

+-------------------------+    +-------------------+   +---------------------+
|                         |    |                   +--->                     |
| Developer workspace     |    |    Ansible        |   | App Engine STAGING  |
|                         +---->   (or other)      |   |                     |
+-------------------------+    |                   |   +---------------------+
                               |                   |
+-------------------------+    |                   |   +---------------------+
|                         +---->   Injects secrets |   |                     |
| Continous Integration        |                   |   | App Engine PROD.    |
|                         |    |                   +--->                     |
+-------------------------+    +-------------------+   +---------------------+

这引出了 3 个问题:

  • 您认为将部署服务器与 App Engine 结合使用是个好主意吗?
  • 如何确保生产和暂存机密保持同步,以便开发人员的部署始终正确?
  • 有没有办法在 App Engine 上将经典环境变量用于机密?

【问题讨论】:

  • 您的秘密在暂存和生产项目中是否稳定,还是经常更改?
  • 我们可以每两周在每个版本中添加一些秘密。所以很稳定

标签: google-app-engine ansible


【解决方案1】:

我强烈建议您考虑结合使用 KMS 和云存储,正如 Google 概述的 here

您说得对,设置起来可能有点让人头疼,但是一旦安装到位,就很容易使用。我们为每个环境设置了单独的密钥环(devteststagingprod),然后为每个应用程序单独的密钥,并编写了一个命令行实用程序,使我们团队中的任何开发人员都可以轻松编写秘密存储到秘密存储中(同时防止他们读回生产秘密)。

归根结底,机密的管理仍然是一个难题。随着团队的壮大,管理多个应用程序/环境的机密非常困难。但我真的鼓励你预先支付投资于 KMS 之类的东西的成本,因为它会让你的生活从本质上永远变得更轻松,并真正降低你不小心撞到自己脚的风险。

【讨论】:

    【解决方案2】:

    正如您所说,这些解决方案(Ansible、Salt 等)中的任何一个都不能与 App Engine 一起使用。如果你要使用它们,你将不得不搬到 GCE。 Google 有一些 official tutorials 介绍如何开始使用这些技术。

    如果您继续使用 App Engine,则可以使用上述解决方案之一,KMS 更适合此目的。

    另一个可能的解决方案是迁移到自定义运行时。根据您的应用程序,您可以生成一个 Dockerfile:

    $ gcloud beta app gen-config --custom

    您的 Dockerfile 将如下所示:

    FROM gcr.io/google_appengine/nodejs
    RUN /usr/local/bin/install_node '>=4.3.2'
    COPY . /app/
    RUN npm install --unsafe-perm || \
      ((if [ -f npm-debug.log ]; then \
          cat npm-debug.log; \
        fi) && false)
    CMD npm start
    

    然后您可以修改它以包含存储在环境变量中的密钥,例如如何在文件中输入密钥的示例:

    sed 's/topsecret/'"$KEY_1"'/g;s/ultrasecret/'"$KEY_2"'/g' app.production.yaml.shadow > app.production.yaml

    注意在 KEY_1 和 KEY_2 之前和之后使用单引号和双引号,因为您需要它们 to enter environment variables using sed

    【讨论】:

      【解决方案3】:

      几次之后,关于这个问题我可以说一下:

      • 为每个环境创建一个 app.yaml。您可以根据自己的环境指定在部署时使用的 app.yaml 文件。
      • 将您的非机密环境参数(如端点 url)放入 env_variables 部分。
      • 对于您的秘密(API 密钥、秘密令牌...),请使用Hashicorp VaultAWS Secrets Manager 等专用工具。这将允许您在您的项目之间共享它们,并在您的团队中处理可以访问它们的人。

      【讨论】:

      • 如果您使用一些 API,例如 Vault 或新的 Google Secret Manager,您什么时候提出这些秘密请求?你在实例启动时这样做吗?我担心的是:1,它增加了启动时间,但更重要的是 2,如果 API 失败会发生什么?另一种方法是执行一个自定义的预部署脚本,该脚本获取秘密,并可能在调用gcloud app deploy 之前将它们放入.env 文件中。如果在获取秘密时出现任何问题,它可以中止。然后你可以.gitignore .env 文件,所以它永远不会被提交。或者,也许我想多了,在启动时做就可以了。
      • 嗯,我所做的是使用 CI 将 AWS Secrets Manager 中的密钥写入部署中包含的文件。这让我不必处理我的实例上的 AWS 账户。但是秘密文件在 App Engine 调试器上是可读的......
      • 啊,很好。所以基本上它是作为部署的一部分完成的——而不是在实例启动中(比如在gcp-build 脚​​本中)。谢谢。
      • @maxime 使用 .gcloudignore 不将您的机密文件上传到 AppEngine。
      猜你喜欢
      • 2021-10-04
      • 2012-06-12
      • 2022-10-04
      • 1970-01-01
      • 1970-01-01
      • 2019-03-09
      • 2020-06-28
      • 2023-03-08
      • 2017-04-25
      相关资源
      最近更新 更多