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.
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?
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
- 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.
- 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:
- Open GCP console
- Now, search for cloud DNS and open it.
- If you have already hosted a zone in the GCP that you can use then not required to follow this.
- Create a DNS zone.
- 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.
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 email@example.com.