Kubernetes DIY Dynamic DNS Operator
· 2 min read
infrastructure
I’ve rolled my own Dynamic DNS Operator with Kubernetes CronJob, kubectl, and External DNS. I’m going to try capture the solution in a Google Design Document.
Context
A solution to dynamically maintain a DNS record containing my routers public IP.
Goals
- Record should not be out of date by more than five minutes.
- Run as a Kubernetes workload.
Non-Goal
- Support multiple public IPs.
- Ingress.
Design
The design is broken down into the following sections:
Discovering Router IP
With simple internet egress via router NAT - we can use several internet based services to return the IP:
$ curl --silent ifconfig.me
120.148.147.73
Changing DNS Records
External DNS Ingress annotations can configure a DNS record:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
external-dns.alpha.kubernetes.io/hostname: ip.home.jamesmoriarty.xyz
external-dns.alpha.kubernetes.io/target: 110.144.168.172
...
Generating Dynamic Configuration
CronJob to periodically generate and apply the configuration. The configuration variables are interpolated via heredoc
template:
cat << EOF > /tmp/ingress.yml && kubectl apply -f /tmp/ingress.yml
...
EOF
Interaction Diagram
Network Diagram
Example Manifest
An example of what the full Kubernetes manifest might look like:
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: dynamic-dns-operator
spec:
schedule: "*/5 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: dynamic-dns-operator
image: bitnami/kubectl
command:
- /bin/sh
- -c
- |
export IP=$(curl --silent ifconfig.me)
cat << EOF > /tmp/ingress.yml && kubectl apply -f /tmp/ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: dynamic-dns-operator
annotations:
kubernetes.io/ingress.class: nginx
external-dns.alpha.kubernetes.io/hostname: '$HOSTNAME'
external-dns.alpha.kubernetes.io/target: '$IP'
spec:
rules:
- host: '$HOSTNAME'
EOF
env:
- name: HOSTNAME
valueFrom:
configMapKeyRef:
name: dynamic-dns-operator
key: hostname
Conclusion
If you’re already using External DNS - another 30-40 lines CronJob can support Dynamic DNS.