In this tutorial, we will follow a step-by-step approach to configure ExternalDNS service on a Kubernetes cluster.
Kubernetes contains an internal DNS module that automatically discovers and assigns DNS names to individual containers when instructed. In practice, this works very well. However, we frequently need to expose some or all parts of the Kubernetes cluster to the public. For instance, if a cluster exists inside a public cloud provider such as AWS or Google Cloud Platform, we would like to have a container service that interacts with this cloud provider and changes any A Records to point to the nodes that expose those services.
This is what the ExternalDNS project does. ExternalDNS is a Kubernetes project with the main purpose of automatically creating DNS records for Ingress or Service resources.
In this tutorial, we will be using a Platform9 Managed Kubernetes Free Tier cluster backed by a DigitalOcean Droplet. However, you can use this tutorial to configure external DNS on any other Kubernetes cluster of your choice.
Now you are ready to deploy the ExternalDNS service on your Kubernetes cluster.
To test the ExternalDNS, we need to assign a domain name. As Digital Ocean does not act as a DNS registrar, you need to assign the nameservers of the domain registrar to point to the following entries:
After that, go to the Networking tab of your DigitalOcean Dashboard and add the domain name there:
Do not assign any droplet there, as we will let the ExternalDNS handle that.
Next, we need to create a Personal Access Token for the DigitalOcean API. Navigate to the API->Tokens and Keys and create a new API key. Note that token value, as it will be exposed only temporarily in the UI.
Setting up the ExternalDNS is the easy part. We just need to define the manifest that consists of the following services:
xxxxxxxxxx
apiVersion v1
kind ServiceAccount
metadata
name external-dns</code>
xxxxxxxxxx
apiVersion rbac.authorization.k8s.io/v1beta1
kind ClusterRole
metadata
name external-dns
rules
apiGroups""
resources"services""endpoints""pods"
verbs"get""watch""list"
apiGroups"extensions"
resources"ingresses"
verbs"get""watch""list"
apiGroups""
resources"nodes"
verbs"list"
xxxxxxxxxx
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
xxxxxxxxxx
apiVersion apps/v1
kind Deployment
metadata
name external-dns
spec
replicas1
selector
matchLabels
app external-dns
strategy
type Recreate
selector
matchLabels
app external-dns
template
metadata
labels
app external-dns
spec
serviceAccountName external-dns
containers
name external-dns
image registry.opensource.zalan.do/teapot/external-dns latest
args
--source=service
--domain-filter=expressiveartsfair.com
--provider=digitalocean
env
name DO_TOKEN
value"YOUR_DIGITALOCEAN_API_KEY"
You can either put all of these manifests in the same file or in separate files. Then apply the configuration:
xxxxxxxxxx
$ kubectl apply -f external-dns.yml
serviceaccount/external-dns created
clusterrole.rbac.authorization.k8s.io/external-dns created
clusterrolebinding.rbac.authorization.k8s.io/external-dns-viewer created
deployment.apps/external-dns created
Monitor the deployment status via the Platform9 UI or on the terminal.
When everything is healthy, we can deploy our first service to test the external DNS configuration.
Create a new file named nginx.demo.service.yml
with the following contents:
xxxxxxxxxx
apiVersion apps/v1
kind Deployment
metadata
name nginx
spec
replicas1
selector
matchLabels
app nginx
template
metadata
labels
app nginx
spec
containers
image nginx
name nginx
ports
containerPort80
---
apiVersion v1
kind Service
metadata
name nginx
annotations
external-dns.alpha.kubernetes.io/hostname demo.expressiveartsfair.com
spec
selector
app nginx
type NodePort
ports
protocol TCP
port80
nodePort30080
The important parts are:
Now anytime we assign the external DNS annotation in a service, the daemon will monitor that event and use the Digital Ocean API to update the DNS Records. In the following image you can see that the DNS entry was added to point to the Droplet that we exposed to the NodePort service:
Now, you may notice one small thing. Currently we cannot use an external Load Balancer service, as the Platform9 Kubernetes distro is running inside a droplet. Thus, we cannot directly navigate to demo.expressiveartsfair.com as the NodePort is open in a different port (port 30080 as we specified in the configuration).
Nonetheless, if we navigate to demo.expressiveartsfair.com:30080, we can see the nginx welcome page as usual:
In order to make this work we have a few options:
In either case, we have the ExternalDNS service handling and updating all the corresponding DNS records without user intervention.
Follow the reverse step and destroy all created resources:
xxxxxxxxxx
$ kubectl delete -f Nginx-service.yml
$ kubectl delete -f external-dns.yml
Then invalidate the DigitalOcean Token you created earlier.