Terraform 和 AWS ECS:类似于 Kubernetes 或 Docker swarm 的配置/秘密

Posted

技术标签:

【中文标题】Terraform 和 AWS ECS:类似于 Kubernetes 或 Docker swarm 的配置/秘密【英文标题】:Terraform and AWS ECS: Configs/Secrets similar to Kubernetes or Docker swarm 【发布时间】:2020-10-15 22:58:01 【问题描述】:

AWS ECS 生态系统中是否有类似 Kubernetes / Docker Swarm 的秘密?我知道使用 SSM 参数存储或 S3 存储桶的选项,但两者在可用性方面无法与 Kubernetes 或 Swarm 中的解决方案相媲美。

SSM 参数存储限制为每个密钥 4/8 KB,因此无法用于更大的配置文件。 Kubernetes 允许每个密钥最多 1 MB。

SSM PS 和 S3 都要求我为不支持通过环境变量进行配置的所有内容维护不同的映像(我所知道的将配置数据放入 ECS 中的容器的唯一方法)。

我是否缺少明显更简单的解决方案?

目前的工作流程对我来说是这样的:

    使用 base64 编码创建 SSM 参数 创建将环境变量解析为目标文件的映像(例如 nginx),例如 nginx.conf,然后调用默认入口点并传递任何参数。 在我的 Terraform ECS 任务定义中使用 secrets

这是一个 Dockerfile 和 run.sh 的示例

#!/bin/sh

echo "version 1.0"

if [ -z $NGINX_CONF ]
then
  echo "no settings received for nginx.conf, connecting with the default settings"
else
  echo $NGINX_CONF | base64 -d > /etc/nginx/nginx.conf
  echo "created /etc/nginx/nginx.conf"
fi

/docker-entrypoint.sh $@
FROM nginx:latest
COPY files/run.sh /bin/run.sh
ENTRYPOINT [ "/bin/run.sh" ]
CMD ["nginx", "-g", "daemon off;"]

【问题讨论】:

Secrets manager 最多支持 64kb。这对你来说足够了吗?将完整的配置文件放入环境变量的想法对我来说听起来像是一个病态的用例。更典型的做法是只传入需要更改的部分,然后使用模板技术从中生成配置。这需要通过环境变量或机密存储传递的数据要少得多。 不知道secrets manager,我去看看。但仅此一项并不能解决我维护一组图像的需要,以便我自己为不支持开箱即用的图像提供此模板。 Nginx、普罗米修斯…… 你能指出官方 NGINX 映像在哪里为完整配置文件获取环境变量吗?我没有看到这种行为。我看到文件挂载到 Kubernetes pod 的正常方式是通过配置映射,然后将这些映射挂载到容器中的特定位置,而不是通过秘密拉入。 好吧,我解释错了我的情况。我不得不在参数存储中存储nginx.conf 之类的文件,这让我很烦恼。不仅如此,在运行时将文件放入容器的唯一方法是作为环境变量。这意味着我必须修改图像以获取 env 变量并将其内容放在文件所属的任何位置 是的,我更喜欢使用 Kubernetes 或 Docker Swarm,但我目前坚持使用 ECS:/ 【参考方案1】:

我找到了一个我现在满意的解决方案:

这是我使用 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>"
    
  ]
,

【讨论】:

以上是关于Terraform 和 AWS ECS:类似于 Kubernetes 或 Docker swarm 的配置/秘密的主要内容,如果未能解决你的问题,请参考以下文章

Terraform + AWS ECS,持续部署流程?

使用 terraform 的 AWS ECS 容量提供程序

Terraform 创建了 AWS ECS 基础设施:运行状况检查一直失败

在 Terraform 的 aws_ecs_task_definition 资源中设置 ulimit 堆栈大小

Terraform:ECS 服务 - InvalidParameterException

用于 ECS 任务/容器的 Terraform AWS CloudWatch 日志组