All Products
Search
Document Center

Container Service for Kubernetes:Use the NodeLocal DNSCache component

Last Updated:Mar 26, 2026

NodeLocal DNSCache runs a DNS caching agent as a DaemonSet on every cluster node, reducing DNS latency and improving reliability for ACK clusters. This topic covers how to install, configure, and manage NodeLocal DNSCache.

How it works

NodeLocal DNSCache consists of two components:

  • DaemonSet (DNS caching agent): Runs on each node, creates a virtual network interface, and listens for DNS queries on 169.254.20.10 by default. To change the listen IP address, submit a ticket.

  • Deployment (admission controller): Intercepts pod creation requests via admission webhooks and automatically injects dnsConfig into pod specs.

The caching agent is built on CoreDNS and provides proxy and caching services only. Do not enable other plugins such as hosts or rewrite on it — configure those in CoreDNS instead.

The following diagram shows the DNS query flow after NodeLocal DNSCache is deployed.

image <table> <thead> <tr> <td><p><b>No.</b></p></td> <td><p><b>Description</b></p></td> </tr> </thead> <colgroup></colgroup> <colgroup></colgroup> <tbody> <tr> <td><p>①</p></td> <td><p>By default, a pod with the local dnsConfig injected uses NodeLocal DNSCache to listen for DNS queries that are sent to the IP address 169.254.20.10 on the node. </p></td> </tr> <tr> <td><p>②</p></td> <td><p>If NodeLocal DNSCache does not find a cache hit for the DNS query, the kube-dns Service is used to request CoreDNS to handle the query. </p></td> </tr> <tr> <td><p>③</p></td> <td><p>CoreDNS uses the DNS server deployed in the virtual private cloud (VPC) to resolve domain names that are not cluster-local. </p></td> </tr> <tr> <td><p>④</p></td> <td><p>If the pod with the local dnsConfig injected fails to connect to NodeLocal DNSCache, the pod uses the kube-dns Service to connect to CoreDNS for DNS resolution. </p></td> </tr> <tr> <td><p>⑤</p></td> <td><p>A pod without the local dnsConfig injected uses the kube-dns Service to connect to CoreDNS for DNS resolution. </p></td> </tr> </tbody> </table>

For details on caching policies, see DNS resolution policies and caching policies.

Prerequisites

Before you begin, ensure that you have:

Limitations

  • NodeLocal DNSCache does not support pods running on ACK Serverless clusters or on Elastic Container Instances (ECI) in ACK managed or dedicated clusters.

  • If the cluster uses the Terway network plugin, Terway 1.0.10.301 or later is required. If Terway runs in inclusive ENI mode based on IPvlan, additional configuration is required. See Configure Terway for IPvlan mode.

  • NodeLocal DNSCache is a transparent caching proxy for CoreDNS and does not provide plugins such as hosts or rewrite. To use these plugins, configure them in CoreDNS.

  • Configure the default protocol for the CoreDNS forward plugin before using NodeLocal DNSCache, or CoreDNS may fail to resolve external domain names. See Best practices for DNS services.

  • NodeLocal DNSCache is not installed on master nodes by default. If business pods run on tainted master nodes, add matching tolerations to the node-local-dns DaemonSet in the kube-system namespace.

Install NodeLocal DNSCache

  1. Log on to the ACK console. In the left-side navigation pane, click ACK consoleClusters.

  2. Find the cluster you want to manage and choose More > Operations > Manage Components in the Actions column.

  3. On the Add-ons page, click the Networking tab and find ACK NodeLocal DNSCache.

  4. Click Install. In the dialog box that appears, click OK.

Configure NodeLocal DNSCache

To route DNS queries from pods through NodeLocal DNSCache, set nameservers in pod dnsConfig to 169.254.20.10 and the cluster IP address of kube-dns. Use one of the following methods:

Method Recommendation Description
Method 1: Automatic dnsConfig injection Recommended The admission controller injects dnsConfig at pod creation time — no manual YAML edits required.
Method 2: Manual dnsConfig Neutral Specify dnsConfig directly in pod YAML.
Method 3: kubelet startup parameters Not recommended Modifies kubelet and requires a restart, which may interrupt workloads.

Method 1: Automatic dnsConfig injection

The admission controller watches for pod creation requests in namespaces labeled node-local-dns-injection=enabled and automatically injects dnsConfig. Label a namespace to enable injection:

kubectl label namespace default node-local-dns-injection=enabled
The preceding command enables injection only for the default namespace. Replace default with any other namespace as needed.

When automatic injection is enabled, the following dnsConfig is added to newly created pods. The cluster IP address of kube-dns is included as a backup DNS server to maintain high availability.

dnsConfig:
  nameservers:
  - 169.254.20.10
  - 172.21.0.10
  options:
  - name: ndots
    value: "3"
  - name: attempts
    value: "2"
  - name: timeout
    value: "1"
  searches:
  - default.svc.cluster.local
  - svc.cluster.local
  - cluster.local
dnsPolicy: None

Injection conditions

Injection applies only when all of the following conditions are met:

  • The pod is not in the kube-system or kube-public namespace.

  • The pod's namespace has the node-local-dns-injection=enabled label.

  • The pod's namespace does not have ECI-related labels (virtual-node-affinity-injection, eci, or alibabacloud.com/eci).

  • The pod does not have eci, alibabacloud.com/eci, or node-local-dns-injection=disabled labels.

  • The pod uses hostNetwork with the ClusterFirstWithHostNet DNS policy, or does not use hostNetwork and uses the ClusterFirst DNS policy.

If no DNS server IP address is injected into a pod's containers, verify that all conditions above are met.

Opt out of injection for specific pods

To exclude specific pods from injection while injection is enabled for their namespace, add node-local-dns-injection=disabled to the pod template labels:

metadata:
  labels:
    node-local-dns-injection: "disabled"
Important

ECI does not support NodeLocal DNSCache. When a Deployment scales out and new pods land on ECI, those pods cannot connect to NodeLocal DNSCache, causing DNS resolution failures. Disable injection for the entire Deployment by adding node-local-dns-injection=disabled to the pod template labels.

Method 2: Manual dnsConfig

Specify dnsConfig directly in the pod spec:

apiVersion: v1
kind: Pod
metadata:
  name: alpine
  namespace: default
spec:
  containers:
  - image: alpine
    command:
      - sleep
      - "10000"
    imagePullPolicy: Always
    name: alpine
  dnsPolicy: None
  dnsConfig:
    nameservers: ["169.254.20.10","172.21.0.10"]
    searches:
    - default.svc.cluster.local
    - svc.cluster.local
    - cluster.local
    options:
    - name: ndots
      value: "3"
    - name: attempts
      value: "2"
    - name: timeout
      value: "1"

Key fields:

Field Value Notes
dnsPolicy None Required when specifying custom dnsConfig.
nameservers 169.254.20.10, kube-dns cluster IP The first entry routes to NodeLocal DNSCache; the second is the kube-dns fallback.
searches Cluster DNS search domains Ensures internal service names resolve correctly.
ndots 3 A lower value reduces the number of search-domain lookups before trying the name as-is. Default is 5. See resolv.conf.

Method 3: kubelet startup parameters

In /etc/systemd/system/kubelet.service.d/10-kubeadm.conf, add --cluster-dns with the NodeLocal DNSCache IP and the kube-dns IP:

--cluster-dns=169.254.20.10 --cluster-dns=<kube-dns-ip> --cluster-domain=<search-domain>
Parameter Description
--cluster-dns DNS servers written into pod dnsConfig. Specify 169.254.20.10 first, then the kube-dns IP.
--cluster-domain DNS search domain written into pod dnsConfig. In most clusters, this is cluster.local.

After editing the file, apply the changes:

sudo systemctl daemon-reload
sudo systemctl restart kubelet
Important

Restarting kubelet may briefly interrupt running workloads.

Example: configure NodeLocal DNSCache for a Deployment

This example uses Method 1 (automatic injection) to enable NodeLocal DNSCache for a Deployment in the default namespace.

  1. Label the namespace to enable automatic dnsConfig injection.

    Important

    The admission controller skips pods in the kube-system and kube-public namespaces. Do not enable injection for those namespaces.

    kubectl label namespace default node-local-dns-injection=enabled
  2. Deploy a sample application. Save the following YAML as ubuntu-deployment.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: ubuntu
      labels:
        app: ubuntu
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: ubuntu
      template:
        metadata:
          labels:
            app: ubuntu
        spec:
          containers:
          - name: ubuntu
            image: ubuntu
            command: ["sh", "-c"]
            args: ["sleep 100000"]

    Apply the manifest:

    kubectl apply -f ubuntu-deployment.yaml

    Expected output:

    deployment.apps/ubuntu created
  3. Verify the Deployment is running.

    kubectl get deployment ubuntu

    Expected output:

    NAME     READY   UP-TO-DATE   AVAILABLE   AGE
    ubuntu   2/2     2            2           7s
  4. Verify that dnsConfig was injected. Get a pod name:

    kubectl get pods

    Expected output:

    NAME                      READY   STATUS    RESTARTS   AGE
    ubuntu-766448f68c-m****   1/1     Running   0          4m39s
    ubuntu-766448f68c-w****   1/1     Running   0          4m39s

    Check the dnsConfig on a pod:

    kubectl get pod ubuntu-766448f68c-m**** -o=jsonpath='{.spec.dnsConfig}'

    Expected output:

    map[nameservers:[169.254.20.10 172.21.0.10] options:[map[name:ndots value:5]] searches:[default.svc.cluster.local svc.cluster.local cluster.local]]

    The presence of 169.254.20.10 in nameservers confirms that the dnsConfig was injected.

Update NodeLocal DNSCache

  1. Log on to the ACK console. In the left-side navigation pane, click Clusters.

  2. Find the cluster you want to manage and click its name. In the left-side navigation pane, choose Operations > Add-ons.

  3. On the Add-ons page, find NodeLocal DNSCache and click Upgrade. In the dialog box that appears, click OK.

If you modified tolerations on the node-local-dns DaemonSet, those changes are overwritten during the upgrade. Reconfigure tolerations after the upgrade completes. If the upgrade fails, see Component troubleshooting.

Uninstall NodeLocal DNSCache

  1. Log on to the ACK console. In the left-side navigation pane, click Clusters.

  2. Find the cluster you want to manage and click its name. In the left-side navigation pane, choose Operations > Add-ons.

  3. On the Add-ons page, find NodeLocal DNSCache and click Uninstall. In the dialog box that appears, click OK.

Important

After uninstalling, all DNS queries go directly to CoreDNS. Scale out CoreDNS before uninstalling to handle the increased load.

Configure Terway for IPvlan mode

In clusters created with an early version of Terway, the default Terway configuration may not route DNS traffic to 169.254.20.10 correctly. Check and update the configuration before installing NodeLocal DNSCache.

  1. Open the Terway ConfigMap for editing:

    kubectl -n kube-system edit cm eni-config -o yaml
  2. Check the ConfigMap:

  3. If eniip_virtual_type is IPVlan and host_stack_cidrs is absent, add host_stack_cidrs and set it to 169.254.20.10/32. Save and exit.

    10-terway.conf: |
     {
       "cniVersion": "0.3.0",
       "name": "terway",
       "eniip_virtual_type": "IPVlan",
       "host_stack_cidrs": ["169.254.20.10/32"],
       "type": "terway"
     }
  4. List the Terway DaemonSet pods:

    kubectl -n kube-system get pod | grep terway-eniip

    Expected output:

    terway-eniip-7****         2/2     Running   0          30m
    terway-eniip-s****         2/2     Running   0          30m
  5. Delete the pods to trigger recreation with the updated configuration:

    kubectl -n kube-system delete pod terway-eniip-7**** terway-eniip-s****
  6. Log on to a cluster node and verify the configuration was applied:

    cat /etc/cni/net.d/*

    Expected output:

    {
      "cniVersion": "0.3.0",
      "name": "terway-chainer",
      "plugins": [
        {
          "eniip_virtual_type": "IPVlan",
          "host_stack_cidrs": [
            "169.254.20.10/32"
          ],
          "type": "terway"
        },
        {
          "type": "cilium-cni"
        }
      ]
    }

    After all Terway pods are recreated and running, proceed to Install NodeLocal DNSCache.

What's next