Data aws_lb in Terraform AWS Provider: ARN Lookup, Tag Matching, and Kubernetes Controller Patterns

The aws_lb data source in the Terraform AWS provider exposes read-only information about an existing Elastic Load Balancer. It is the current name for the resource previously documented as aws_alb. The functionality is identical.

The data source proves useful when a module accepts a load balancer as an input variable and needs to, for example, determine the security groups associated with it, discover its ARN for downstream references, or resolve attributes that are only known after the load balancer is created by another system such as the AWS Load Balancer Controller.

The data source supports three optional input attributes. Only one is typically required to uniquely identify the load balancer.

Core Arguments and Identifier Options

The data source can be addressed by ARN, by name, or by tag set.

The following arguments are supported:

  • arn - Optional. The full ARN of the load balancer.
  • name - Optional. The unique name of the load balancer.
  • tags - Optional. A map of tags used to filter load balancers.

A common pattern for module inputs is to make both ARN and name optional variables with empty defaults and pass them through to the data source:

```hcl
variable "lb_arn" {
type = string
default = ""
}

variable "lb_name" {
type = string
default = ""
}

data "awslb" "test" {
arn = var.lb
arn
name = var.lb_name
}
```

This pattern allows a caller to supply either identifier. When both are empty the data source will error, which is the expected guardrail.

When ARN or name is known, resolution is deterministic and fast. The provider queries the load balancer directly by that identifier and returns a full set of computed attributes including arn, name, id, security_groups, subnets, vpc_id, load_balancer_type, dns_name, and the full tag map.

Tag-Based Lookup and the Missing Filter Block

A frequent use case is to look up a load balancer created outside of Terraform, for example by the AWS Load Balancer Controller in a Kubernetes cluster. In those environments the load balancer does not have a predictable name from the Terraform perspective, but it carries Kubernetes controller tags.

Typical tags populated by the controller on an Application Load Balancer include:

  • ingress.k8s.aws/resource = LoadBalancer
  • ingress.k8s.aws/stack = xyzalb
  • elbv2.k8s.aws/cluster = "my-shiny-eks-cluster"

Operators often want to extract the ARN of an AWS LB using a tag such as elbv2.k8.aws/cluster = "my-shiny-eks-cluster" and ideally also narrow it down by the vpc-id.

The aws_lb data source does not expose a filter block or attribute. It instead has three optional attributes - arn, name and tags. The filter command is not available for this data resource.

Because of that limitation, the correct syntax for tag matching is a map attribute named tags, not a nested tags {} block.

An incorrect attempt that produces a parsing error looks like:

hcl data "aws_lb" "alb_listener_details" { tags { elbv2.k8.aws/cluster = "my-shiny-eks-cluster" } }

The error produced is:

Error: Argument or block definition is required. on main.tf line 33, in data "aws_lb" "alb_listener_details" 33: elbv2.k8.aws/cluster = "my-shiny-eks-cluster" "An argument or block definition is required here"

The provider interprets tags {} as a block definition, but tags is an argument that expects a map. The correct form uses map syntax:

hcl data "aws_lb" "alb_listener_details" { tags = { "elbv2.k8.aws/cluster" = "my-shiny-eks-cluster" } }

This working example is frequently shared to pre-empt repeated questions about the same problem.

When using tag matching, the provider returns the first load balancer that matches the supplied tag set. If multiple load balancers share the same tag values, the result is non-deterministic. This is an important operational caveat.

Tag Matching Behavior and Limitations

The tags argument accepts a map of string to string. The provider performs an AND match across all supplied key/value pairs. There is no support for OR logic, wildcard values, or tag key prefix matching within the data source itself.

Because there is no filter block, operators cannot combine tag matching with additional AWS API filters such as VPC ID, load balancer type, or scheme. If narrowing down by vpc-id is required, the typical workaround is to add a second tag that encodes the VPC, or to retrieve the load balancer via name or ARN after an external lookup.

The reference discussion notes attempts to use the standard linux backslash options for continuation and the standard Terraform filter syntax, neither of which is applicable here.

Table 1 summarizes the input options for the data source.

Argument Type Optional Purpose
arn string Yes Full ARN of the load balancer
name string Yes Unique name of the load balancer
tags map(string) Yes Tag key/value pairs for lookup

Table 2 shows common Kubernetes controller tags observed on ALBs managed by AWS Load Balancer Controller.

Tag Key Example Value Meaning
ingress.k8s.aws/resource LoadBalancer Resource type created by controller
ingress.k8s.aws/stack xyzalb Stack identifier
elbv2.k8s.aws/cluster my-shiny-eks-cluster EKS cluster name

Interaction with AWS Load Balancer Controller

AWS Load Balancer Controller is a controller to help manage Elastic Load Balancers for a Kubernetes cluster. It satisfies Kubernetes Ingress resources by provisioning Application Load Balancers. It satisfies Kubernetes Service resources by provisioning Network Load Balancers. It satisfies Kubernetes Gateway resources by provisioning Network Load Balancers and Application Load Balancers.

This project was formerly known as "AWS ALB Ingress Controller", we rebranded it to be "AWS Load Balancer Controller".

AWS ALB Ingress Controller was originated by Ticketmaster and CoreOS as part of Ticketmaster's move to AWS and CoreOS Tectonic.

Gateway resources are provisioned by the controller as Network Load Balancers and Application Load Balancers.

In practice, teams running EKS with the controller often need to reference the ALB created by the controller from Terraform. Since the controller owns the lifecycle of the load balancer, Terraform cannot create it. The aws_lb data source with tag matching is the bridge.

A typical workflow is:

  • Deploy EKS and install AWS Load Balancer Controller
  • Create an Ingress with annotations that cause the controller to provision an ALB with tags including elbv2.k8s.aws/cluster
  • In Terraform, use data "aws_lb" with tags = { "elbv2.k8s.aws/cluster" = var.cluster_name } to retrieve the ARN
  • Use the retrieved ARN to create downstream resources such as listeners, rules, or CloudFront origins

The tag key names contain dots and slashes, which must be quoted in HCL map keys to avoid parsing issues.

Practical Patterns and Pitfalls

When the load balancer name is known, using name is the most reliable identifier. Names are unique within an AWS account and region.

When the ARN is known, using arn is the most efficient because it requires no listing.

Tag-based lookup is convenient for controller-managed resources but carries risks:

  • Tag collisions across multiple load balancers in the same region can return an unexpected result
  • Tag values can change if the controller is reconfigured
  • The data source does not support partial matches, so exact key/value pairs are required

If a more precise selection is needed, a two-step approach is common: first use an external data source or a custom script to list load balancers by tags via the AWS API, then pass the discovered ARN or name into Terraform as a variable. This preserves deterministic behavior.

Another consideration is that the aws_lb data source returns information about a load balancer, not about listeners or rules. Listener details require separate data sources such as aws_lb_listener and aws_lb_listener_rule, which themselves require the load balancer ARN.

Conclusion

The aws_lb data source provides a read-only interface to an existing load balancer and is identical in functionality to the legacy aws_alb name. It supports identification by ARN, by name, or by an exact tag map. The absence of a filter block means operators must use the tags map argument with correct HCL map syntax, not a nested block.

For Kubernetes environments managed by AWS Load Balancer Controller, tag-based lookup using keys such as elbv2.k8s.aws/cluster is the practical method to bridge controller-provisioned resources into Terraform. The pattern works reliably when tag values are unique enough to identify a single load balancer, and it fails predictably when multiple resources share the same tags.

Designing modules around optional lb_arn and lb_name variables allows both direct identifier passing and tag-based discovery. Understanding the three optional attributes - arn, name and tags - and the lack of filter support avoids the common parsing error "An argument or block definition is required here" and enables safe integration of Terraform with externally managed load balancers.

Sources

  1. https://docs.w3cub.com/terraform/providers/aws/d/lb.html
  2. https://discuss.hashicorp.com/t/how-to-extract-the-arn-of-a-aws-lb-using-a-tag-that-has-in-it/45277
  3. https://github.com/kubernetes-sigs/aws-load-balancer-controller

Related Posts