首页 > 解决方案 > 在 AWS 上存储 Docker 容器的配置文件的最佳方式是什么?

问题描述

我有一个 node.js 应用程序,它有一个包含敏感数据的配置文件。我想通过 AWS ECS(集群)作为 docker 容器启动它。

存储敏感配置数据的最佳方式是什么?

我目前正在通过 Docker 容器的任务定义中的环境变量发送它们,但必须有更好的方法来做到这一点。

这种事情的最佳做法是什么?我应该使用 Docker 机密还是 Amazon 机密管理器?

我知道这是一个非常笼统的问题,但我找不到答案,所以也许有人有建议?

标签: amazon-web-servicesdockerenvironment-variablescontainersamazon-ecs

解决方案


好问题。我同意 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>"
    }
  ]
},

推荐阅读