After setting up a LoadBalancer and Ingress in my previous post I'm able to deploy a website successfully. But I have to enter the IP of the LoadBalancer to access the site. Not unlike you would do with a classical setup, there is DNS. Yes we can write DNS entries for all sites we want to host on the cluster. There are even pretty practical (web) user interfaces to do that.
But I want to get even further and rather not write DNS entries myself, but let Kubernetes configure it based on what Ingress resources I deploy.
Thanks to the folks at https://github.com/kubernetes-sigs/external-dns there are several integrations/providers available to let Kubernetes automatically configure DNS entries, based on Services/Ingress resources/annotations.
My initial thought was to do everything on my own, using the CoreDNS provider and configuring an ETCD and CoreDNS server to implement a DNS service. Still I would need a secondary DNS service to act as secondary DNS, since this is recommended when having a DNS service. I used https://www.buddyns.com/ so far and was very happy with the service!
But the status “alpha” of that provider has a reason. It is pretty unstable, but served DNS entries for Ingress resources I deployed…. sometimes. Having to use a ClusterIP in the config, since Kubernetes DNS resolution doesn't work on a CoreDNS container for a good reason, it isn't robust to redeploys of the ETCD service too. I might revisit that solution in the future, but for now it is too unstable to rely on.
One interesting solution is the Cloudflare DNS provider. Cloudflare provides an authoritative DNS service free of charge for personal blogs or websites like mine. And that provider is in “beta” state and first tests, showed it was much more reliable than the CoreDNS provider.
Create Cloudflare account and add first domain
First you need to create a Cloudflare account and add your first domain to the DNS editor: https://support.cloudflare.com/hc/en-us/articles/201720164-Step-2-Create-a-Cloudflare-account-and-add-a-website
Cloudflare will try to automatically retrieve your existing DNS configuration. You can safely ignore that, since we will create new entries with Kubernetes anyway. If any entries are “imported” or “proxied” you should remove all names, which you want to configure with Kubernetes.
Configure Cloudflare dns for your domain
You'll have to configure the Cloudflare DNS servers (shown in your dash on cloudflare.com under DNS) on your domains registrar in order to setup completely. Cloudflare will try to help you with that.
You can skip this step until you're sure you are setup.
Create Cloudflare API token
The service does need an access token to edit the DNS entries on your behalf. Please create a new API token on https://dash.cloudflare.com/profile/api-tokens. But only give it following permissions:
write down that token, since it will only be displayed once! We will need that very soon!
Deploy the External DNS controller
We can finally deploy the External DNS controller. I will enable automatic configuration of Ingress and Services with the right annotations. This differs from the official documentation sample.
Create a namespace for the DNS controller
kubectl create ns external-dns
Deploy the controller with RBAC enabled. You will need the API token for that (right at the bottom).
cat <<EOF | kubectl apply -f- apiVersion: v1 kind: ServiceAccount metadata: name: external-dns namespace: external-dns --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: name: external-dns namespace: external-dns rules: - apiGroups: [""] resources: ["services"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["nodes"] verbs: ["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: external-dns --- apiVersion: apps/v1 kind: Deployment metadata: name: external-dns namespace: 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: eu.gcr.io/k8s-artifacts-prod/external-dns/external-dns:v0.5.18 args: - --source=ingress - --source=service - --provider=cloudflare env: - name: CF_API_TOKEN value: "<your-cloudflare-api-token-goes-here>" EOF
Now whenever you deploy a Ingress resource with a host key or a Service with the
external-dns.alpha.kubernetes.io/hostname=nginx.example.org annotation (replace
nginx.example.org with a real value)
it will create a DNS entry for it.
You may ask yourself what's next? I want to enable the cluster to automatically issue Let's Encrypt certificates for each domain I deploy, so stay tuned!