Terraform AWS Provider 中 aws_ecs_container_definition 数据源:按容器名读取 ECS 任务定义详情
【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws
本篇技术指南围绕 Terraform AWS Provider 的aws_ecs_container_definition数据源展开,介绍如何在 Terraform 配置中从已有的 ECS 任务定义(Task Definition)里精确提取某一个容器的镜像、内存、CPU、环境变量等配置详情;读完后你将掌握该数据源的完整参数与属性参考、底层实现调用链(DescribeTaskDefinition+ 容器名过滤)、image_digest的解析规则与边界情况,以及可复制的端到端示例与验收测试写法。
数据源定位与适用场景
官方文档描述(见 website/docs/d/ecs_container_definition.html.markdown):
The ECS container definition data source allows access to details of a specific container within an AWS ECS service.
aws_ecs_container_definition是一个只读数据源:它不创建或管理任何 AWS 资源,而是根据"任务定义 ARN + 容器名"两个条件,从 AWS ECS 控制面查询该任务定义中指定容器的完整配置,并把结果导出为 Terraform 属性,供其他资源或output引用。
典型应用场景:
- 用 Terraform 管理了一个
aws_ecs_task_definition(尤其是container_definitions以 JSON 字符串 heredoc 形式书写、无法用属性直接解析的场景),需要把其中某个容器的镜像、内存等配置"取出来"传递给其他资源(如依赖该镜像的其他服务、日志配置、告警规则等); - 跨工作目录/状态引用:从另一个 Terraform 根模块或已有环境中已创建的任务定义中,按容器名读取镜像与 digest,实现配置复用;
- 审计与校验:确认线上任务定义中某容器实际使用的镜像与内存配置是否符合预期。
从 internal/service/ecs/service_package_gen.go 的服务注册表可以看到,该数据源以aws_ecs_container_definition类型名注册为 ECS 服务的 SDK 数据源,并声明了Region: inttypes.ResourceRegionDefault(),即支持按 provider 默认 Region 解析,同时可通过region参数覆盖。
基本用法
文档给出的最小示例:
data "aws_ecs_container_definition" "ecs-mongo" { task_definition = aws_ecs_task_definition.mongo.id container_name = "mongodb" }注意task_definition接受任务定义的ARN(文档 Argument Reference 中明确写为 "ARN of the task definition which contains the container")。aws_ecs_task_definition资源的id与arn均可以是 ARN 形式(取决于任务定义是否含命名空间前缀),传入后由 provider 原样作为DescribeTaskDefinition的入参。
参数参考(Argument Reference)
该数据源支持以下参数(完整继承自 website/docs/d/ecs_container_definition.html.markdown):
| 参数 | 必填 | 类型 | 说明 |
|---|---|---|---|
container_name | 是 | string | 要读取的容器定义名称,必须与任务定义 JSON 中的name字段完全一致 |
task_definition | 是 | string | 包含该容器的任务定义 ARN |
region | 否 | string | 资源所在 Region,默认使用 provider 配置中的 Region |
Schema 层面的对应定义在 internal/service/ecs/container_definition_data_source.go:container_name与task_definition均为Required字符串,其余字段全部为Computed,符合"只读数据源"的语义——所有输出字段均不接受用户写入。
属性参考(Attribute Reference)
该数据源在参数之外导出以下属性,源码中每个字段都与 SDK 的awstypes.ContainerDefinition一一对应:
| 属性 | Schema 类型 | 对应 SDK 字段 | 说明 |
|---|---|---|---|
cpu | int | def.Cpu | 该容器定义的 CPU 限制(单位与任务定义 JSON 中cpu字段一致) |
disable_networking | bool | def.DisableNetworking | 是否禁用网络 |
docker_labels | map(string) | def.DockerLabels | Docker 标签键值对 |
environment | map(string) | def.Environment | 容器环境变量,由 SDK 的[name, value]列表在 provider 内转换为map |
image | string | def.Image | 容器使用的 Docker 镜像(含 tag 或 digest 部分) |
image_digest | string | —(派生字段) | 从image字符串中解析出的"冒号后"部分,见下文专题说明 |
memory | int | def.Memory | 容器内存硬限制(MiB) |
memory_reservation | int | def.MemoryReservation | 内存软限制(MiB),系统内存紧张时 Docker 尽力将容器内存保持在该值 |
其中environment的列表转 map 逻辑可以在 internal/service/ecs/container_definition_data_source.go 中直接看到:
var environment = map[string]string{} for _, v := range def.Environment { environment[aws.ToString(v.Name)] = aws.ToString(v.Value) } d.Set(names.AttrEnvironment, environment)因此在 Terraform 中用data.aws_ecs_container_definition.mongo.environment.MY_KEY的点号语法即可按 key 取值。
实现原理:两步查找与错误处理
数据源的 Read 函数为dataSourceContainerDefinitionRead(internal/service/ecs/container_definition_data_source.go),其工作流程是:
- 从 provider 客户端获取 ECS 客户端:
conn := meta.(*conns.AWSClient).ECSClient(ctx); - 调用
findContainerDefinitionByTwoPartKey(ctx, conn, taskDefinition, containerName),这是一个"两段式 key"查找:先按任务定义 ARN 描述整个任务定义,再按容器名过滤; - 若任一步骤出错,统一包装为
SingularDataSourceFindError(tfresource.SingularDataSourceFindError("ECS Container Definition", err)),在 plan/apply 阶段呈现为清晰的"找不到该数据源目标"错误; - 找到后将各字段
d.Set到 Terraform state,并生成资源 ID。
关键的查找函数findContainerDefinitionByTwoPartKey(internal/service/ecs/container_definition_data_source.go)实现如下:
func findContainerDefinitionByTwoPartKey(ctx context.Context, conn *ecs.Client, taskDefinitionName, containerName string) (*awstypes.ContainerDefinition, error) { input := &ecs.DescribeTaskDefinitionInput{ TaskDefinition: aws.String(taskDefinitionName), } taskDefinition, _, err := findTaskDefinition(ctx, conn, input) if err != nil { return nil, err } return tfresource.AssertSingleValueResult(tfslices.Filter(taskDefinition.ContainerDefinitions, func(v awstypes.ContainerDefinition) bool { return aws.ToString(v.Name) == containerName })) }从源码结构看可以得出三点结论:
- 底层 API 是 ECS 的
DescribeTaskDefinition(由 internal/service/ecs/task_definition.go 中的findTaskDefinition统一封装调用,该函数被任务定义资源、数据源与容器定义数据源复用),而非针对容器定义的独立 API——ECS API 本身不提供"按容器名查询"的接口,过滤是在 provider 侧完成的; - 任务定义内的所有
ContainerDefinitions会经过tfslices.Filter按Name == containerName精确匹配过滤,随后由tfresource.AssertSingleValueResult断言"恰好一个结果":任务定义不存在、容器名拼错、或同名容器出现多次,都会导致查找失败并报错; - 整个查找是纯读操作,不会修改任何 AWS 资源,可安全用于
terraform plan阶段。
数据源自身的 Terraform state ID 由两段 key 拼接而成(internal/service/ecs/container_definition_data_source.go):
d.SetId(fmt.Sprintf("%s/%s", taskDefinition, aws.ToString(def.Name)))即task_definition/container_name形式,这与该数据源find...ByTwoPartKey的命名保持一致,也符合仓库内"以 ID 表达定位 key"的惯例(参见 docs/design-decisions/standardize-use-of-the-id-attribute.md)。
image_digest的解析规则与边界情况
image_digest是一个派生字段,并非直接来自 SDK 结构体。源码中的处理逻辑(internal/service/ecs/container_definition_data_source.go):
image := aws.ToString(def.Image) d.Set("image", image) if strings.Contains(image, ":") { d.Set("image_digest", strings.Split(image, ":")[1]) }即:仅当image字符串包含冒号时,取第一个冒号之后的部分作为image_digest。由此推出两种典型取值:
image配置 | image_digest输出 |
|---|---|
mongo:latest | latest(实际是 tag,而非 SHA digest) |
123456789012.dkr.ecr.us-west-2.amazonaws.com/my-app@sha256:abc123... | sha256:abc123...(真正的 digest) |
ubuntu(无任何冒号) | 不设置,state 中为空 |
需要注意:文档将其描述为"Digest of the docker image in use",但从实现看它只是镜像引用字符串的"冒号后缀",当镜像使用 tag 时取到的就是 tag。若你的场景严格依赖 SHA256 digest(如镜像不可变发布校验),应在配置侧保证任务定义中使用image@sha256:...形式引用镜像,而不是 tag。这一解析行为在验收测试中也有对应断言(见下节)。
完整可运行示例
文档示例依赖一个名为mongo的aws_ecs_task_definition。仓库验收测试 internal/service/ecs/container_definition_data_source_test.go 提供了一个包含 Cluster、Task Definition、Service 与数据源的端到端配置,可直接参考:
resource "aws_ecs_cluster" "default" { name = "tf_acc_td_ds_cluster_ecs_containter_definition" } resource "aws_ecs_task_definition" "mongo" { family = "tf_acc_td_ds_ecs_containter_definition" container_definitions = <<DEFINITION [ { "cpu": 128, "environment": [ { "name": "SECRET", "value": "KEY" } ], "essential": true, "image": "mongo:latest", "memory": 128, "memoryReservation": 64, "name": "mongodb" } ] DEFINITION } data "aws_ecs_container_definition" "mongo" { task_definition = aws_ecs_task_definition.mongo.id container_name = "mongodb" }对应地,该测试在 apply 后断言了数据源各属性(internal/service/ecs/container_definition_data_source_test.go):
resource.TestCheckResourceAttr("data.aws_ecs_container_definition.mongo", "image", "mongo:latest"), resource.TestCheckResourceAttr("data.aws_ecs_container_definition.mongo", "image_digest", "latest"), resource.TestCheckResourceAttr("data.aws_ecs_container_definition.mongo", "memory", "128"), resource.TestCheckResourceAttr("data.aws_ecs_container_definition.mongo", "memory_reservation", "64"), resource.TestCheckResourceAttr("data.aws_ecs_container_definition.mongo", "cpu", "128"), resource.TestCheckResourceAttr("data.aws_ecs_container_definition.mongo", "environment.SECRET", "KEY"),这些断言恰好覆盖了上文属性表中各字段的取值预期,也验证了image_digest = "latest"的解析规则。
使用限制与注意事项
- 只读且无缓存:该数据源只在读取时调用一次
DescribeTaskDefinition,不会持续跟踪任务定义的新版本。任务定义升级到新版本(新版本号对应新 ARN)后,需更新task_definition引用的 ARN 才会读到新容器配置; - 容器名必须精确匹配:查找是大小写敏感的字符串精确比较(
aws.ToString(v.Name) == containerName),拼写不一致会直接报 find error 而非静默返回空; - 属性覆盖面有限:该数据源只导出上文 8 个属性,任务定义中的
portMappings、logConfiguration、secrets、mountPoints等字段并未暴露。若需要这些细节,可考虑改用 aws_ecs_task_definition 相关数据源或直接在aws_ecs_task_definition资源侧以结构化 schema 管理容器定义; - Region 行为:未指定
region时遵循 provider 默认配置,与 internal/service/ecs/service_package_gen.go 中ResourceRegionDefault()的注册一致。
相关仓库入口
| 内容 | 路径 |
|---|---|
| 数据源官方文档 | website/docs/d/ecs_container_definition.html.markdown |
| 数据源 Schema 与 Read 实现 | internal/service/ecs/container_definition_data_source.go |
| 验收测试与端到端示例配置 | internal/service/ecs/container_definition_data_source_test.go |
findTaskDefinition(DescribeTaskDefinition封装) | internal/service/ecs/task_definition.go |
| ECS 服务数据源注册表 | internal/service/ecs/service_package_gen.go |
【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考