Networking
Resolve Route53 Records from Within EKS
Enable seamless DNS resolution for private Route53 records directly within your EKS cluster using CoreDNS.
If you already store internal records in a private Route53 hosted zone, it is often useful for workloads inside EKS to resolve those names directly. CoreDNS includes a Route53 plugin that makes this possible without introducing another DNS layer.
This approach works well when you already rely on Route53 private zones for internal service discovery, shared services, or AWS-managed resources and you want the cluster to resolve those names natively.
CoreDNS Route53 Plugin Overview
The Route53 plugin allows CoreDNS to serve records from one or more hosted zones. That makes private DNS names available to pods inside the cluster while keeping Kubernetes service discovery in place for everything else.
By default, the plugin refreshes records every minute, which is usually a sensible balance between freshness and API usage. Source: CoreDNS Route53 plugin.
Configuration Steps
To enable the plugin, update the CoreDNS ConfigMap and add the Route53 zone to the Corefile:
<domain> {
route53 <domain>.:<HOSTED_ZONE_ID>
}
Replace <domain> with your domain and <HOSTED_ZONE_ID> with the hosted zone ID from Route53.
An updated CoreDNS ConfigMap might look like this:
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
<domain> {
route53 <domain>.:<HOSTED_ZONE_ID>
}
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
This keeps existing Kubernetes service discovery intact while adding private Route53 resolution for the zone you specify.
IAM Permissions for CoreDNS
CoreDNS needs permission to read the hosted zone records. In AWS that usually means the following actions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["route53:GetHostedZone", "route53:ListHostedZones", "route53:ListResourceRecordSets"],
"Resource": "*"
}
]
}
If you are using IRSA, attach that policy to the service account CoreDNS uses.
Verifying the Configuration
After updating the ConfigMap and permissions, restart CoreDNS:
kubectl rollout restart deployment coredns -n kube-system
Then verify resolution from inside the cluster:
nslookup <record>.<domain> <coredns-cluster-ip>
You can also check the CoreDNS logs if you need to confirm queries are reaching Route53 successfully:
kubectl logs -n kube-system -l k8s-app=kube-dns
Troubleshooting
If CoreDNS fails to restart or the lookups do not resolve as expected, the first things to check are:
- IAM permissions for Route53 access
- the service account or role association used by CoreDNS
- syntax errors in the
Corefile - whether the hosted zone ID and domain match what is configured in Route53
Most problems usually come down to permissions or a small Corefile mistake.
Additional Configuration Options
If you need to control how often records are refreshed, use the refresh option rather than relying on the default:
<domain> {
route53 <domain>.:<HOSTED_ZONE_ID> {
refresh 3m
}
}
This is useful when you want to reduce AWS API calls or tune how quickly record changes become visible in-cluster.
Benefits of Using CoreDNS with Route53
- Simple integration with the cluster DNS path you already use
- Dynamic updates as records are refreshed from Route53
- Clean internal discovery for workloads that need private AWS names
- Native Kubernetes fit because CoreDNS is already the default DNS service in most clusters
Conclusion
Using the Route53 plugin in CoreDNS is a simple way to make private hosted zone records available inside EKS. With the right ConfigMap changes and IAM permissions in place, pods can resolve internal AWS addresses cleanly without adding another DNS component to the platform.