深入解析 Terraform AWS Provider 的 aws_elb 数据源:读取 Classic Load Balancer 配置
【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws
aws_elb是 terraform-provider-aws 中用于读取 AWS Classic Elastic Load Balancer(简称 Classic ELB,下称 ELB)运行时配置的数据源。当模块以负载均衡器名称作为输入、需要进一步获取其安全组、子网、监听器、健康检查与 DNS 信息时,用它替代硬编码值是最直接的方式。读完本篇,你将掌握该数据源的完整参数与全部导出属性,理解其底层 AWS API 调用链与源码实现细节,并能在模块化 Terraform 工程中正确使用它。
数据源定位:Classic ELB 还是 ALB/NLB?
aws_elb数据源专门面向 AWS 于 2015 年前后发布的 "Classic" Elastic Load Balancer(第一代负载均衡服务)。在 AWS 推出 Application Load Balancer(ALB)与 Network Load Balancer(NLB)之后,Terraform 社区通常将它们统称为 "v2" 负载均衡器。如果你需要读取的是 ALB 或 NLB 的信息,应改用aws_lb数据源;aws_elb仅适用于 Classic ELB。
数据源文档开篇即给出典型动机:
当一个模块将 LB 作为输入变量接收、需要据此确定其关联的安全组等信息时,该数据源非常有用。
例如,一个应用模块接收lb_name字符串作为输入,内部通过aws_elb数据源拿到该 ELB 的全部运行时属性,从而推导出安全组、可用区、子网等依赖关系,而无需在调用方与模块之间层层传递这些值。
最小可用示例
数据源的全部使用方式围绕name参数展开。文档给出的最小示例:
variable "lb_name" { type = string default = "" } data "aws_elb" "test" { name = var.lb_name }执行terraform plan或terraform apply时,Provider 会调用 AWS 的DescribeLoadBalancers与DescribeLoadBalancerAttributesAPI,按name精确匹配一个 Classic ELB,并将结果写入状态。随后在配置中即可引用data.aws_elb.test.dns_name、data.aws_elb.test.security_groups等导出属性。
若指定的名称不存在,数据源读取会直接失败并返回形如reading ELB Classic Load Balancer (...) : ...的错误(对应源码中的错误包装逻辑,见 load_balancer_data_source.go),因此name对应的 ELB 必须真实存在。
Argument Reference:参数说明
数据源支持以下参数:
| 参数 | 必填 | 说明 |
|---|---|---|
name | 是 | 负载均衡器的唯一名称。底层对应 AWS API 的LoadBalancerName,用于精确匹配。 |
region | 否 | 数据源所在的 AWS 区域,默认使用 Provider 配置中设置的区域。 |
注意一个值得说明的细节:虽然文档层面列出了region参数,但从当前仓库中数据源的 schema 定义(load_balancer_data_source.go)看,schema 中只显式声明了name为必填属性,其余均为Computed。实际读取时使用的是 Provider 连接(meta.(*conns.AWSClient).ELBClient(ctx))所对应的区域——也就是说区域由 Provider 配置统一决定,这也与"Defaults to the Region set in the provider configuration"的说明一致。
Attribute Reference:完整导出属性
数据源文档明确说明:返回的属性与aws_elb资源完全一致。结合资源文档与数据源源码 schema,data.aws_elb.*完整导出以下属性:
基础标识与网络属性
| 属性 | 类型 | 说明 |
|---|---|---|
id | string | ELB 的名称(与name相同)。 |
name | string | ELB 的名称。 |
arn | string | ELB 的 Amazon Resource Name。 |
dns_name | string | ELB 的 DNS 名称,用于接入流量解析。 |
zone_id | string | ELB 的规范 hosted zone ID,常配合 Route 53 Alias 记录使用。 |
internal | bool | 是否为内网(internal)ELB。 |
availability_zones | set(string) | ELB 服务流量的可用区列表(EC2-classic 场景)。 |
subnets | set(string) | ELB 挂载的子网 ID 列表(VPC 场景)。 |
security_groups | set(string) | 分配给 ELB 的安全组 ID 列表。 |
instances | set(string) | ELB 后端实例池中的实例 ID 列表。 |
监听器与健康检查
| 属性 | 类型 | 说明 |
|---|---|---|
listener | set | 监听器配置块列表,每个块包含instance_port、instance_protocol、lb_port、lb_protocol、ssl_certificate_id。 |
health_check | list | 健康检查配置块,包含healthy_threshold、unhealthy_threshold、target、interval、timeout。 |
行为特性与安全属性
| 属性 | 类型 | 说明 |
|---|---|---|
cross_zone_load_balancing | bool | 是否开启跨可用区负载均衡。 |
idle_timeout | int | 连接允许空闲的秒数。 |
connection_draining | bool | 是否开启连接排空。 |
connection_draining_timeout | int | 连接排空允许的秒数。 |
desync_mitigation_mode | string | HTTP 反同步缓解模式,取值monitor、defensive(默认)、strictest。 |
access_logs | list | 访问日志配置块,包含bucket、bucket_prefix、interval、enabled。 |
source_security_group | string | 可用于后端应用实例入站规则的安全组名称(Classic 或默认 VPC 场景)。 |
source_security_group_id | string | 后端应用实例入站规则使用的安全组 ID(仅 VPC 中的 ELB 可用)。 |
tags/tags_all | map | 资源标签映射。tags_all包含从 Providerdefault_tags继承的标签。 |
这些导出属性与资源的对应关系完全一致:例如资源侧ssl_certificate_id仅在lb_protocol为 HTTPS 或 SSL 时合法,数据源读取的listener块也会原样呈现这些字段。
源码级剖析:数据源是如何读取 ELB 的
数据源注册与 Schema
数据源在 load_balancer_data_source.go 中通过注解// @SDKDataSource("aws_elb", name="Classic Load Balancer")声明,由 Provider 的代码生成机制注册到aws_elb地址。其实现是典型的 Plugin SDK v2schema.Resource:name为Required,其余 20 余个字段全部标记为Computed,意味着该数据源只读、不做任何写操作。
读取流程与 API 调用链
核心读取逻辑dataSourceLoadBalancerRead(load_balancer_data_source.go)按以下顺序工作:
- 按名称查找 ELB:调用
findLoadBalancerByName(load_balancer.go),其内部发起DescribeLoadBalancers请求,并将AccessPointNotFoundException映射为retry.NotFoundError——这是 Provider 把"资源不存在"统一表达为 NotFound 的标准做法,随后通过tfresource.AssertSingleValueResult断言唯一结果。 - 读取属性配置:发起
DescribeLoadBalancerAttributes请求,取得LoadBalancerAttributes(访问日志、连接排空、跨可用区、空闲超时、反同步缓解等)。 - 手工构造 ARN:通过
arn.ARN结构体拼接elasticloadbalancing服务的 ARN,资源段为loadbalancer/<名称>,分区、区域、账号 ID 均取自 Provider 客户端上下文。 - 补齐安全组 ID:AWS 的
DescribeLoadBalancers响应只返回源安全组名称与属主,不返回安全组 ID。源码在lb.VPCId存在时,会进一步调用 EC2 客户端的FindSecurityGroupByNameAndVPCIDAndOwnerID反向查找source_security_group_id(load_balancer_data_source.go)。 - 处理访问日志的"不可删除"语义:注释明确指出 AWS API 不允许删除
access_logs、只能禁用它。源码通过d.GetChange("access_logs")对比配置与远端状态,只有配置中存在访问日志块且远端已启用时才写入状态,从而避免把外部 API 创建的日志配置误判为 drift(相关历史 issue 详见源码注释)。 - 读取标签:调用
listTags获取标签并通过IgnoreAWS().IgnoreConfig(ignoreTagsConfig)过滤后写入tags。 - 回填健康检查:健康检查只有一个,
lb.HealthCheck.Target非空时通过flattenHealthCheck写入。
字段展开函数
数据源用到的展开函数集中在 flex.go:
flattenAccessLog(L17-L42):将 API 的AccessLog对象映射为bucket、bucket_prefix、interval、enabled四个字段;flattenHealthCheck(L56-L73):映射healthy_threshold、unhealthy_threshold、target、timeout、interval;flattenInstances(L75-L79):把 API 的Instance列表投影为实例 ID 字符串列表;flattenListenerDescriptions(L132 起):将每个监听器映射为instance_port、instance_protocol、lb_port、lb_protocol、ssl_certificate_id,并统一转为小写协议名。
而desync_mitigation_mode这类位于AdditionalAttributes中的扩展属性,则在读取循环中按常量elb.http.desyncmitigationmode(定义于 consts.go)逐一匹配后写入状态。
实测验证:数据源如何被测试覆盖
仓库为数据源提供了完整的验收测试TestAccELBLoadBalancerDataSource_basic(load_balancer_data_source_test.go)。该测试先创建一个完整的 VPC、两个子网、一个安全组与一个内部 ELB,再通过data "aws_elb" "test" { name = aws_elb.test.name }读取它,并断言:
cross_zone_load_balancing、internal等布尔属性与预期一致;idle_timeout精确等于资源侧的30;subnets.#、security_groups.#数量正确;desync_mitigation_mode默认值为defensive;- 标签
tags.Name、tags.TestName完整回传; dns_name、zone_id非空;- 数据源的
arn与资源侧aws_elb.test.arn完全一致(TestCheckResourceAttrPair)。
测试中特意将 ELB 名称控制在 32 个字符以内(代码注释:ELB name 必须小于 32 字符),这正是 Classic ELB 的命名约束。这段测试既是对数据源行为的权威验证,也是"模块内通过数据源反查 ELB 属性"这一用法的可直接复制的示例。
实战建议与注意事项
- 模块输入用名称而非属性:在模块边界传递
lb_name字符串,模块内部用aws_elb数据源展开安全组、DNS、子网等派生属性,可避免模块接口膨胀,也方便对已存在(非 Terraform 管理)的 ELB 做只读集成。 - 区分数据源与资源:
aws_elb资源负责创建与管理 ELB(完整参数见 aws_elb 资源文档),数据源只负责读取。若需要管理而非查询,应使用资源。 source_security_group_id的适用性:该属性仅对 VPC 内的 ELB 生效,且需要额外一次 EC2 API 查询;EC2-classic 场景下应使用source_security_group。- 区分 ELB 家族数据源:同目录下还有 aws_elb_hosted_zone_id 与 aws_elb_service_account 两个配套数据源,分别用于获取 ELB 的 Route 53 hosted zone ID 与访问日志写入账号 ID,常与
aws_elb组合使用;ALB/NLB 场景请改用 aws_lb 数据源。 - 资源属性参照:数据源返回的所有属性与
aws_elb资源完全一致,若需了解各属性的取值范围(如desync_mitigation_mode的合法值、ssl_certificate_id的 ECDSA 曲线限制),可直接查阅该资源文档。
小结
aws_elb数据源是 Classic ELB 生态中"只读集成"的关键入口:以name为唯一必填参数,返回与资源侧完全一致的完整属性集。其底层由DescribeLoadBalancers+DescribeLoadBalancerAttributes两条 AWS API 驱动,辅以 EC2 安全组反查、ARN 手工拼接、标签过滤与访问日志语义处理等细节实现,并由验收测试严格保证行为正确。无论是对既有 ELB 做只读查询,还是在模块化工程中传递 LB 依赖,它都是可靠且标准的选择。
【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考