Skip to main content
Configure NodeLocal DNS Cache
Last update:

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 user pods send requests, they first pass through the local DNS cache. If these queries match previously saved 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.

  1. Configure NodeLocal DNS Cache.
  2. Check NodeLocal DNS Cache operation.

Configure NodeLocal DNS Cache

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

    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.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
  2. 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

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

    data:
    Corefile: |
    cluster.local:53 {
    log
    errors
    cache {
    success 9984 30
    denial 9984 5
    }
  2. Apply the manifest:

    kubectl apply -f nodelocaldns.yaml
  3. 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
  4. Make sure the sub is in Running status:

    kubectl get pods dnsutils
  5. Connect to the pod:

    kubectl exec -i -t dnsutils -- bash
  6. 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
  7. 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