All Products
Search
Document Center

Container Service for Kubernetes:Use the NodeLocal DNSCache add-on

Last Updated:Jun 15, 2026

Install a per-node DNS cache to reduce query latency and improve resolution reliability.

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.

Built on CoreDNS, the caching agent provides proxy and caching only. Do not enable plugins such as hosts or rewrite on it — configure them in CoreDNS.

DNS query flow after NodeLocal DNSCache is deployed:

image

DNS query flow after NodeLocal DNSCache is deployed:

image

No.

Description

By default, a pod with the local dnsConfig injected uses NodeLocal DNSCache, which listens for DNS queries sent to 169.254.20.10 on the node.

If NodeLocal DNSCache does not find a cache hit, it uses the kube-dns Service to forward the query to CoreDNS.

CoreDNS uses the DNS server deployed in the virtual private cloud (VPC) to resolve domain names that are not cluster-local.

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.

A pod without the local dnsConfig injected uses the kube-dns Service to connect to CoreDNS for DNS resolution.

See DNS resolution policies and caching policies.

Prerequisites

Before you begin, ensure that you have:

Limitations

  • Windows nodes are not supported. For pods on virtual nodes (including ECI and ACS pods), DNS caching is supported only when NodeLocal DNSCache v1.6.0 or later and ack-virtual-node v2.14.0 or later are installed.

  • If the cluster uses Terway, version 1.0.10.301 or later is required. If Terway runs in inclusive ENI mode with IPvlan, configure Terway for IPvlan mode first.

  • NodeLocal DNSCache acts only as a transparent caching proxy for CoreDNS and does not expose plugin extensibility. Configure plugins such as hosts or rewrite in CoreDNS instead.

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

  • Not installed on master nodes by default. If 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 your cluster 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, 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 injects dnsConfig into pods in namespaces labeled node-local-dns-injection=enabled. Label a namespace to enable injection:

kubectl label namespace default node-local-dns-injection=enabled
This enables injection for the default namespace only. Replace default with your target namespace as needed.

When enabled, the following dnsConfig is added to new pods. The kube-dns cluster IP is included as a fallback for 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 conditions below 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 injection fails, verify all conditions above.

Opt out of injection for specific pods

To exclude specific pods from injection, add node-local-dns-injection=disabled to the pod template labels:

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

On NodeLocal DNSCache versions earlier than v1.6.0 or ack-virtual-node versions earlier than v2.14.0, ECI pods cannot use NodeLocal DNSCache, which causes DNS failures. In that case, disable injection for the Deployment by adding node-local-dns-injection=disabled to 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 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

Enable NodeLocal DNSCache for a Deployment in the default namespace with Method 1 (automatic injection).

  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 this 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 dnsConfig injection. 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 a pod's dnsConfig:

    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]]

    169.254.20.10 in nameservers confirms dnsConfig injection.

Update NodeLocal DNSCache

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

  2. Click your cluster 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, click OK.

Custom tolerations on the node-local-dns DaemonSet are overwritten during upgrade. Reconfigure them afterward. 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. Click your cluster 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, 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 with early Terway versions, the default configuration may not route DNS traffic to 169.254.20.10 correctly. 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 apply 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 update:

    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 running, proceed to Install NodeLocal DNSCache.

Next steps