我之前使用过 Heroku 和 AWS,现在正在使用 App Engine 和 Cloud SQL(Postgres)在 Google Cloud 平台上建立服务。
我们尝试使用 12 因素原则来构建该应用程序。
事实证明这个设置非常繁琐,我开始怀疑我是否从根本上错过了什么。
以下是一些让我感到困惑的事情:
- 被鼓励写密码进入最终进入源代码控制的文件中 (app.yaml)。
- 需要破解加载环境变量的解决方法(如果我不想将它们提交给源代码控制)。
- 发现要连接到云 SQL 实例,我需要一行引用 app.yaml 中的特定实例 - 所以现在我需要 app.staging.yaml 和 app.production.yaml?
- 发现该行似乎仅支持 1 个 DB 实例,并且不清楚如果我们希望应用程序连接到 2 个 DB,是否支持。
我是否错过了服务器管理中的一些重大发展,而这些已成为最佳实践?刚刚发现第 3 点和第 4 点后,我真的开始认为我的设置中一定出现了根本性错误。是吗?
答案1
我还没有专门尝试按照您描述的方式配置应用程序,但我知道这些不是 Google 想要的结果。为了解决一些具体问题:
连接到 Cloud SQL具体说以下内容表明存储密码不是他们的本意,并为秘密提供单独的解决方案。
# Remember - storing secrets in plaintext is potentially unsafe. Consider using # something like https://cloud.google.com/secret-manager/docs/overview to help keep # secrets secret.
根据本文,Google App engine 不支持 app.yaml 中的环境变量(有关 Google App Engine 类似问题的评论)。我针对类似问题的解决方案是以下代码:
#!/bin/bash # deploy-helper.sh prepare_yaml() { [ -z "$1" ] && echo "ERROR: template.yaml filename must be provided." && exit 1 template="${1}" # ARG #1 : filename of template yaml finalYAML=$(mktemp) # make temporary file generated_stdin_cmds="$(echo "cat <<EOF >\"$finalYAML\""; cat $template; echo EOF;)" source /dev/stdin <<< "$generated_stdin_cmds" echo "$finalYAML"; # return filepath of filled-in file return 0 } # Set environment variables TYPE="prod" # in script file source env/production.vars # read them in from a file DEPLOYMENT_FILE="app.flexible.yaml" tmpfile="$(prepare_yaml "app.tpl.yaml")" if [ $? -eq 0 ]; then mv "$tmpfile" "$PWD/$DEPLOYMENT_FILE" # gcloud wants specific filename gcloud app deploy "$DEPLOYMENT_FILE" rm "$DEPLOYMENT_FILE" # Cleanup temporary file fi
注意:此脚本也可以使用 subprocess 库以 Python 编写。这就是我为 GKE 项目自动构建的方法。
接下来,获取应用程序 app.yaml 文件并添加 bash 变量字符串替换,如本示例 app-tpl.flexible.yaml:
# example app-tpl.flexible.yaml --- runtime: custom env: flex env_variables: MYSQL_SOCK: "/cloudsql/${project}:${region}:${instance}" MYSQL_DB: "${db_name}" MYSQL_USER: "${db_user}" MYSQL_PASSWORD: "${db_pw}"
制作包含必要变量的文件(在源代码管理中被忽略)
#!/bin/bash # FILE: env/production.vars project="project-name" region="europe-west1" instance="prod001" db_name="db001" db_user="root" db_pw="qwerty"
这应该由答案 #2 解决。在要执行的脚本上添加一个标志/选项,用于交换 SQL 实例或更改环境变量名称。
看起来你需要配置两个 CloudSQL 连接实例,然后自动 CloudSQL 代理将能够连接到 2 个数据库。请参阅cloud.google.com/sql/docs/mysql/connect-app-engine-flexible和这个回答因为他们使用不同的端口号来工作。
祝你好运!
答案2
@codejedi 的上述回答(使用 Google Secrets Manager 或在部署期间注入它们)是我今天要采取的措施。
在我发布这个问题时(2018 年 4 月),Google Secrets Manager 还要 18 个月才会发布。
我最终决定自己解决这个问题使用数据存储区。