How should I automatically associate a Kubernetes-provisioned elastic load balancer with a Route 53 alias?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
If Kubernetes creates an AWS load balancer for a Service or Ingress, the cleanest way to keep Route 53 in sync is usually external-dns. It watches Kubernetes resources, discovers the cloud load balancer hostname, and updates DNS records automatically. That is much safer than trying to maintain Route 53 aliases by hand after every rollout or replacement.
Why Manual DNS Entries Drift
AWS load balancer hostnames are assigned dynamically. If you create the Route 53 alias manually, you now have two sources of truth:
- Kubernetes decides which load balancer exists
- Route 53 decides which hostname your users reach
That works until the load balancer is recreated, the service is replaced, or the cluster is rebuilt. Then DNS drifts away from the real infrastructure.
The better design is to make the DNS name part of the Kubernetes resource and let a controller reconcile the Route 53 record.
Use external-dns on a Service
For a Service of type LoadBalancer, add an annotation that declares the desired public hostname.
external-dns reads that annotation, sees the AWS load balancer created for the service, and upserts the matching Route 53 record.
Or Use It on an Ingress
If the public entry point is really an ingress controller rather than a directly exposed service, annotate the Ingress instead.
Choose the resource that actually owns the public hostname. For a shared ingress layer, that is usually the Ingress, not the backend Service.
Deploy external-dns With Route 53 Access
external-dns needs two kinds of permissions:
- read access to the relevant Kubernetes resources
- permission to change the Route 53 hosted zone
A typical deployment passes arguments such as these:
The TXT registry is important because it helps track ownership and prevents multiple clusters or controllers from fighting over the same DNS records.
Let Terraform Manage the Zone, Not the Dynamic Records
If your platform uses Terraform, a good split of responsibility is:
- Terraform creates the hosted zone and IAM role
- Kubernetes plus
external-dnsmanages the application records dynamically
That keeps infrastructure definitions clean while still allowing services to appear and disappear without manual DNS work.
Why Custom Scripts Are Usually Worse
A custom script can watch Kubernetes, look up the AWS load balancer, and call Route 53. But that script now needs:
- retries
- reconciliation logic
- idempotency
- credentials
- monitoring
external-dns already solves those problems. In most cases, it is better to use the existing controller than to build a smaller, less battle-tested copy of it.
Common Pitfalls
- Missing IAM permissions for Route 53 even though
external-dnsis running fine in the cluster. - Annotating the wrong Kubernetes object and expecting the DNS record to follow a different load balancer.
- Forgetting TXT ownership records and then getting conflicts between clusters or controllers.
- Expecting the DNS record to appear instantly when Route 53 propagation still takes time.
- Managing the same record manually while
external-dnsis also trying to reconcile it.
Summary
- '
external-dnsis usually the right automation tool for mapping Kubernetes-created AWS load balancers into Route 53.' - Put the desired hostname in an annotation on the
ServiceorIngressthat owns the public endpoint. - Give the controller scoped permission to update the hosted zone.
- Use TXT ownership records to avoid conflicts and drift.
- Keep DNS derived from Kubernetes state instead of maintaining aliases by hand.

