I’ve decided to move my DNS server from a VM in the physical ESXi, to some pods in my Raspberry Pi K3s cluster. If you have some Raspberry Pis laying around and want to setup a simple K8s cluster, checkout my guide: K3s on the Raspberry Pi
The below guide will assume that you’ve setup a kubernetes cluster and have some external Load Balancer configured. In my case, I’m using MetalLB.
Configure the Deployment and Service yaml
The below file will include our deployment using the cytopia/bind image, and an L4 service type LoadBalancer. See additional details on cytopia
It will create 2 services, 1 for UDP 53 and another for TCP 53.
Specify all the A records and the PTR (reverse dns) records that you want added.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dns
spec:
selector:
matchLabels:
app: dns
replicas: 3
template:
metadata:
labels:
app: dns
spec:
containers:
- name: dns
image: cytopia/bind
ports:
- containerPort: 53
env:
- name: DNS_PTR
value: 192.168.3.4=esxi2.home.lab, 192.168.3.5=esxi1.home.lab
- name: DNS_A
value: esxi2=192.168.3.4, esxi1=192.168.3.5
- name: ALLOW_QUERY
value: any
- name: DOCKER_LOGS
value: '1'
---
apiVersion: v1
kind: Service
metadata:
name: dns-service-udp
annotations:
metallb.universe.tf/address-pool: dnspool
metallb.universe.tf/allow-shared-ip: "dnskey"
spec:
selector:
app: dns
ports:
- protocol: UDP
port: 53
targetPort: 53
type: LoadBalancer
loadBalancerIP: 192.168.3.199
---
apiVersion: v1
kind: Service
metadata:
name: dns-service-tcp
annotations:
metallb.universe.tf/address-pool: dnspool
metallb.universe.tf/allow-shared-ip: "dnskey"
spec:
selector:
app: dns
ports:
- protocol: TCP
port: 53
targetPort: 53
type: LoadBalancer
loadBalancerIP: 192.168.3.199
Apply the DNS yaml
# Apply the yaml
kubectl apply -f dns.yaml
Testing
# Kubernetes Objects
kubectl get pods
kubectl get service
# Test DNS
# +short just returns the response
# +vc tests TCP, the default is UDP
dig @192.168.3.199 esxi1.home.lab +short
dig @192.168.3.199 esxi1.home.lab +short +vc
dig @192.168.3.199 -x 192.168.3.5 +short
dig @192.168.3.199 -x 192.168.3.5 +short +vc
Extra
It’s rather annoying to have to add each DNS entry into that list, especially to duplicate it again with the PTR records. Having to do that manually might take minutes..
So I have a simple python script that will take a list of fqdn and IP addresses, and convert them into the appropriate yaml format
#!/usr/bin/python3
import yaml
dns_list = {
"esxi2.home.lab": "192.168.3.4",
"esxi1.home.lab": "192.168.3.5",
"ns1.home.lab": "192.168.3.6"
}
def Arecords(dnslist):
DNS_A = []
for dns in dnslist:
DNS_A.append(dns + "=" + dnslist[dns])
return (', '.join(DNS_A))
def PTRrecords(dnslist):
DNS_PTR = []
for dns in dnslist:
DNS_PTR.append(dnslist[dns] + "=" + dns)
return (', '.join(DNS_PTR))
if __name__ == '__main__':
json = []
json.append({"name": "DNS_PTR", "value": PTRrecords(dns_list)})
json.append({"name": "DNS_A", "value": Arecords(dns_list)})
json.append({"name": "ALLOW_QUERY", "value": "any"})
json.append({"name": "DOCKER_LOGS", "value": "1"})
print (yaml.dump(json,sort_keys=False))