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.10by 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.
<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:
-
An ACK cluster. See Create an ACK managed cluster.
-
kubectl connected to the cluster. See Obtain the kubeconfig file of a cluster and use kubectl to connect to the cluster.
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
hostsorrewrite. 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-dnsDaemonSet in thekube-systemnamespace.
Install NodeLocal DNSCache
-
Log on to the ACK console. In the left-side navigation pane, click ACK consoleClusters.
-
Find the cluster you want to manage and choose More > Operations > Manage Components in the Actions column.
-
On the Add-ons page, click the Networking tab and find ACK NodeLocal DNSCache.
-
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 thedefaultnamespace. Replacedefaultwith 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-systemorkube-publicnamespace. -
The pod's namespace has the
node-local-dns-injection=enabledlabel. -
The pod's namespace does not have ECI-related labels (
virtual-node-affinity-injection,eci, oralibabacloud.com/eci). -
The pod does not have
eci,alibabacloud.com/eci, ornode-local-dns-injection=disabledlabels. -
The pod uses
hostNetworkwith theClusterFirstWithHostNetDNS policy, or does not usehostNetworkand uses theClusterFirstDNS 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"
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
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.
-
Label the namespace to enable automatic dnsConfig injection.
ImportantThe admission controller skips pods in the
kube-systemandkube-publicnamespaces. Do not enable injection for those namespaces.kubectl label namespace default node-local-dns-injection=enabled -
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.yamlExpected output:
deployment.apps/ubuntu created -
Verify the Deployment is running.
kubectl get deployment ubuntuExpected output:
NAME READY UP-TO-DATE AVAILABLE AGE ubuntu 2/2 2 2 7s -
Verify that dnsConfig was injected. Get a pod name:
kubectl get podsExpected output:
NAME READY STATUS RESTARTS AGE ubuntu-766448f68c-m**** 1/1 Running 0 4m39s ubuntu-766448f68c-w**** 1/1 Running 0 4m39sCheck 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.10innameserversconfirms that the dnsConfig was injected.
Update NodeLocal DNSCache
-
Log on to the ACK console. In the left-side navigation pane, click Clusters.
-
Find the cluster you want to manage and click its name. In the left-side navigation pane, choose Operations > Add-ons.
-
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
-
Log on to the ACK console. In the left-side navigation pane, click Clusters.
-
Find the cluster you want to manage and click its name. In the left-side navigation pane, choose Operations > Add-ons.
-
On the Add-ons page, find NodeLocal DNSCache and click Uninstall. In the dialog box that appears, click OK.
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.
-
Open the Terway ConfigMap for editing:
kubectl -n kube-system edit cm eni-config -o yaml -
Check the ConfigMap:
-
If
eniip_virtual_typeis not set toIPVlan, no changes are needed. Proceed to Install NodeLocal DNSCache. -
If
host_stack_cidrsis already present, no changes are needed. Proceed to Install NodeLocal DNSCache.
-
-
If
eniip_virtual_typeisIPVlanandhost_stack_cidrsis absent, addhost_stack_cidrsand set it to169.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" } -
List the Terway DaemonSet pods:
kubectl -n kube-system get pod | grep terway-eniipExpected output:
terway-eniip-7**** 2/2 Running 0 30m terway-eniip-s**** 2/2 Running 0 30m -
Delete the pods to trigger recreation with the updated configuration:
kubectl -n kube-system delete pod terway-eniip-7**** terway-eniip-s**** -
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.