Configure NodeLocal DNS Cache
To reduce DNS load in a Managed Kubernetes cluster and speed up response times from external and internal resources, you can use NodeLocal DNS Cache.
NodeLocal DNS Cache is a DNS query caching mechanism that runs on all Managed Kubernetes nodes and provides a local cache for the DNS resolver. When a user's nodes send queries, they first pass through the local DNS cache. If these queries match previously stored records, additional queries to an external DNS server are avoided. This reduces DNS query processing time and saves network traffic in the cluster.
Read more about NodeLocal DNS Cache in Kubernetes documentation.
Configure NodeLocal DNS Cache
-
Create a yaml file
nodelocaldns.yaml
with a manifesto:File nodelocaldns.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: node-local-dns
namespace: kube-system
labels:
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
---
apiVersion: v1
kind: Service
metadata:
name: kube-dns-upstream
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
kubernetes.io/name: "KubeDNSUpstream"
spec:
ports:
- name: dns
port: 53
protocol: UDP
targetPort: 53
- name: dns-tcp
port: 53
protocol: TCP
targetPort: 53
selector:
k8s-app: kube-dns
---
apiVersion: v1
kind: ConfigMap
metadata:
name: node-local-dns
namespace: kube-system
labels:
addonmanager.kubernetes.io/mode: Reconcile
data:
Corefile: |
cluster.local:53 {
errors
cache {
success 9984 30
denial 9984 5
}
reload
loop
bind 169.254.20.25 10.96.0.10
forward . __PILLAR__CLUSTER__DNS__ {
force_tcp
}
prometheus :9253
health 169.254.20.25:8080
}
in-addr.arpa:53 {
errors
cache 30
reload
loop
bind 169.254.20.25 10.96.0.10
forward . __PILLAR__CLUSTER__DNS__ {
force_tcp
}
prometheus :9253
}
ip6.arpa:53 {
errors
cache 30
reload
loop
bind 169.254.20.25 10.96.0.10
forward . __PILLAR__CLUSTER__DNS__ {
force_tcp
}
prometheus :9253
}
.:53 {
errors
cache 30
reload
loop
bind 169.254.20.25 10.96.0.10
forward . __PILLAR__UPSTREAM__SERVERS__
prometheus :9253
}
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-local-dns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
spec:
updateStrategy:
rollingUpdate:
maxUnavailable: 10%
selector:
matchLabels:
k8s-app: kube-dns
template:
metadata:
labels:
k8s-app: kube-dns
annotations:
prometheus.io/port: "9253"
prometheus.io/scrape: "true"
spec:
priorityClassName: system-node-critical
serviceAccountName: node-local-dns
hostNetwork: true
dnsPolicy: Default # Do not use cluster DNS.
tolerations:
- key: "CriticalAddonsOnly"
operator: "Exists"
- effect: "NoExecute"
operator: "Exists"
- effect: "NoSchedule"
operator: "Exists"
containers:
- name: node-cache
image: registry.k8s.io/dns/k8s-dns-node-cache:1.22.20
resources:
requests:
cpu: 25m
memory: 5Mi
args: [ "-localip", "169.254.20.25,10.96.0.10", "-conf", "/etc/Corefile", "-upstreamsvc", "kube-dns-upstream" ]
securityContext:
capabilities:
add:
- NET_ADMIN
ports:
- containerPort: 53
name: dns
protocol: UDP
- containerPort: 53
name: dns-tcp
protocol: TCP
- containerPort: 9253
name: metrics
protocol: TCP
livenessProbe:
httpGet:
host: 169.254.20.25
path: /health
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
volumeMounts:
- mountPath: /run/xtables.lock
name: xtables-lock
readOnly: false
- name: config-volume
mountPath: /etc/coredns
- name: kube-dns-config
mountPath: /etc/kube-dns
volumes:
- name: xtables-lock
hostPath:
path: /run/xtables.lock
type: FileOrCreate
- name: kube-dns-config
configMap:
name: kube-dns
optional: true
- name: config-volume
configMap:
name: node-local-dns
items:
- key: Corefile
path: Corefile.base -
Apply the manifest:
kubectl create -f nodelocaldns.yaml
A list of created objects will appear in the response:
serviceaccount/node-local-dns created
service/kube-dns-upstream created
configmap/node-local-dns created
daemonset.apps/node-local-dns created
Verify NodeLocal DNS Cache operation
-
Enable logging mode for NodeLocal DNS pods. In the manifest
nodelocaldns.yaml
in the facilityConfigMap
add a linelog
:data:
Corefile: |
cluster.local:53 {
log
errors
cache {
success 9984 30
denial 9984 5
} -
Apply the manifest:
kubectl apply -f nodelocaldns.yaml
-
Run under with the DNS checking utilities:
kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml
A confirmation will appear in the response that a sub has been created:
pod/dnsutils created
-
Make sure that under the status
Running
:kubectl get pods dnsutils
-
Connect to the pod:
kubectl exec -i -t dnsutils -- bash
-
Perform a test query about the domain to the DNS server:
dig @169.254.20.25 selectel.ru
The response will show that the request is successful:
;; ANSWER SECTION:
selectel.ru. 30 IN A 85.119.149.3
;; Query time: 437 msec
;; SERVER: 169.254.20.25#53(169.254.20.25)
;; WHEN: Wed Sep 20 15:43:46 UTC 2023
;; MSG SIZE rcvd: 67 -
Check the logs:
kubectl logs --namespace=kube-system -l k8s-app=kube-dns -f
In the response, DNS records A and AAAA with the code
NOERROR
:[INFO] 10.10.71.3:45929 - 55864 "A IN ru-2.cloud.api.selcloud.ru.kube-system.svc.cluster.local. udp 85 false 1232" NOERROR qr,aa,rd,ra 212 3.975488442s
[INFO] 10.10.71.3:36099 - 21119 "AAAA IN ru-2.cloud.api.selcloud.ru.kube-system.svc.cluster.local. udp 85 false 1232" NOERROR qr,aa,rd 74 3.976010334s