Nachdem ich in meinem vorherigen Beitrag einen LoadBalancer und Ingress eingerichtet habe, kann ich eine Website erfolgreich deployen. Allerdings muss ich die IP des LoadBalancers eingeben, um die Site zu erreichen. Wie bei einem klassischen Setup gibt es dafür DNS. Ja, wir können DNS-Einträge für alle Sites schreiben, die wir auf dem Cluster hosten wollen. Es gibt sogar recht praktische (Web-)Oberflächen dafür.
Aber ich will noch weiter gehen und DNS-Einträge lieber nicht selbst schreiben, sondern Kubernetes sie auf Basis der deployten Ingress-Ressourcen konfigurieren lassen.
Dank der Leute von https://github.com/kubernetes-sigs/external-dns gibt es mehrere Integrationen/Provider, mit denen Kubernetes DNS-Einträge automatisch auf Basis von Services/Ingress-Ressourcen/Annotations konfiguriert.
Mein erster Gedanke war, alles selbst zu machen: den CoreDNS-Provider nutzen und einen ETCD- und CoreDNS-Server konfigurieren, um einen DNS-Dienst umzusetzen. Trotzdem bräuchte ich einen sekundären DNS-Dienst, denn ein Secondary DNS wird bei einem eigenen DNS-Dienst empfohlen. Bisher habe ich https://www.buddyns.com/ genutzt und war mit dem Dienst sehr zufrieden!
Aber der Status “alpha” dieses Providers hat einen Grund. Er ist ziemlich instabil, lieferte DNS-Einträge für deployte Ingress-Ressourcen aber … manchmal. Da man in der Config eine ClusterIP nutzen muss – weil Kubernetes-DNS-Auflösung auf einem CoreDNS-Container aus gutem Grund nicht funktioniert – ist er auch gegen Redeploys des ETCD-Dienstes nicht robust. Vielleicht schaue ich mir die Lösung künftig noch einmal an, aber im Moment ist sie zu instabil, um sich darauf zu verlassen.
Eine interessante Lösung ist der Cloudflare DNS-Provider. Cloudflare bietet einen autoritativen DNS-Dienst kostenlos für private Blogs oder Websites wie meine an. Dieser Provider ist im “beta”-Status, und erste Tests zeigten, dass er deutlich zuverlässiger war als der CoreDNS-Provider.
Cloudflare-Konto erstellen und erste Domain hinzufügen #
Zuerst erstellst du ein Cloudflare-Konto und fügst deine erste Domain im DNS-Editor hinzu: https://support.cloudflare.com/hc/en-us/articles/201720164-Step-2-Create-a-Cloudflare-account-and-add-a-website
Cloudflare versucht, deine bestehende DNS-Konfiguration automatisch abzurufen. Das kannst du getrost ignorieren, da wir die Einträge ohnehin neu mit Kubernetes anlegen. Falls Einträge “importiert” oder “proxied” werden, solltest du alle Namen entfernen, die du mit Kubernetes konfigurieren willst.
Cloudflare-DNS für deine Domain konfigurieren #
Um das Setup vollständig abzuschliessen, musst du die Cloudflare-DNS-Server (in deinem Dashboard auf cloudflare.com unter DNS zu sehen) beim Registrar deiner Domain eintragen. Cloudflare hilft dir dabei.
Diesen Schritt kannst du überspringen, bis du sicher bist, dass alles eingerichtet ist.
Cloudflare-API-Token erstellen #
Der Dienst braucht ein Access-Token, um die DNS-Einträge in deinem Namen zu bearbeiten. Erstelle ein neues API-Token auf https://dash.cloudflare.com/profile/api-tokens. Vergib aber nur folgende Berechtigungen:
| Permissions | ||
|---|---|---|
| Zone | Zone | Read |
| Zone | DNS | Edit |
Notiere dir das Token, denn es wird nur einmal angezeigt! Wir brauchen es gleich!
External-DNS-Controller deployen #
Endlich können wir den External-DNS-Controller deployen. Ich aktiviere die automatische Konfiguration von Ingress und Services mit den passenden Annotations. Das weicht vom offiziellen Beispiel der Dokumentation ab.
Namespace für den DNS-Controller anlegen:
kubectl create ns external-dnsDeploye den Controller mit aktiviertem RBAC. Dafür brauchst du das API-Token (ganz unten).
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>"
EOFSobald du nun eine Ingress-Ressource mit einem host-Key oder einen Service mit der Annotation external-dns.alpha.kubernetes.io/hostname=nginx.example.org deployst (ersetze nginx.example.org durch einen echten Wert), wird dafür ein DNS-Eintrag erstellt.
Wie geht’s weiter? #
Du fragst dich vielleicht, wie es weitergeht? Ich will den Cluster so einrichten, dass er für jede deployte Domain automatisch Let’s-Encrypt-Zertifikate ausstellt – bleib also dran!