amazon-web-services - 在 AWS 上存储 Docker 容器的配置文件的最佳方式是什么?
问题描述
我有一个 node.js 应用程序,它有一个包含敏感数据的配置文件。我想通过 AWS ECS(集群)作为 docker 容器启动它。
存储敏感配置数据的最佳方式是什么?
我目前正在通过 Docker 容器的任务定义中的环境变量发送它们,但必须有更好的方法来做到这一点。
这种事情的最佳做法是什么?我应该使用 Docker 机密还是 Amazon 机密管理器?
我知道这是一个非常笼统的问题,但我找不到答案,所以也许有人有建议?
解决方案
好问题。我同意 SSM Parameter Store 或 AWS Secrets Manager 是这项工作的推荐工具,但如果您遵循基础设施即代码原则,我认为它们并不那么有用。
因此,我将我的配置文件保存在同一个 Git 存储库中的 Terraform 脚本旁边,并在运行时将实际敏感数据(密码、密钥等)从 SSM 参数存储注入到特定的目标文件中。
与使用 AWS 提供的解决方案相比,这有几个优点:
- 没有大小限制(在免费版本中,SSM Parameter Store 将您限制为 4 KB)。
- 非敏感配置受版本控制,具有随之而来的所有优势。
- 我可以轻松查看当前使用的配置并更新它们,而不是登录 AWS 控制台等。
以下是我使用 Terraform / AWS ECS 管理配置/机密的方法
基本思想如下:我们将没有敏感数据的配置文件存储在 Terraform 旁边的存储库中。秘密存储在 AWS 参数存储中。为了在运行时将数据放入我们的容器中,我们修改入口点。我们当然可以只创建修改后的图像,但在我看来这会产生很大的维护开销。使用入口点方法,我们可以继续使用原版图像。
缺点是我必须创建自定义入口点脚本。这意味着我必须找到我感兴趣的镜像的 Dockerfile 并提取用于启动镜像中运行的实际进程的命令。
我有一个这样的 git 存储库:
├── files
│ └── promstack
│ ├── grafana
│ │ ├── default-datasources.yml
│ │ ├── grafana.ini
│ │ └── run.sh
│ ├── loki
│ │ └── run.sh
│ ├── nginx
│ │ ├── nginx.conf
│ │ └── run.sh
│ └── prometheus
│ ├── prometheus.yml
│ ├── rules-alerting.yml
│ ├── rules-recording.yml
│ └── run.sh
├── myscript.tf
└── variables.tf
run.sh
脚本代表入口点。这是一个示例run.sh
:
#!/bin/sh
set -x
require () {
if [ ! "$1" ]; then
echo "ERROR: var not found"
exit 1
fi
}
expand () {
var_name="${1}"
file="${2}"
eval var="\$$var_name"
sed -i "s+\${${var_name}}+${var}+g" ${file}
sed -i "s+\$${var_name}+${var}+g" ${file}
}
require ${GRAFANA_INI}
require ${DEFAULT_DATASOURCES_YML}
require ${DOMAIN}
echo ${GRAFANA_INI} | base64 -d > /etc/grafana/grafana.ini
chmod 666 /etc/grafana/grafana.ini
expand DOMAIN /etc/grafana/grafana.ini
echo ${DEFAULT_DATASOURCES_YML} | base64 -d > /etc/grafana/provisioning/datasources/default.yml
chmod 666 /etc/grafana/provisioning/datasources/default.yml
su -s "/bin/sh" -c "/run.sh" grafana
这是 Terraform 脚本的一部分(准确地说是 ECS 容器任务定义):
{
name: "grafana",
image: "grafana/grafana:7.0.5",
portMappings: [{
containerPort : 3000,
hostPort: 0,
protocol: "tcp"
}],
user: "0",
entryPoint: [ "/bin/sh", "-c", join(" ", [
"export DEFAULT_DATASOURCES_YML=${base64encode(file("${path.module}/files/promstack/grafana/default-datasources.yml"))};",
"export GRAFANA_INI=${base64encode(file("${path.module}/files/promstack/grafana/grafana.ini"))};",
"echo '${base64encode(file("${path.module}/files/promstack/grafana/run.sh"))}' | base64 -d | sh;"
])],
secrets: [
{
name: "DOMAIN",
valueFrom: "<my ssm parameter>"
}
]
},
推荐阅读
- ethereum - 以太坊 - 更新配置属性
- python-3.x - 错误信息 FileNotFoundError: [Errno 2] No such file or directory
- c++ - 以度为单位定义一个 boost::units 角度
- c - 无法解决 Visual Studio 中的 LNK 2001 错误
- react-native - Appium desktop v1.20.0 iOS 看不到基于 react-native 构建的屏幕子组件中的元素及其 id?
- reactjs - 如何使用 Jest 部分模拟自定义反应钩子?
- android - 在 Android 11 中将文件从外部存储复制到内部存储
- installation - 在 Windows 7 上安装 Python 3.8.10 的 TA-Lib 包时遇到问题
- c# - 在 RestSharp 和 C# 中解析 JSON 内容时出错
- azure - ADF 管道成本