---
title: "Configure NodeLocal DNS Cache in a Managed Kubernetes cluster"
sidebar_label: "Configure NodeLocal DNS Cache"
description: "How to configure local DNS caching"
sidebar_position: 7
toc_max_heading_level: 2
---

import Formbricks from '@theme/MDXComponents/Formbricks'

# Configure NodeLocal DNS Cache in a Managed Kubernetes cluster

To reduce the load on DNS 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 user pods send requests, they first pass through the local DNS cache. If these requests match previously saved records, additional requests to an external DNS server are avoided. This allows for reduced DNS request processing time and saves network traffic in the cluster.

Read more about NodeLocal DNS Cache in the [Kubernetes documentation](https://kubernetes.io/docs/tasks/administer-cluster/nodelocaldns/).

1. [Configure NodeLocal DNS Cache](#configure-nodelocal-dns-cache).
2. [Check the operation of NodeLocal DNS Cache](#check-nodelocal-dns-cache-operation).

## Configure NodeLocal DNS Cache \{#configure-nodelocal-dns-cache}

1. Create a `nodelocaldns.yaml` YAML file with the manifest:

   <details>
     <summary>nodelocaldns.yaml file</summary>

     ```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
     ```
   </details>

2. Apply the manifest:

   ```bash
   kubectl create -f nodelocaldns.yaml
   ```

   The list of created objects will appear in the response:

   ```bash
   serviceaccount/node-local-dns created
   service/kube-dns-upstream created
   configmap/node-local-dns created
   daemonset.apps/node-local-dns created
   ```

## Check the operation of NodeLocal DNS Cache \{#check-nodelocal-dns-cache-operation}

1. enable logging mode for NodeLocal DNS pods. In the `nodelocaldns.yaml` manifest, add the `ConfigMap` object line `log`:

   ```bash
   data:
     Corefile: |
         cluster.local:53 {
           log
           errors
           cache {
                   success 9984 30
                   denial 9984 5
           }
   ```

2. Apply the manifest:

   ```bash
   kubectl apply -f nodelocaldns.yaml
   ```

3. Start a pod with DNS testing utilities:

   ```bash
   kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml
   ```

   The response will show confirmation that the pod has been created:

   ```bash
   pod/dnsutils created
   ```

4. ensure the pod is in the `Running` status:

   ```bash
   kubectl get pods dnsutils
   ```

5. Connect to the pod:

   ```bash
   kubectl exec -i -t dnsutils -- bash
   ```

6. Execute a test domain request to the DNS server:

   ```bash
   dig @169.254.20.25 selectel.ru
   ```

   The response will show that the request was successfully executed:

   ```bash
   ;; 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
   ```

7. Check the logs:

   ```bash
   kubectl logs --namespace=kube-system -l k8s-app=kube-dns -f
   ```

   The response will contain A and AAAA DNS records with the `NOERROR`:

   ```bash
   [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
   ```

<Formbricks />
