Blog

Effortless DNS Automation In Kubernetes With ExternalDNS

external-dns

Introduction

Effective DNS management is critical for ensuring services are accessible both within and outside any infrastructure. Managing external DNS records can often require manual intervention, which is not only inefficient but also prone to errors. For services that need to be accessible across cloud platforms or externally from Kubernetes clusters, automating DNS management is essential. This is where ExternalDNS comes in, providing a solution to automatically manage external DNS records.

While CoreDNS handles internal DNS resolution within Kubernetes clusters, it doesn’t extend to external DNS providers. In this blog, we’ll focus on how ExternalDNS automates external DNS management in Kubernetes environments, particularly within AWS. Although we focus on AWS, the concepts and best practices discussed here are applicable across various cloud and DNS providers.

The DNS Management Challenge in Kubernetes

Managing DNS in Kubernetes presents several challenges, especially in large-scale, multi-account, and multi-region environments. In AWS, it’s common to centralize DNS management in a Shared Services account, with separate AWS Route 53 Hosted Zones for each environment (e.g., development, staging, production). While this approach improves control, manually managing DNS records across multiple Hosted Zones can still introduce complexities and increase the risk of misconfigurations.

Key Challenges of Traditional DNS Management:

  • Inconsistency Between Kubernetes Resources and DNS Records: When DNS records are managed separately from Kubernetes resources, inconsistencies can arise. For example, new services or ingress resources might be deployed in Kubernetes, but the corresponding DNS records aren’t updated in AWS Route 53, leading to broken connections or unavailable services.
  • Overhead in Managing Infrastructure as a Code (IaaC): While Infrastructure as a Code (IaaC) tools like Terraform or CloudFormation can help automate parts of DNS management, they introduce operational overhead. Managing and updating DNS records through IaaC often involves lengthy deployment cycles, increased risk of human error, and additional maintenance of configuration files.
  • Manual Intervention and Scaling Issues: In rapidly evolving Kubernetes environments, the frequent addition of new applications and services requires DNS records to be updated in real-time. Manual updates can’t keep up with the speed and complexity of these changes, leading to potential downtime or delays in provisioning, making automated solutions essential for scalability.

To address these challenges, ExternalDNS offers a fully automated solution that dynamically updates DNS records based on the state of Kubernetes resources. By integrating DNS management directly with Kubernetes, ExternalDNS eliminates the need for manual intervention and ensures your DNS records are always in sync with your infrastructure.

ExternalDNS: Automating DNS Records for Kubernetes

ExternalDNS is an open-source controller designed to automate DNS management for Kubernetes resources. It monitors Kubernetes services and ingress resources, dynamically syncing DNS records with external DNS providers, such as AWS Route 53. This eliminates the need for manual updates and ensures that DNS records are always aligned with your infrastructure.

How ExternalDNS Works

external-dns

ExternalDNS is deployed within your Kubernetes cluster, continuously monitoring resources and updating DNS records based on the state of the services and ingress resources. When a new service or ingress is created, modified, or deleted in Kubernetes, ExternalDNS automatically reflects these changes in your DNS provider.

By Default, ExternalDNS keeps track of the records it manages by adding a TXT record to the AWS Route 53 Hosted Zone.

Key Features of ExternalDNS

  • Automated DNS Management: ExternalDNS automatically handles the creation, updating, and deletion of DNS records based on Kubernetes resource changes. This ensures that your DNS records are always accurate and up-to-date, without manual intervention.
  • Multi-Account and Multi-Region Support: ExternalDNS is particularly useful for AWS environments that involve multi-account setups. For example, it can handle DNS management across different AWS accounts by assuming the necessary IAM roles, making it easier to manage DNS for complex, distributed environments.
  • Compatibility with Multiple DNS Providers: While our focus is on AWS Route 53, ExternalDNS also supports other DNS providers, including Google Cloud DNS and AzureDNS. This makes it a flexible solution for organizations running multi-cloud environments.
  • Sync and Upsert Policies for Flexible Control
  • Sync: This policy ensures that DNS records exactly match the Kubernetes resources. When a Kubernetes resource is deleted, ExternalDNS will remove the corresponding DNS record, ensuring there are no unused or stale records.
  • Upsert-Only: This policy focuses on creating and updating DNS records without deleting them. It’s useful for environments where you want to ensure that existing DNS records aren’t accidentally removed.

How to Deploy and Configure ExternalDNS

Deploying ExternalDNS in a Kubernetes cluster is a straightforward process using Helm. Below are the steps to configure ExternalDNS in an AWS environment.

Prerequisites:

  • kubectl: A configured kubectl command-line tool for interacting with your Kubernetes cluster.
  • AWS ALB Controller: To handle ingress resources for HTTP/HTTPS traffic in AWS.
  • AWS EKS Cluster
  • AWS Route 53 Hosted Zone: for managing DNS records.
  • AWS IAM Role: with necessary permissions for Route 53.

Step 1: Create an IAM Role for ExternalDNS

To allow ExternalDNS to interact with Route 53, you need to create an IAM role that grants it permission to assume the role and manage DNS records. Below is the trust policy and the permissions required. Replace the placeholder values with your specific environment details.

IAM Role Trust Policy
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::<ACCOUNT_ID>:oidc-provider/oidc.eks.<REGION>.amazonaws.com/id/<OIDC_ID>"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "oidc.eks.<REGION>.amazonaws.com/id/<OIDC_ID>:aud": "sts.amazonaws.com",
          "oidc.eks.<REGION>.amazonaws.com/id/<OIDC_ID>:sub": "system:serviceaccount:<NAMESPACE>:<SERVICE_ACCOUNT>"
        }
      }
    }
  ]
}
IAM Policy for Route 53 Access
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "route53:ChangeResourceRecordSets"
      ],
      "Resource": [
        "arn:aws:route53:::hostedzone/<HOSTED_ZONE_ID>"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "route53:ListHostedZones",
        "route53:ListResourceRecordSets"
      ],
      "Resource": "*"
    }
  ]
}

<ACCOUNT_ID>: AWS account ID where your EKS cluster is deployed.
<REGION>: AWS region where your EKS cluster is deployed (e.g., us-east-1).
<OIDC_ID>: OpenID Connect (OIDC) provider ID for your EKS cluster. You can find this in the EKS cluster configuration within the AWS console.
<NAMESPACE>: Kubernetes namespace where ExternalDNS is deployed (e.g., external-dns).
<SERVICE_ACCOUNT>: The name of the Kubernetes service account that ExternalDNS will use (e.g., external-dns).

Step 2: Install ExternalDNS Using Helm

After configuring the IAM role, install ExternalDNS in your Kubernetes cluster using Helm. Update the placeholder values to match your environment:

helm repo add external-dns https://kubernetes-sigs.github.io/external-dns/

helm upgrade --install external-dns external-dns/external-dns \
--namespace external-dns \
--create-namespace \
--version 1.15.0 \
--set policy=upsert-only \
--set serviceAccount.name=external-dns \
--set serviceAccount.annotations."eks\\.amazonaws\\.com/role-arn"=arn:aws:iam::<ACCOUNT_ID>:role/<IAM_ROLE_NAME> \
--set txtPrefix="external-dns-" \
--set txtOwnerId="my-cluster"

Use Case Example: Deploying a Service and Ingress with Automatic DNS Creation

With ExternalDNS installed and configured, we’ll walk through a use case to demonstrate how it automatically creates DNS records in AWS Route 53 when a service and ingress are deployed in Kubernetes.

Step 1: Deploy an NGINX Deployment

Create a deployment for NGINX:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

Apply the deployment:

kubectl apply -f nginx-deployment.yaml

Step 2: Create a Kubernetes Service

Expose the NGINX deployment with a service of type ClusterIP:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    app: nginx
  type: ClusterIP

Apply the service:

kubectl apply -f nginx-service.yaml

Step 3: Create an Ingress Resource

Create an ingress resource to expose the service and enable ExternalDNS to create a DNS A record (in our example – directeam.io).

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  annotations:
    alb.ingress.kubernetes.io/target-type: 'ip'
spec:
  ingressClassName: alb
  rules:
  - host: "directeam.io"
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              number: 80

Apply the ingress:

kubectl apply -f nginx-ingress.yaml

Step 4: Verify DNS Record Creation

You can verify that ExternalDNS has created the DNS record by checking the logs or querying AWS Route 53.

Check ExternalDNS Logs:

kubectl -n external-dns logs --selector app.kubernetes.io/name=external-dns

Verify DNS Record in AWS Route 53:

Log into your AWS console and navigate to Route 53. You should see a new A record for directeam.io (in our example) pointing to the load balancer associated with your ingress. You can also see the two TXT records that ExternalDNS creates by default to keep track of the records it manages

ExternalDNS in CI/CD Pipelines

In Kubernetes environments, dynamic scaling and frequent deployments are common, particularly in a CI/CD pipeline where new environments are spun up and torn down regularly. Managing DNS records manually in these fast-moving scenarios can lead to bottlenecks and delays. ExternalDNS solves this problem by automating DNS updates as part of the CI/CD process.

How ExternalDNS Enhances CI/CD Workflows

In a typical CI/CD pipeline, environments are created dynamically to support testing, staging, and production workloads. Each environment requires DNS records to be created and updated as new services and ingress resources are deployed. With ExternalDNS, these records are automatically managed, reducing manual effort and ensuring that DNS entries are consistently aligned with the current state of your infrastructure.

Example Use Case

Imagine a scenario where your team deploys a new application to a Kubernetes cluster as part of a CI/CD pipeline. Once the application is deployed, it requires a DNS record to be accessible externally. With ExternalDNS integrated into your pipeline:

  • Service Deployment: You deploy a new service and ingress resource to your Kubernetes cluster.
  • DNS Automation: ExternalDNS automatically creates the corresponding DNS records in AWS Route 53, making the service publicly accessible without requiring any manual updates.
  • Temporary Environments: For temporary environments, such as those created for testing, ExternalDNS will handle DNS entries during the environment’s lifecycle, deleting them when the resources are removed.

This fully automated DNS management ensures that DNS records are always in sync with the resources in your cluster, allowing CI/CD pipelines to run without unnecessary delays or manual intervention.

Benefits of Using ExternalDNS in CI/CD

  • Faster Deployments: Automating DNS management reduces the time spent on manual configurations and updates, speeding up the deployment process.
  • Improved Consistency: DNS records are always up-to-date with the current state of Kubernetes resources, reducing the risk of misconfiguration.
  • Scalability: ExternalDNS scales effortlessly as your infrastructure grows, handling dynamic environments and multiple clusters without additional manual effort.

Best Practices for Using ExternalDNS in AWS

To maximize the benefits of ExternalDNS and ensure smooth DNS management in your Kubernetes environments, it’s essential to follow best practices that enhance security, scalability, and operational efficiency.

Below are some recommended strategies for optimizing your ExternalDNS setup in AWS:

  • Use a Separate Hosted Zone per Environment: In multi-environment architectures, it’s a good practice to create separate Route 53 Hosted Zones for each environment (e.g., development, staging, and production). This separation prevents potential conflicts between DNS records and allows for more granular control over DNS management.

Example: Create separate Hosted Zones for each environment:

  • dev.example.com
  • stage.example.com
  • prod.example.com

This setup helps isolate DNS changes and reduces the risk of cross-environment issues.

  • Set Unique txtOwnerId Values for Each Cluster: When running multiple Kubernetes clusters that share the same Route 53 Hosted Zone, it’s important to assign a unique txtOwnerId to each cluster. This identifier ensures that ExternalDNS manages DNS records without overwriting entries created by another cluster, preventing conflicts.

Example: In your Helm chart or deployment configuration, set a unique value for each cluster:

--set txtOwnerId="dev-cluster"

This ensures that ExternalDNS knows which DNS records it owns and manages, reducing the likelihood of conflicts between different environments or clusters.

  • Implement Least Privilege Access with IAM Roles: Security should be a top priority when granting ExternalDNS access to AWS Route 53. Apply the principle of least privilege by creating specific IAM roles that allow ExternalDNS to modify only the necessary Hosted Zones. This limits the controller’s access and minimizes potential security risks.
  • Use sync and upsert-only Policies Appropriately: ExternalDNS offers two key policies for managing DNS records: upsert-only and sync. Understanding when to use each is critical for maintaining control over your DNS records without risking accidental deletion or inconsistency.

Sync Policy:

The sync policy ensures that DNS records exactly match your Kubernetes resources. It actively deletes any records it manages that no longer have corresponding Kubernetes resources, making it a powerful option for environments where strict control is required.

When to use sync: In environments where you want full automation and ensure no stale DNS records remain, the sync policy is ideal. It keeps the DNS in perfect alignment with Kubernetes, automatically cleaning up unused records when services or ingress resources are deleted. This is especially beneficial in large-scale or dynamic environments where clusters are frequently updated, ensuring that no stale DNS entries remain that could cause conflicts or confusion.

Upsert-Only Policy:

The upsert-only policy ensures that ExternalDNS only creates or updates DNS records but never deletes them. This makes it a safer option in scenarios where you want to introduce ExternalDNS gradually without impacting existing records.

When to use upsert-only: When migrating existing services to a new Kubernetes environment, there are often pre-existing DNS records in your DNS provider (e.g., AWS Route 53). The upsert-only policy is ideal in this case because it prevents ExternalDNS from inadvertently deleting records that are still in use or were manually created outside of Kubernetes. This way, you can ensure new records are created without disrupting services that rely on existing DNS entries.

  • Use DynamoDB To Track Ownership Instead Of TXT Records: Instead of using TXT records to track DNS ownership, you can configure ExternalDNS to use DynamoDB.

Why Use DynamoDB?

Clean DNS Records: This avoids adding additional TXT records to your DNS provider, making your DNS records easier to read and manage.

To configure ExternalDNS with DynamoDB, follow these steps:

Create a DynamoDB Table: By default, the DynamoDB registry stores data in the table named external-dns and it needs to exist before configuring ExternalDNS to use the DynamoDB registry. If the DynamoDB table has a different name, it may be specified using the --dynamodb-table flag in the extraArgs. If the DynamoDB table is in a different region, it may be specified using the --dynamodb-region flag in the extraArgs.
Please notice, --dynamodb-region is mandatory even when using the default table name (external-dns).
Make sure to review the official documentation for using DynamoDB as the registry.

How to configure ExternalDNS to use DynamoDB: When installing ExternalDNS using Helm, configure it to use DynamoDB by specifying the table name (optional if using the default name) and region in the Helm values.

helm repo add external-dns https://kubernetes-sigs.github.io/external-dns/

helm upgrade --install external-dns external-dns/external-dns \
--namespace external-dns \
--create-namespace \
--version 1.15.0 \
--set policy=upsert-only \
--set serviceAccount.name=external-dns \
--set serviceAccount.annotations."eks\\.amazonaws\\.com/role-arn"=arn:aws:iam::<ACCOUNT_ID>:role/<IAM_ROLE_NAME> \
--set registry=dynamodb \
--set 'extraArgs={'--dynamodb-region=us-east-1','--dynamodb-table=external-dns}' \
--set txtOwnerId="my-cluster"

<ACCOUNT_ID>: AWS account ID where your EKS cluster is deployed.
<IAM_ROLE_NAME>: The name of the IAM role you created for ExternalDNS (e.g., external-dns-controller).

Looking at Route 53 & DynamoDB table, we will see the following:

Frequently Asked Questions

  1. Will ExternalDNS overwrite my existing DNS records? No, ExternalDNS does not take control of pre-existing DNS records unless you specifically configure it. If you have manually created records in your DNS provider (e.g., AWS Route 53) with the same hostname as a Kubernetes resource, ExternalDNS will not attempt to modify or overwrite those records.
  2. What happens if I manually delete a DNS record created by ExternalDNS? If you manually delete a DNS record in AWS Route 53 that was created by ExternalDNS, the controller will re-create the record during its next reconciliation loop (by default, the interval is 1 minute). ExternalDNS ensures that DNS records for the services and ingress resources in Kubernetes always exist as long as those resources remain in the cluster.
  3. How do I prevent a specific DNS record from being deleted by ExternalDNS? If you’re using the sync policy, which automatically deletes records when corresponding Kubernetes resources are removed, you can prevent a DNS record from being deleted by manually deleting its associated TXT record (or DynamoDB registry as previously mentioned). ExternalDNS uses these TXT records to track ownership of DNS entries, and deleting the TXT record will signal that ExternalDNS should no longer manage that specific entry.
  4. How can I make ExternalDNS take control of pre-existing DNS records? To make ExternalDNS manage an existing DNS record, you need to create the corresponding TXT record (or DynamoDB registry as previously mentioned) that marks it as owned by ExternalDNS. This can be useful when migrating from a manually managed DNS setup to ExternalDNS.
  5. What happens if I delete a Kubernetes resource (like an ingress)? If you’re using the sync policy, ExternalDNS will automatically delete the DNS record associated with the deleted Kubernetes resource. This ensures that DNS records do not remain after the resource is removed from the cluster, preventing stale or orphaned DNS entries. In contrast, the upsert-only policy will leave the DNS record intact, so manual intervention would be required to clean up unused records.

Conclusion

By following these best practices, you can leverage ExternalDNS to automate DNS management in Kubernetes environments. ExternalDNS automates the creation and management of DNS records, ensuring consistency across multiple accounts, regions, and complex CI/CD pipelines.

Although we focused on AWS environments in this post (EKS & Route 53), the best practices and strategies apply to other cloud providers and DNS services. As cloud environments grow more complex, it’s critical to adopt tools like ExternalDNS to stay ahead of manual bottlenecks and reduce operational overhead.

If you need assistance deploying ExternalDNS or optimizing your cloud infrastructure, our team of experts is here to help.

Contact Us to learn more about how we can streamline your DNS management and accelerate your cloud automation.

Official ExternalDNS documentation