De DNS records die aangemaakt dienen te worden in mijn DNS server (Pi-Hole) wil ik automatisch laten doen zodra er een Ingress aangemaakt wordt voor de FQDN van de service. Hiervoor is External DNS die ook A-records kan aanmaken in de Local DNS van Pi-Hole.

Het installeren van External DNS is een kwestie van de kubectl commando’s ingeven, of zorg ervoor dat het automatisch geïnstalleerd met behulp van ArgoCD of Fleet of wat voor CI/CD tool dan ook.
Installatie
Maak eerst een namespace:
kubectl create namespace externaldns
En dan een secret waarin het wachtwoord van de Pi-Hole API staat:
kubectl -n externaldns create secret generic pihole-password --from-literal EXTERNAL_DNS_PIHOLE_PASSWORD=[het wachtwoord]
en dan kan een service-account aangemaakt worden, een clusterrole en clusterrolebinding in de externaldns namespace voor het service-account en uiteindelijk de deployment zelf.
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1
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: ["list","watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
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: externaldns
---
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: registry.k8s.io/external-dns/external-dns:v0.13.5
envFrom:
- secretRef:
name: pihole-password
args:
- --source=service
- --source=ingress
- --registry=noop ## omdat pi-hole geen TXT records kan aanmaken
- --policy=upsert-only ## om te voorkomen dat andere DNS records verwijderd worden
- --provider=pihole
- --pihole-server=http://[adres van jouw Pi-Hole server]
securityContext:
fsGroup: 65534
Kwestie van het manifest apply’en met kubectl en external DNS is geïnstalleerd.
External-DNS naar Pi-Hole local-DNS records kan helaas niet voorzien worden van TXT-records, vandaar de optie ‘noop‘. Hierdoor kan External-DNS niet bepalen welke records in Pi-Hole door External-DNS zijn aangemaakt.
Indien in Pi-Hole ook DNS records worden gebruikt die niet met external-dns zijn aangemaakt, dan is de optie ‘upsert-only‘ van toepassing om te voorkomen dat die records worden verwijderd door External-DNS. Het nadeel is dat records wel aangemaakt met External-DNS in Pi-Hole handmatig verwijderd dienen te worden als de service (of Ingress) in Kubernetes niet meer gebruikt wordt. (omdat er dus geen TXT-record aan hangt)
Services
Om voor services een DNS record aan te laten maken, is het noodzakelijk om in de service een annotation te zetten, bijvoorbeeld:
kubectl annotate service nginx "external-dns.alpha.kubernetes.io/hostname=nginx-speeltuin.digitalinfo.nl."
eventueel voorzien van een TimeToLive waarde:
kubectl annotate service nginx "external-dns.alpha.kubernetes.io/ttl=10"
De DNS records voor een ClusterIP type service is:
kubectl annotate service nginx "external-dns.alpha.kubernetes.io/internal-hostname=nginx-speeltuin.internal.digitalinfo.nl."
Ingress
Voor het aanmaken van een DNS record aan de hand van een Ingress hostname is geen annotation nodig. De DNS records voor een Ingress worden door external-dns aangemaakt zodra de Ingress wordt aangemaakt.