How To Automatically Manage DNS Records From DigitalOcean Kubernetes Using ExternalDNS
How To Automatically Manage DNS Records From DigitalOcean Kubernetes Using ExternalDNS
We hope you find this tutorial helpful. In addition to guides like this one, we provide simple cloud infrastructure for developers. Learn more →

How To Automatically Manage DNS Records From DigitalOcean Kubernetes Using ExternalDNS

PostedJune 5, 2019 3.5k views Kubernetes Nginx DNS

The author selected the Free and Open Source Fund to receive a donation as part of the Write for DOnations program.

Introduction

When deploying web apps to Kubernetes, you usually use Services and Ingresses to expose apps beyond the cluster at your desired domain. This involves manually configuring not only the Ingress, but also the DNS records at your provider, which can be a time-consuming and error-prone process. This can become an obstacle as your application grows in complexity; when the external IP changes, it is necessary to update the DNS records accordingly.

To overcome this, the Kubernetes sig-network team created ExternalDNS for the purpose of automatically managing external DNS records from within a Kubernetes cluster. Once deployed, ExternalDNS works in the background and requires almost no additional configuration. Whenever a Service or Ingress is created or changed, ExternalDNS will update the records right away.

In this tutorial, you will install ExternalDNS to your DigitalOcean Kubernetes cluster via Helm and configure it to use DigitalOcean as your DNS provider. Then, you will deploy a sample web app with an Ingress and use ExternalDNS to point it to your domain name. In the end, you will have an automated DNS record managing system in place for both Services and Ingresses.

Prerequisites

  • A DigitalOcean Kubernetes cluster with your connection configured as the kubectl default. Instructions on how to configure kubectl are shown under the Connect to your Cluster step when you create your cluster. To create a Kubernetes cluster on DigitalOcean, see Kubernetes Quickstart.

  • The Helm package manager installed on your local machine, and Tiller installed on your cluster. To do this, complete Steps 1 and 2 of the How To Install Software on Kubernetes Clusters with the Helm Package Manager tutorial.

  • The Nginx Ingress Controller installed on your cluster using Helm in order to use ExternalDNS with Ingress Resources. To do this, follow How to Set Up an Nginx Ingress on DigitalOcean Kubernetes Using Helm. You'll need to set the publishService property to true as per the instructions in Step 2.

  • A DigitalOcean API key (Personal Access Token) with read and write permissions. To create one, visit How to Create a Personal Access Token.

  • A fully registered domain name. This tutorial will use echo.example.com throughout. You can purchase a domain name on Namecheap, get one for free on Freenom, or use the domain registrar of your choice.

Step 1 — Installing ExternalDNS Using Helm

In this section, you will install ExternalDNS to your cluster using Helm and configure it to work with the DigitalOcean DNS service.

In order to override some of the default settings of the ExternalDNS Helm chart, you'll need to create a values.yaml file that you'll pass in to Helm during installation. On the machine you use to access your cluster in the prerequisites, create the file by running:

  • nano externaldns-values.yaml

Add the following lines:

externaldns-values.yaml
rbac:
  create: true

provider: digitalocean

digitalocean:
  apiToken: your_api_token

interval: "1m"

policy: sync # or upsert-only

# domainFilters: [ 'example.com' ]

In the first block, you enable RBAC (Role Based Access Control) manifest creation, which must be enabled on RBAC-enabled Kubernetes clusters like DigitalOcean. In the next line, you set the DNS service provider to DigitalOcean. Then, in the next block, you'll add your DigitalOcean API token by replacing your_api_token.

The next line sets the interval at which ExternalDNS will poll for changes to Ingresses and Services. You can set it to a lower value to propogate changes to your DNS faster.

The policy setting determines whether ExternalDNS will only insert DNS records (upsert-only) or create and delete them as needed (sync). Fortunately, since version 0.3, ExternalDNS supports the concept of ownership by creating accompanying TXT records in which it stores information about the domains it creates, limiting its scope of action to only those it created.

The domainFilters parameter is used for limiting the domains that ExternalDNS can manage. You can uncomment it and enter your domains in the form of a string array, but this isn't necessary.

When you've finished editing, save and close the file.

Now, install ExternalDNS to your cluster by running the following command:

  • helm install stable/external-dns --name external-dns -f externaldns-values.yaml

The output will look similar to the following:

Output
NAME: external-dns LAST DEPLOYED: ... NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/Pod(related) NAME READY STATUS RESTARTS AGE external-dns-69c545655f-xqjjf 0/1 ContainerCreating 0 0s ==> v1/Secret NAME TYPE DATA AGE external-dns Opaque 1 0s ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE external-dns ClusterIP 10.245.47.69 <none> 7979/TCP 0s ==> v1/ServiceAccount NAME SECRETS AGE external-dns 1 0s ==> v1beta1/ClusterRole NAME AGE external-dns 0s ==> v1beta1/ClusterRoleBinding NAME AGE external-dns 0s ==> v1beta1/Deployment NAME READY UP-TO-DATE AVAILABLE AGE external-dns 0/1 1 0 0s NOTES: ...

You can verify the ExternalDNS creation by running the following command:

  • kubectl --namespace=default get pods -l "app=external-dns,release=external-dns" -w
Output
NAME READY STATUS RESTARTS AGE external-dns-69bfcf8ccb-7j4hp 0/1 ContainerCreating 0 3s

You've installed ExternalDNS to your Kubernetes cluster. Next, you will deploy an example web app, expose it using an Nginx Ingress, and let ExternalDNS automatically point your domain name to the appropriate Load Balancer.

Step 2 — Deploying and Exposing an Example Web App

In this section, you will deploy a dummy web app to your cluster in order to expose it using your Ingress. Then you'll set up ExternalDNS to automatically configure DNS records for you. In the end, you will have DNS records for your domain pointed to the Load Balancer of the Ingress.

The dummy web app you'll deploy is http-echo by Hashicorp. It is an in-memory web server that echoes back the message you give it. You'll store its Kubernetes manifests in a file named echo.yaml. Create it and open it for editing:

  • nano echo.yaml

Add the following lines to your file:

echo.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: echo-ingress
spec:
  rules:
  - host: echo.example.com
    http:
      paths:
      - backend:
          serviceName: echo
          servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: echo
spec:
  ports:
  - port: 80
    targetPort: 5678
  selector:
    app: echo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo
spec:
  selector:
    matchLabels:
      app: echo
  replicas: 3
  template:
    metadata:
      labels:
        app: echo
    spec:
      containers:
      - name: echo
        image: hashicorp/http-echo
        args:
        - "-text=Echo!"
        ports:
        - containerPort: 5678

In this configuration, you define a Deployment, an Ingress, and a Service. The Deployment consists of three replicas of the http-echo app, with a custom message (Echo!) passed in. The Service is defined to allow access to the Pods in the Deployment via port 80. The Ingress is configured to expose the Service at your domain.

Replace echo.example.com with your domain, then save and close the file.

Now there is no need for you to configure the DNS records for the domain manually. ExternalDNS will do so automatically, as soon as you apply the configuration to Kubernetes.

To apply the configuration, run the following command:

  • kubectl create -f echo.yaml

You'll see the following output:

Output
ingress.extensions/echo-ingress created service/echo created deployment.apps/echo created

You'll need to wait a short amount of time for ExternalDNS to notice the changes and create the appropriate DNS records. The interval setting in the Helm chart governs the length of time you'll need to wait for your DNS record creation. In values.yaml, the interval length is set to 1 minute by default.

You can visit your DigitalOcean Control Panel to see an A and TXT record.

Control Panel - Generated DNS Records

Once the specified time interval has passed, access your domain using curl:

  • curl echo.example.com

You'll see the following output:

Output
Echo!

This message confirms you've configured ExternalDNS and created the necessary DNS records to point to the Load Balancer of the Nginx Ingress Controller. If you see an error message, give it some time. Or, you can try accessing your domain from your browser where you'll see Echo!.

You've tested ExternalDNS by deploying an example app with an Ingress. You can also observe the new DNS records in your DigitalOcean Control Panel. In the next step, you'll expose the Service at your domain name.

Step 3 — (Optional) Exposing the App Using a Service

In this optional section, you'll use Services with ExternalDNS instead of Ingresses. ExternalDNS allows you to make different Kubernetes resources available to DNS servers. Using Services is a similar process to Ingresses with the configuration modified for this alternate resource.

Note: Following this step will delete the DNS records you've just created.

Since you'll be customizing the Service contained in echo.yaml, you won't need the echo-ingress anymore. Delete it using the following command:

  • kubectl delete ing echo-ingress

The output will be:

Output
ingress.extensions/echo-ingress deleted

ExternalDNS will delete the existing DNS records it created in the previous step. In the remainder of the step, you can use the same domain you have used before.

Next, open the echo.yaml file for editing:

  • nano echo.yaml

Replace the file contents with the following lines:

echo.yaml
apiVersion: v1
kind: Service
metadata:
  name: echo
  annotations:
    external-dns.alpha.kubernetes.io/hostname: echo.example.com
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 5678
  selector:
    app: echo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo
spec:
  selector:
    matchLabels:
      app: echo
  replicas: 3
  template:
    metadata:
      labels:
        app: echo
    spec:
      containers:
      - name: echo
        image: hashicorp/http-echo
        args:
        - "-text=Echo!"
        ports:
        - containerPort: 5678

You've removed Ingress from the file for the previous set up and changed the Service type to LoadBalancer. Furthermore, you've added an annotation specifying the domain name for ExternalDNS.

Apply the changes to your cluster by running the following command:

  • kubectl apply -f echo.yaml

The output will be:

Output
service/echo configured deployment.apps/echo configured

You can watch the Service's Load Balancer become available by running:

  • kubectl get svc echo -w

You will see output similar to the following:

Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE echo LoadBalancer 10.245.81.235 <pending> 80:31814/TCP 8s ...

As in the previous step, you'll need to wait some time for the DNS records to be created and propagated. Once that is done, curl the domain you specified:

  • curl echo.example.com

The output will be the same as the previous step:

Output
Echo!

If you get an error, wait a little longer, or you can try a different domain. Since DNS records are cached on client systems, it may take a long time for the changes to actually propagate.

In this step, you created a Service (of type LoadBalancer) and pointed it to your domain name using ExternalDNS.

Conclusion

ExternalDNS works silently in the background and provides a friction-free experience. Your Kubernetes cluster has just become the central source of truth regarding the domains. You won't have to manually update DNS records anymore.

The real power of ExternalDNS will become apparent when creating testing environments from a Continuous Delivery system. If you want to set up one such system on your Kubernetes cluster, visit How To Set Up a CD Pipeline with Spinnaker on DigitalOcean Kubernetes.

0 Comments

Creative Commons License