当我将新的应用程序版本部署到云时,注入的数据库凭据发生变化
injected db credentials change when I deploy new app version to cloud
我将 Web 应用程序部署到本地 cloudfoundry 环境。作为我的 DEV 环境的数据库服务,我选择了 Marketplace 服务 google-cloudsql-postgres
和计划 postgres-db-f1-micro
。使用 Web UI 我创建了一个名为 myapp-test-database
的实例,并在 CF 清单中提到了它:
applications:
- name: myapp-test
services:
- myapp-test-database
起初,一切都很好。我什至可以重新部署现有的工件。但是,当我构建我的应用程序的新版本并将其推送到 CF 时,注入的凭据已更新并且该应用程序无法再访问表:
PSQLException: ERROR: permission denied for table
这些表仍然存在,但它们归之前的用户所有。它们是由 ORM 在 public
架构中自动创建的。
虽然 -OLD
应用程序仍然存在,但我可以从 CF Web UI 或 $VCAP_SERVICES
检索旧的 username/password 并删除表格。
这都是因为滚动应用部署吗?不过接下来应该会有很多抱怨吧。
如果您严格执行 cf push
(或 restart
/restage
),则不涉及代理(Cloud Controller 不与其对话),并且服务凭据不会更改。
通过 cf
命令可以修改您的凭据的唯一操作是执行 unbind
,然后执行 bind
。许多(但不是全部)服务代理将丢弃 unbind
上的凭据并为 bind
提供新的唯一凭据。这通常是可取的,以便您可以在凭据泄露时轮换凭据。
如果您有自定义脚本或 cf cli 插件来实施滚动部署,这可能会成为问题。像这样的大多数工具将使用两个单独的应用程序实例,这意味着您将拥有两个单独的绑定和两组单独的凭据。
如果您必须拥有一组凭据,您可以使用服务密钥来解决此问题。服务密钥类似于绑定,但不与 CloudFoundry 中的应用程序相关联。
服务密钥的缺点是它不会像绑定一样通过 $VCAP_SERVICES
自动暴露给您的应用程序。要解决此问题,您可以将服务密钥凭据传递到用户提供的服务中,然后将其绑定到您的应用程序,或者您可以通过其他环境变量将它们传递到您的应用程序中,例如 DB_URL
.
另一种选择是不再使用脚本和 cf cli 插件进行 blue/green 部署,而是使用现在内置到 Cloud Foundry 中的支持。使用 cf
cli 版本 7+,cf push
有一个 --strategy
选项,可以将其设置为 rolling
以执行滚动部署。这不会创建多个应用程序实例,因此只会存在一个服务绑定和一组凭据。
使用额外的bind parameter“用户名”请求静态用户名:
cf bind-service my-app-test-CANDIDATE myapp-test-database -c "{\"username\":\"myuser\"}"
使用 cf7+ 可以将参数添加到清单中:
applications:
- name: myapp-test
services:
- name: myapp-test-database
parameters: { "username": "myuser" }
https://docs.cloudfoundry.org/devguide/services/application-binding.html#arbitrary-params-binding
Note: Arbitrary parameters are not supported in app manifests in cf CLI v6.x. Arbitrary parameters are supported in app manifests in cf CLI v7.0 and later.
但是,我在这里找不到新语法:https://docs.cloudfoundry.org/devguide/deploy-apps/manifest-attributes.html#services-block。我使用的语法来自其他一些 SO 问题。
我将 Web 应用程序部署到本地 cloudfoundry 环境。作为我的 DEV 环境的数据库服务,我选择了 Marketplace 服务 google-cloudsql-postgres
和计划 postgres-db-f1-micro
。使用 Web UI 我创建了一个名为 myapp-test-database
的实例,并在 CF 清单中提到了它:
applications:
- name: myapp-test
services:
- myapp-test-database
起初,一切都很好。我什至可以重新部署现有的工件。但是,当我构建我的应用程序的新版本并将其推送到 CF 时,注入的凭据已更新并且该应用程序无法再访问表:
PSQLException: ERROR: permission denied for table
这些表仍然存在,但它们归之前的用户所有。它们是由 ORM 在 public
架构中自动创建的。
虽然 -OLD
应用程序仍然存在,但我可以从 CF Web UI 或 $VCAP_SERVICES
检索旧的 username/password 并删除表格。
这都是因为滚动应用部署吗?不过接下来应该会有很多抱怨吧。
如果您严格执行 cf push
(或 restart
/restage
),则不涉及代理(Cloud Controller 不与其对话),并且服务凭据不会更改。
通过 cf
命令可以修改您的凭据的唯一操作是执行 unbind
,然后执行 bind
。许多(但不是全部)服务代理将丢弃 unbind
上的凭据并为 bind
提供新的唯一凭据。这通常是可取的,以便您可以在凭据泄露时轮换凭据。
如果您有自定义脚本或 cf cli 插件来实施滚动部署,这可能会成为问题。像这样的大多数工具将使用两个单独的应用程序实例,这意味着您将拥有两个单独的绑定和两组单独的凭据。
如果您必须拥有一组凭据,您可以使用服务密钥来解决此问题。服务密钥类似于绑定,但不与 CloudFoundry 中的应用程序相关联。
服务密钥的缺点是它不会像绑定一样通过 $VCAP_SERVICES
自动暴露给您的应用程序。要解决此问题,您可以将服务密钥凭据传递到用户提供的服务中,然后将其绑定到您的应用程序,或者您可以通过其他环境变量将它们传递到您的应用程序中,例如 DB_URL
.
另一种选择是不再使用脚本和 cf cli 插件进行 blue/green 部署,而是使用现在内置到 Cloud Foundry 中的支持。使用 cf
cli 版本 7+,cf push
有一个 --strategy
选项,可以将其设置为 rolling
以执行滚动部署。这不会创建多个应用程序实例,因此只会存在一个服务绑定和一组凭据。
使用额外的bind parameter“用户名”请求静态用户名:
cf bind-service my-app-test-CANDIDATE myapp-test-database -c "{\"username\":\"myuser\"}"
使用 cf7+ 可以将参数添加到清单中:
applications:
- name: myapp-test
services:
- name: myapp-test-database
parameters: { "username": "myuser" }
https://docs.cloudfoundry.org/devguide/services/application-binding.html#arbitrary-params-binding
Note: Arbitrary parameters are not supported in app manifests in cf CLI v6.x. Arbitrary parameters are supported in app manifests in cf CLI v7.0 and later.
但是,我在这里找不到新语法:https://docs.cloudfoundry.org/devguide/deploy-apps/manifest-attributes.html#services-block。我使用的语法来自其他一些 SO 问题。