Introduction to External DNS in Kubernetes

External DNS
Reading Time: 4 minutes

Are you running your workloads in GKE / EKS / AKS? Do you use the ingress and load balancer service type for public-facing domains? Are your sub-domains increasing and changing regularly? If yes, then external DNS is for you.

Problem

Let us suppose you have a web application running in your Kubernetes Cluster. You might have a public-facing load balancer so that your application is accessible to the entire world.

Imagine you have a domain name called example.com and you want to map that to your public-facing load balancer provisioned by Kubernetes. For this, you can either use a gcloud command or maybe do it manually.

Now, what if you have hundreds of projects and thousands of DNS records to be created? What if the LoadBalancer Endpoint changes? How do you keep a track of hundreds of thousands of DNS records?

Solution

Here come external-dns to the picture. ExternalDNS allows you to control DNS records dynamically via Kubernetes resources in a DNS provider-agnostic way. ExternalDNS synchronizes exposed Kubernetes Services and Ingresses with DNS providers.

DNS Provider support

ExternalDNS allows you to keep selected zones (via --domain-filter) synchronized with Ingresses and Services of type=LoadBalancer and nodes in various cloud providers:

  • Google Cloud DNS
  • AWS Route53
  • Azure DNS
  • BlueCat
  • Cloudflare
  • RcodeZero
  • DigitalOcean
  • DNSimple, etc

What is the entire story all about? (TLDR)

  • Create a GKE cluster.
  • Deploy ExternalDNS to our GKE Cluster.
  • Deploy a sample Web-Application.
  • Automate the creation of DNS records in Google Cloud DNS using External DNS.

Prerequisites

  • GCP account with running GKE cluster
  • A Domain hosted in Google Cloud DNS

Host domain in Cloud DNS

Follow the below steps to configure Cloud DNS:

  1. Open GCP console
  2. Now, search for cloud DNS and open it.
  3. If you have already hosted a zone in the GCP that you can use then not required to follow this.
  4. Create a DNS zone.
  5. After that put your Name Server information to your domain provider Nameserver settings.

Deploy External DNS to the Kubernetes Cluster

Below is the manifest file to deploy the external-dns to the GKE cluster:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: external-dns
rules:
- apiGroups: [""]
  resources: ["services","endpoints","pods"]
  verbs: ["get","watch","list"]
- apiGroups: ["extensions","networking.k8s.io"]
  resources: ["ingresses"] 
  verbs: ["get","watch","list"]
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: external-dns-viewer
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: external-dns
subjects:
- kind: ServiceAccount
  name: external-dns
  namespace: default
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-dns
spec:
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: external-dns
  template:
    metadata:
      labels:
        app: external-dns
    spec:
      serviceAccountName: external-dns
      containers:
      - name: external-dns
        image: k8s.gcr.io/external-dns/external-dns:v0.7.3
        args:
        - --source=service
        - --source=ingress
        - --domain-filter=my.himanshuchaudhary.tech
        - --provider=google
        - --policy=upsert-only 
        - --registry=txt
        - --txt-owner-id=gcloud-external-dns

Firstly, check the --domain-filter arg which is filtering the domain that you want to use with external-dns. Secondly, check the --policy arg which is set to upsert-only which means it can only create a dns entry but is not able to delete it automatically.

If you want to delete it as well, then change it to sync.

To deploy external-dns run the below command:

$ kubectl apply -f external-dns.yml
$ kubectl get pods
$ kubectl logs external-dns-6554c7ddf4-z5cfr

Deploy sample Application

After setting up the external dns now deploy a sample application with load balancer service and check the dns entry in the cloud dns which is done automatically with the help of external dns.

sample-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mywebapp
  labels:
    service: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      service: nginx
  template:
    metadata:
      name: mywebapp-pod
      labels:
        service: nginx
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: service
                  operator: In
                  values:
                  - nginx
              topologyKey: "kubernetes.io/hostname"
            weight: 100
      containers:
      - name: mywebapp
        image: docker.io/himanshuchaudhary/mywebapp:v1
        ports:
        - containerPort: 80

Above is the sample deployment, and the service type of load balancer is used for internet facing the application.

service.yml
apiVersion: v1
kind: Service
metadata:
  name: mywebapp
  labels:
    service: nginx
  annotations:
    external-dns.alpha.kubernetes.io/hostname: test.my.himanshuchaudhary.tech
spec:
  selector:
    service: nginx
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 80

In service.yml I had used an annotation of external-dns, which tells the controller, which sub-domain entry it needs to add in cloud dns.

Verifying the Implementation

In the above image, you can see DNS entry is created automatically by external-dns and routing traffic to the load balancer IP. We can more verify by checking the logs of the controller.

Conclusion

In the blog, we learned how can we automate the DNS entry with the help of external-dns. If you have any doubts you can comment below or can reach out to me at himanshu.chaudhary@knoldus.com.

Written by 

Himanshu is a Software Consultant[[Devops]] at Knoldus Software LLP. He loves to explore and learn new tools and technologies.