Custom DNS entry with KubeDNS stubdomain
Thu 11 March 2021 | Last updated on Tue 06 December 2022An example use case that I've seen is where you have a K8s service exposed on the ClusterIP and you want to make that service accessible over a domain name that you don't control.
You can do to the following steps to set this up:
- Deploy CoreDNS with custom DNS entries
- Configure kube-dns to use stubDomain that points to CoreDNS
1. Deploying CoreDNS with custom DNS entries
Create the namespace for coredns k8s resources:
kubectl create ns coredns
Create a file called core-dns-cm.yaml
with the following content:
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: coredns
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
cache 30
log
reload
loadbalance
file /etc/coredns/example.db example.org
}
example.db: |
; example.org test file
example.org. IN SOA sns.dns.icann.org. noc.dns.icann.org. 2015082541 7200 3600 1209600 3600
example.org. IN NS b.iana-servers.net.
example.org. IN NS a.iana-servers.net.
example.org. IN A 10.200.0.1
In the configmap you definte the custom dns entries. In the example, the A record for example.org has been overriden to point to 10.200.0.1. You would change example.org and the specific DNS entries depending on your needs.
Create the configmap:
kubectl apply -f core-dns-cm.yaml
Create a file named core-dns-deployment.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: coredns
namespace: coredns
labels:
k8s-app: coredns
kubernetes.io/name: "CoreDNS"
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
selector:
matchLabels:
k8s-app: coredns
template:
metadata:
labels:
k8s-app: coredns
spec:
containers:
- name: coredns
image: coredns/coredns:1.8.3
imagePullPolicy: IfNotPresent
resources:
limits:
memory: 170Mi
requests:
cpu: 100m
memory: 70Mi
args: [ "-conf", "/etc/coredns/Corefile" ]
volumeMounts:
- name: config-volume
mountPath: /etc/coredns
readOnly: true
ports:
- containerPort: 53
name: dns
protocol: UDP
- containerPort: 53
name: dns-tcp
protocol: TCP
securityContext:
allowPrivilegeEscalation: false
capabilities:
add:
- NET_BIND_SERVICE
drop:
- all
readOnlyRootFilesystem: true
livenessProbe:
httpGet:
path: /health
port: 8080
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
readinessProbe:
httpGet:
path: /ready
port: 8181
scheme: HTTP
dnsPolicy: Default
volumes:
- name: config-volume
configMap:
name: coredns
items:
- key: Corefile
path: Corefile
- key: example.db
path: example.db
Create the deployment that uses the configmap:
kubectl apply -f core-dns-deployment.yaml
Create a file named core-dns-svc.yaml
:
apiVersion: v1
kind: Service
metadata:
name: coredns
namespace: coredns
labels:
k8s-app: coredns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "CoreDNS"
spec:
clusterIP: 10.0.6.177
selector:
k8s-app: coredns
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP
Notice that we set a static cluster IP so this blog post is easier to follow.
You will probably want to remove clusterIP: 10.0.6.177
and let K8s asign a
random clusterIP, afterwards note note down the cluster IP. You will need the
CoreDNS cluster IP in the next step during configuring kube-dns.
Create the coredns k8s service:
kubectl apply -f core-dns-svc.yaml
2. Configure kube-dns to use stubDomain that points to CoreDNS
In this step, you will be configuring kube-dns to go to our coredns server
that holds the custom DNS entries. This is done by configuring a stubDomain
that for e.g. example.org
that points to the coreDNS clusterIP.
Create a file named kube-dns-cm.yaml
:
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-dns
namespace: kube-system
data:
stubDomains: |
{"example.org" : ["10.0.6.177"]}
Apply the config map:
kubectl apply -f kube-dns-cm.yaml
Summary
You have deployed a custom DNS server that holds custom DNS entries by using
coreDNS deployed on K8s. Afterwards you configured kube-dns to point to that
DNS server by configuring a stubdomain. Now you can test it out by deploying
a pod and running dig example.org
from a pod. That should return 10.200.0.1
.