Configure NodeLocal DNS Cache in a Managed Kubernetes cluster
To reduce the load on DNS in a Managed Kubernetes cluster and speed up the response 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 the Kubernetes documentation.
Configure NodeLocal DNS Cache
-
Create a
nodelocaldns.yamlfilewith themanifest:File nodelocaldns.yaml
apiVersion: v1kind: ServiceAccountmetadata:name: node-local-dnsnamespace: kube-systemlabels:kubernetes.io/cluster-service: "true"addonmanager.kubernetes.io/mode: Reconcile---apiVersion: v1kind: Servicemetadata:name: kube-dns-upstreamnamespace: kube-systemlabels:k8s-app: kube-dnskubernetes.io/cluster-service: "true"addonmanager.kubernetes.io/mode: Reconcilekubernetes.io/name: "KubeDNSUpstream"spec:ports:- name: dnsport: 53protocol: UDPtargetPort: 53- name: dns-tcpport: 53protocol: TCPtargetPort: 53selector:k8s-app: kube-dns---apiVersion: v1kind: ConfigMapmetadata:name: node-local-dnsnamespace: kube-systemlabels:addonmanager.kubernetes.io/mode: Reconciledata:Corefile: |cluster.local:53 {errorscache {success 9984 30denial 9984 5}reloadloopbind 169.254.20.25 10.96.0.10forward . __PILLAR__CLUSTER__DNS__ {force_tcp}prometheus :9253health 169.254.20.25:8080}in-addr.arpa:53 {errorscache 30reloadloopbind 169.254.20.25 10.96.0.10forward . __PILLAR__CLUSTER__DNS__ {force_tcp}prometheus :9253}ip6.arpa:53 {errorscache 30reloadloopbind 169.254.20.25 10.96.0.10forward . __PILLAR__CLUSTER__DNS__ {force_tcp}prometheus :9253}.:53 {errorscache 30reloadloopbind 169.254.20.25 10.96.0.10forward . __PILLAR__UPSTREAM__SERVERS__prometheus :9253}---apiVersion: apps/v1kind: DaemonSetmetadata:name: node-local-dnsnamespace: kube-systemlabels:k8s-app: kube-dnskubernetes.io/cluster-service: "true"addonmanager.kubernetes.io/mode: Reconcilespec:updateStrategy:rollingUpdate:maxUnavailable: 10%selector:matchLabels:k8s-app: kube-dnstemplate:metadata:labels:k8s-app: kube-dnsannotations:prometheus.io/port: "9253"prometheus.io/scrape: "true"spec:priorityClassName: system-node-criticalserviceAccountName: node-local-dnshostNetwork: truednsPolicy: Default # Do not use cluster DNS.tolerations:- key: "CriticalAddonsOnly"operator: "Exists"- effect: "NoExecute"operator: "Exists"- effect: "NoSchedule"operator: "Exists"containers:- name: node-cacheimage: registry.k8s.io/dns/k8s-dns-node-cache:1.22.20resources:requests:cpu: 25mmemory: 5Miargs: [ "-localip", "169.254.20.25,10.96.0.10", "-conf", "/etc/Corefile", "-upstreamsvc", "kube-dns-upstream" ]securityContext:capabilities:add:- NET_ADMINports:- containerPort: 53name: dnsprotocol: UDP- containerPort: 53name: dns-tcpprotocol: TCP- containerPort: 9253name: metricsprotocol: TCPlivenessProbe:httpGet:host: 169.254.20.25path: /healthport: 8080initialDelaySeconds: 60timeoutSeconds: 5volumeMounts:- mountPath: /run/xtables.lockname: xtables-lockreadOnly: false- name: config-volumemountPath: /etc/coredns- name: kube-dns-configmountPath: /etc/kube-dnsvolumes:- name: xtables-lockhostPath:path: /run/xtables.locktype: FileOrCreate- name: kube-dns-configconfigMap:name: kube-dnsoptional: true- name: config-volumeconfigMap:name: node-local-dnsitems:- key: Corefilepath: Corefile.base -
Apply the manifest:
kubectl create -f nodelocaldns.yamlA list of created objects will appear in the response:
serviceaccount/node-local-dns createdservice/kube-dns-upstream createdconfigmap/node-local-dns createddaemonset.apps/node-local-dns created
Verify NodeLocal DNS Cache operation
-
Enable logging mode for NodeLocal DNS pods. In the
nodelocaldns.yamlmanifest, add the log line to theConfigMapobject:data:Corefile: |cluster.local:53 {logerrorscache {success 9984 30denial 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.yamlA confirmation will appear in the response that a sub has been created:
pod/dnsutils created -
Make sure the sub is in
Runningstatus: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.ruThe 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 -fThe response is DNS records A and AAAA with a
NOERRORcode:[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