Automate DNS Records Creation With ExternalDNS on AWS Elastic Kubernetes Service
This article will help automate the process of creating and configuring DNS records in Route 53 using ExternalDNS and Ingress on Elastic Kubernetes Service (EKS).
Join the DZone community and get the full member experience.
Join For FreeExternalDNS is a handy tool in the Kubernetes world, making it easy to coordinate Services and Ingresses with different DNS providers. This tool automates the process, allowing users to manage DNS records dynamically using Kubernetes resources. Instead of being tied to a specific provider, ExternalDNS works seamlessly with various providers. ExternalDNS intelligently determines the desired DNS records, paving the way for effortless DNS management.
In this article, we'll explore what ExternalDNS is all about and why it's useful. Focusing on a specific situation — imagine a Kubernetes cluster getting updated and using Route 53 in AWS — we'll walk you through how ExternalDNS can automatically create DNS records in Route 53 whenever Ingresses are added. Come along for a simplified journey into DNS management and automation with ExternalDNS.
A high-level illustration of creation of DNS records in R53 using ExternalDNS on EKS
The Steps to Deploy ExternalDNS and Ingress
Deploying ExternalDNS and Ingress involves several steps. Below are the general steps to deploy ExternalDNS in a Kubernetes cluster (EKS).
1. Create IAM Policy and Role
Create an IAM policy and role with the necessary permissions for ExternalDNS to interact with Route53.
# External DNS policy to allow intract R53
ExternalDnsPolicy
Type AWS IAM ManagedPolicy
Properties
Description External DNS controller policy
PolicyDocument
Version'2012-10-17'
Statement
Effect Allow
Sid PermitR53Listings
Action
route53:ListResourceRecordSets
route53:ListHostedZones
Resource'*'
Effect Allow
Sid PermitR53Changes
Action
route53:ChangeResourceRecordSets
Resource arn aws route53 hostedzone/*
# I AM Role for External DNS
rExternalDnsRole
Type AWS IAM Role
Properties
RoleName"ExternalDns-Role"
AssumeRolePolicyDocument
Fn::Sub
|
"Version""2012-10-17"
"Statement"
"Effect""Allow"
"Principal"
"Federated" arn aws iam <ACCOUNT_NUMBER> oidc-provider/<OIDC_PROVIDER>
"Action""sts:AssumeRoleWithWebIdentity"
"Condition"
"StringEquals"
"<<EKS Cluster Id>>""system:serviceaccount:kube-system:external-dns"
clusterid !Sub "<<EKS Issuer>>:sub"
providerarn
Path /
ManagedPolicyArns
!Ref ExternalDnsPolicy
2. Deploy ExternalDNS
Deploy a service account that is mapped to the IAM role created in the previous step. Use the kubectl apply service_account.yaml to deploy the service account.
service_account.yaml:
apiVersion v1
kind ServiceAccount
metadata
labels
k8s-addon external-dns.addons.k8s.io
k8s-app external-dns
name external-dns
namespace kube-system
annotations
eks.amazonaws.com/role-arn <<provide IAM Role ARN that created on the above step>>
To check the name of your service account, run the following command:
kubectl get sa
Example output:
NAME SECRETS AGE
default 1 1h
external-dns 1 1h
In the example output above, 'external-dns' is the assigned name for the service account during its creation.
Run the following command:
kubectl apply external_dns.yaml
external_dns.yaml file:
apiVersion rbac.authorization.k8s.io/v1
kind ClusterRole
metadata
name external-dns
labels
app.kubernetes.io/name external-dns
rules
apiGroups""
resources"services""endpoints""pods""nodes"
verbs"get""watch""list"
apiGroups"extensions""networking.k8s.io"
resources"ingresses"
verbs"get""watch""list"
---
apiVersion rbac.authorization.k8s.io/v1
kind ClusterRoleBinding
metadata
name external-dns-viewer
namespace kube-system
roleRef
apiGroup rbac.authorization.k8s.io
kind ClusterRole
name external-dns
subjects
kind ServiceAccount
name external-dns
namespace kube-system
---
apiVersion apps/v1
kind Deployment
metadata
name external-dns
namespace kube-system
labels
app external-dns
spec
replicas1
selector
matchLabels
app external-dns
template
metadata
labels
app external-dns
spec
serviceAccountName external-dns
containers
name external-dns
image registry.k8s.io/external-dns/external-dns v0.13.5
args
--source=service
--source=ingress
--provider=aws
--aws-zone-type=private
--registry=txt
--txt-owner-id=external-dns-addon
# will make ExternalDNS see only the hosted zones matching provided domain --domain-filter=<< provide host zone id >>
--policy=upsert-only
env
name AWS_REGION
value us-east-1
resources
limits
cpu 300m
memory 400Mi
requests
cpu 200m
memory 200Mi
imagePullPolicy"Always"
Verify that the deployment was successful:
kubectl get deployments
Example output:
NAME READY UP-TO-DATE AVAILABLE AGE
external-dns 1/1 1 1 15m
Check the logs to verify the records are up-to-date:
kubectl logs external-dns-7f34d6d1b-sx4fx
time="2024-02-15T20:22:02Z" level=info msg="Instantiating new Kubernetes client"
time="2024-02-15T20:22:02Z" level=info msg="Using inCluster-config based on serviceaccount-token"
time="2024-02-15T20:22:02Z" level=info msg="Created Kubernetes client https://10.100.0.1:443"
time="2024-02-15T20:22:09Z" level=info msg="Applying provider record filter for domains: [<yourdomainname>.com. .<yourdomainname>.com.]"
time="2024-02-15T20:22:09Z" level=info msg="All records are already up to date"
Deploying an Ingress
Creating an Ingress Template for AWS Load Balancers involves several key components to ensure effective configuration.
- Rules: Define routing rules specifying how traffic is directed based on paths or hosts.
- Backend services: Specify backend services to handle the traffic, including service names and ports.
- Health checks: Implement health checks to ensure the availability and reliability of backend services.
We'll walk through each component, detailing their significance and providing examples to create a comprehensive Ingress Template for AWS Load Balancers. This step-by-step approach ensures a well-structured and functional configuration tailored to your specific application needs.
apiVersion networking.k8s.io/v1
kind Ingress
metadata
name sample-ingress
annotations
kubernetes.io/ingress.class"alb"
alb.ingress.kubernetes.io/scheme"internet-facing or internal"
alb.ingress.kubernetes.io/certificate-arn"arn:aws:acm:your-region:your-account-id:certificate/your-acm-cert-arn"
spec
rules
host"app.external.dns.test.com"
http
paths
path /*
pathType Prefix
backend
service
name default-service
port
number80
path /products
pathType Prefix
backend
service
name products-service
port
number80
path /accounts
pathType Prefix
backend
service
name accounts-service
port
number80
- metadata: Specifies the name of the Ingress and includes annotations for AWS-specific settings.
- kubernetes.io/ingress.class: "alb": Specifies the Ingress class to be used, indicating that the Ingress should be managed by the AWS ALB Ingress Controller.
- alb.ingress.kubernetes.io/scheme: "internet-facing" or "internal": Determines whether the ALB should be internet-facing or internal.
Options:- "internet-facing": The ALB is accessible from the internet.
- "internal": The ALB is internal and not accessible from the internet
- alb.ingress.kubernetes.io/certificate-arn: "arn:aws:acm:your-region:your-account-id: certificate/your-acm-cert-arn": Specifies the ARN (Amazon Resource Name) of the ACM (AWS Certificate Manager) certificate to be associated with the ALB.
- spec.rules: Defines routing rules based on the host. The /* rule directs traffic to the default service, while /products and /accounts have specific rules for products and accounts services.
- pathType: Specifies the type of matching for the path.
- backend.service.name and backend. service.port: Specifies the backend services for each rule.
ExternalDNS simplifies DNS management in Kubernetes by automating the creation and updating of DNS records based on changes to Ingress resources. For instance, when creating an Ingress with the hostname 'app.external.dns.test.com,' ExternalDNS actively monitors these changes and dynamically recreates corresponding DNS records in Amazon Route 53 (R53). This automation ensures that DNS entries align seamlessly with the evolving environment, eliminating manual interventions.
After successfully deploying the ExternalDNS and Ingress template mentioned above, the corresponding hosted zone and records are automatically created.
Conclusion
ExternalDNS emerges as a pivotal solution for simplifying and automating DNS management within Kubernetes environments. By seamlessly connecting Ingress resources with DNS providers like Amazon Route 53, ExternalDNS eliminates the complexities of manual record management. Its dynamic approach ensures that DNS entries stay synchronized with the evolving Kubernetes landscape, providing a hassle-free experience for users. The tool's versatility and ease of integration make it an invaluable asset for streamlining operations and maintaining a consistent and up-to-date DNS infrastructure. As organizations embrace cloud-native architectures, ExternalDNS stands out as an essential component for achieving efficient and automated DNS management.
Opinions expressed by DZone contributors are their own.
Comments