DNS is a critical Kubernetes infrastructure service. Improper client settings and large cluster scale can cause resolution timeouts and failures. Optimize client and server configuration using these best practices.
Usage notes
Does not apply to managed CoreDNS or ACK clusters with Auto Mode enabled. Managed CoreDNS auto-scales with workload, so manual adjustments are unnecessary.
Contents
DNS best practices cover the client side and server side:
-
On the client side, reduce resolution latency by optimizing domain name resolution requests. Minimize resolution anomalies with appropriate container images, suitable node operating systems, and NodeLocal DNSCache.
-
On the CoreDNS server side, monitor runtime status to detect DNS anomalies and identify root causes. Improve CoreDNS high availability and queries per second (QPS) throughput by adjusting deployment settings.
See the official CoreDNS documentation.
Optimize domain name resolution requests
DNS resolution is one of the most frequent network activities in Kubernetes. Many requests can be optimized or avoided:
-
(Recommended) Use connection pools. If a containerized application frequently accesses another service, cache upstream connections in memory to avoid DNS resolution and TCP setup on each access.
-
Use asynchronous or long polling to obtain the IP address for a DNS domain name.
-
Use DNS caching:
-
(Recommended) If your application cannot use connection pools, cache DNS resolution results on the application side or use NodeLocal DNSCache.
-
If NodeLocal DNSCache is unavailable, cache DNS queries inside the container with Name Service Cache Daemon (NSCD). See Use NSCD in Kubernetes clusters.
-
-
Optimize the resolv.conf file: ndots and search affect resolution efficiency based on how you write domain names in container configurations. See DNS policy configuration and domain name resolution for details on ndots and search.
-
Optimize domain name configuration to minimize resolution attempts and reduce resolution time:
-
For same-namespace Service access, use
<service-name>, whereservice-nameis the Service name. -
For cross-namespace Service access, use
<service-name>.<namespace-name>, wherenamespace-nameis the Service namespace. -
For external domains, use fully qualified domain names (FQDNs). Append a trailing dot (.) to specify absolute addresses and avoid invalid
searchdomain concatenation. For example, use www.aliyun.com. instead of www.aliyun.com.-
In clusters version 1.33 or later, set the search domain to a single "." (see 125883) for a similar effect:
dnsPolicy: None dnsConfig: nameservers: ["192.168.0.10"] ## Replace 192.168.0.10 with the actual CoreDNS service clusterIP searches: - . - default.svc.cluster.local ## Replace "default" with your namespace name - svc.cluster.local - cluster.localAfter you apply this configuration, /etc/resolv.conf in the pod appears as follows:
search . default.svc.cluster.local svc.cluster.local cluster.local nameserver 192.168.0.10A "." as the first search domain treats all domain requests as FQDNs and resolves them directly without unnecessary search attempts.
ImportantSet
dnsPolicytoNonefor this configuration to take effect.
-
-
Understand DNS configuration in containers
-
Different DNS resolvers may behave differently. You might see dig <domain> succeed while ping <domain> fails.
-
Avoid Alpine base images. Use other base images such as Debian or CentOS instead. The musl libc in Alpine differs from glibc and can cause these issues:
-
Alpine 3.18 and earlier do not support falling back to TCP for DNS queries.
-
Alpine 3.3 and earlier do not support the search parameter or search domains, which blocks service discovery.
-
Concurrent queries to multiple DNS servers in /etc/resolv.conf can invalidate NodeLocal DNSCache optimizations.
-
Concurrent A and AAAA queries on the same socket can trigger conntrack source port conflicts on older kernels, causing packet loss.
See musl libc.
-
-
For Go applications, understand the differences between CGO and Pure Go DNS resolver implementations.
Avoid probabilistic DNS resolution timeouts caused by IPVS defects
With IPVS as the kube-proxy load balancing mode, you may encounter intermittent DNS resolution timeouts during CoreDNS scale-in or restart due to a Linux kernel defect. See IPVS.
Reduce the impact of IPVS defects using one of these methods:
-
Modify the IPVS UDP session persistence timeout in kube-proxy. See How do I modify the IPVS UDP session persistence timeout in kube-proxy?.
Use NodeLocal DNSCache
In some scenarios, CoreDNS may encounter these issues:
-
Concurrent A and AAAA queries may rarely cause packet loss and DNS resolution failures.
-
Full conntrack tables on nodes may cause packet loss and DNS resolution failures.
Install the NodeLocal DNSCache add-on to improve DNS stability and performance. It runs a DNS cache on each node. See Use the NodeLocal DNSCache component for deployment in ACK clusters.
After you install NodeLocal DNSCache, inject the DNS cache configuration into your pods. Label a namespace to auto-inject DNS cache configuration into new pods:
kubectl label namespace default node-local-dns-injection=enabled
Use an appropriate CoreDNS version
CoreDNS maintains good backward compatibility across Kubernetes versions. Keep CoreDNS at a recent, stable version. The Component Management page in the ACK console provides install, upgrade, and configuration features. Monitor component status and upgrade CoreDNS during off-peak hours when an update is available.
-
See Automatic upgrade for non-managed CoreDNS for upgrade instructions.
-
See CoreDNS release notes.
CoreDNS versions earlier than v1.7.0 have known risks, including but not limited to:
-
If connectivity between CoreDNS and the API server fails during an API server restart, migration, or network jitter, CoreDNS may restart because it fails to write error logs. See Set klog's logtostderr flag.
-
CoreDNS consumes extra memory during startup. The default memory limit may trigger out-of-memory (OOM) issues in large clusters, causing CoreDNS pods to repeatedly restart without recovery. See CoreDNS uses a lot of memory during initialization phase.
-
CoreDNS has known issues affecting Headless Service domains and external domain resolution. See plugin/kubernetes: handle tombstones in default processor and Data is not synced when CoreDNS reconnects to kubernetes api server after protracted disconnection.
-
If a node is abnormal, outdated CoreDNS versions may deploy pods on the abnormal node due to default toleration policies. These pods may not auto-evict, causing domain resolution failures.
The recommended minimum CoreDNS version depends on the Kubernetes cluster version:
|
Cluster version |
Recommended minimum CoreDNS version |
|
Below 1.14.8 |
v1.6.2 (no longer maintained) |
|
1.14.8 and later, below 1.20.4 |
v1.7.0.0-f59c03d-aliyun |
|
1.20.4 and later, below 1.21.0 |
v1.8.4.1-3a376cc-aliyun |
|
1.21.0 and later |
v1.11.3.2-f57ea7ed6-aliyun |
Monitor CoreDNS runtime status
Monitoring metrics
CoreDNS exposes health metrics such as resolution results through a standard Prometheus interface to help detect anomalies in CoreDNS or upstream DNS servers.
Prometheus for ACK includes built-in CoreDNS monitoring metrics and alerting rules. Enable Prometheus and Dashboard in the Container Service for Kubernetes console. See CoreDNS component monitoring.
With a self-managed Prometheus instance, observe relevant metrics and set alerts for critical ones. See the official CoreDNS Prometheus documentation.
Operational logs
Use CoreDNS logs to diagnose root causes when DNS anomalies occur. Enable domain resolution logs and SLS log collection. See Analyze and monitor CoreDNS logs.
Kubernetes event delivery
In CoreDNS v1.9.3.6-32932850-aliyun and later, enable the k8s_event plugin to deliver critical CoreDNS logs as Kubernetes events to the Event Hub. See the k8s_event plugin documentation.
Newly deployed CoreDNS instances have this feature enabled by default. When upgrading from an older version, manually modify the configuration file to enable it.
-
Open the CoreDNS configuration file:
kubectl -n kube-system edit configmap/coredns -
Add the kubeAPI and k8s_event plugins.
apiVersion: v1 data: Corefile: | .:53 { errors health { lameduck 15s } // Begin addition (ignore other differences). kubeapi k8s_event { level info error warning // Deliver critical logs with info, error, or warning levels. } // End addition. kubernetes cluster.local in-addr.arpa ip6.arpa { pods verified fallthrough in-addr.arpa ip6.arpa } // Omitted below. } -
Check the CoreDNS pod status and logs. If the logs contain the word
reload, the modification is successful.
Ensure CoreDNS high availability
CoreDNS is the authoritative DNS for the cluster. A CoreDNS failure can disrupt internal Service access and large portions of your business. Ensure CoreDNS high availability with these measures:
Assess CoreDNS component pressure
Run DNS stress tests to evaluate CoreDNS add-on pressure. Open-source tools such as DNSPerf can help. If you cannot accurately assess DNS pressure, follow these recommendations:
-
Deploy at least two CoreDNS pods, each with resource limits of at least 1 CPU core and 1 GB of memory.
-
CoreDNS QPS capacity correlates with CPU usage. With NodeLocal DNSCache, each CPU core supports more than 10,000 QPS. Business workload DNS QPS varies significantly. Monitor peak CPU usage per CoreDNS pod and scale out replicas when usage exceeds one core during peak periods. If peak usage is unknown, deploy one CoreDNS pod per eight cluster nodes as a conservative measure.
Adjust the number of CoreDNS pods
The number of CoreDNS pods directly determines available compute resources. Adjust based on your assessment.
Because UDP lacks retransmission, CoreDNS pod scale-in or restart may cause cluster-wide DNS resolution timeouts lasting up to five minutes if IPVS UDP defects exist on cluster nodes. See Troubleshoot DNS resolution anomalies for IPVS-related solutions.
-
Automatically adjust the number of pods based on recommended policies
Deploy the following
dns-autoscaler. It adjusts CoreDNS pod count in real time at a ratio of one pod per eight cluster nodes. Replica count: `replicas = max(ceil(cores × 1/coresPerReplica), ceil(nodes × 1/nodesPerReplica))`, constrained bymaxandminlimits. -
Manual adjustments
Manually adjust CoreDNS pod count:
kubectl scale --replicas={target} deployment/coredns -n kube-system # Replace {target} with the desired pod count -
Do not use workload autoscaling
Workload autoscaling mechanisms such as horizontal pod autoscaling (HPA) or CronHPA trigger frequent scaling operations. Due to resolution anomalies during pod scale-in, do not use workload autoscaling for CoreDNS pods.
Adjust CoreDNS pod specifications
Modify pod specifications to adjust CoreDNS resources. In ACK managed clusters Pro, CoreDNS pods have a default memory limit of 2Gi and no CPU limit. Set the CPU limit to 4096m, with a minimum of 1024m. Adjust CoreDNS pod configuration in the console.
Schedule CoreDNS pods
Incorrect scheduling configurations may prevent CoreDNS pod deployment and cause CoreDNS to fail. Fully understand scheduling before proceeding.
Deploy CoreDNS pods across zones and nodes to avoid single-node or single-zone failures. CoreDNS versions earlier than v1.8.4.3 use weak node anti-affinity by default, which may place all pods on the same node when resources are insufficient. Delete pods to trigger rescheduling or upgrade to the latest component version. CoreDNS versions earlier than v1.8 are no longer maintained. Upgrade as soon as possible.
Avoid deploying CoreDNS on nodes with full CPU or memory utilization, which affects DNS QPS and response latency. Use custom parameters to schedule CoreDNS on dedicated nodes for stable domain name resolution.
Optimize CoreDNS configuration
Container Service for Kubernetes (ACK) provides only default CoreDNS configurations. Review all parameters and optimize them for your application containers. CoreDNS configuration is highly flexible. See DNS policy configuration and domain name resolution and the official CoreDNS documentation.
Default CoreDNS configurations from older Kubernetes versions may have risks. Check and optimize them as follows:
Use scheduled inspection and fault diagnosis in Container Intelligence Operations to check CoreDNS configuration files. If Container Intelligence Operations reports CoreDNS ConfigMap anomalies, review the items above.
CoreDNS may consume extra memory when reloading configurations. After modifying configuration items, monitor pod status. If pods experience memory shortages, increase the memory limit in the CoreDNS Deployment. Set memory to 2 GB.
Disable affinity settings for kube-dns service
Affinity settings may cause significant load imbalances among CoreDNS replicas. Disable them using one of these methods:
Console method
Log on to the ACK console. In the left navigation pane, click Clusters.
On the Clusters page, click the name of your cluster. In the left navigation pane, click .
-
In the kube-system namespace, click Edit YAML to the right of the kube-dns service.
-
If sessionAffinity is
None, skip the remaining steps. -
If sessionAffinity is
ClientIP, continue with the remaining steps.
-
-
Delete the sessionAffinity and sessionAffinityConfig fields and all their subkeys. Then, click Update.
# Delete all the following content. sessionAffinity: ClientIP sessionAffinityConfig: clientIP: timeoutSeconds: 10800 -
Click Edit YAML again for the kube-dns service and verify sessionAffinity is
None. If so, the kube-dns service update succeeded.
Command-line method
-
View the kube-dns service configuration:
kubectl -n kube-system get svc kube-dns -o yaml-
If sessionAffinity is
None, skip the remaining steps. -
If sessionAffinity is
ClientIP, continue with the remaining steps.
-
-
Open and edit the kube-dns service:
kubectl -n kube-system edit service kube-dns -
Delete all sessionAffinity-related settings (sessionAffinity, sessionAffinityConfig, and all subkeys). Then, save the change and exit.
# Delete all the following content. sessionAffinity: ClientIP sessionAffinityConfig: clientIP: timeoutSeconds: 10800 -
After modification, verify sessionAffinity is
None. If so, the kube-dns service update succeeded.kubectl -n kube-system get svc kube-dns -o yaml
Disable the Autopath plugin
Some older CoreDNS versions have the Autopath plugin enabled, which may produce incorrect resolution results in extreme scenarios. Verify whether the plugin is enabled and disable it by editing the configuration file. See Autopath.
After you disable the Autopath plugin, client-side DNS query QPS may increase up to three times, and single-domain resolution time may increase up to three times. Monitor CoreDNS load and business impact.
-
Open the CoreDNS configuration file with
kubectl -n kube-system edit configmap coredns. -
Delete the
autopath @kubernetesline and save the change. -
Check the CoreDNS pod status and logs. If the logs contain the word
reload, the modification is successful.
Configure graceful shutdown for CoreDNS
The lameduck mechanism in CoreDNS enables graceful shutdown. When CoreDNS stops or restarts, ongoing requests complete normally instead of being abruptly interrupted. The lameduck mechanism works as follows:
-
When CoreDNS terminates, it enters Lameduck mode.
-
In
lameduckmode, CoreDNS stops accepting new requests but continues processing existing requests until they complete or thelameducktimeout expires.
Console method
Log on to the ACK console. In the left navigation pane, click Clusters.
On the Clusters page, click the name of your cluster. In the left navigation pane, click .
-
In the kube-system namespace, click Edit YAML to the right of the coredns configuration item.
-
Ensure the health plugin is enabled and set the lameduck timeout to
15sper the following configuration. Then, click OK.
.:53 {
errors
# The health plugin may have different default settings in various CoreDNS versions.
# Case 1: health plugin disabled by default.
# Case 2: health plugin enabled by default but lameduck time not set.
# health
# Case 3: health plugin enabled by default with lameduck time set to 5s.
# health {
# lameduck 5s
# }
# For all three cases, modify uniformly as follows to set lameduck to 15s.
health {
lameduck 15s
}
# Do not modify other plugins; omitted here.
}
If CoreDNS pods run normally, the graceful shutdown configuration is updated. If pods become abnormal, check pod events and logs to identify the cause.
Command-line method
-
Open the CoreDNS configuration file:
-
Ensure the
healthplugin is enabled and set lameduck to15sper the following Corefile: -
Save and exit after modifying the CoreDNS configuration file.
-
If CoreDNS runs normally, the graceful shutdown configuration is updated. If pods become abnormal, check pod events and logs to identify the cause.
kubectl -n kube-system edit configmap/coredns
.:53 {
errors
# The health plugin may have different default settings in various CoreDNS versions.
# Case 1: health plugin disabled by default.
# Case 2: health plugin enabled by default but lameduck time not set.
# health
# Case 3: health plugin enabled by default with lameduck time set to 5s.
# health {
# lameduck 5s
# }
# For all three cases, modify uniformly as follows to set lameduck to 15s.
health {
lameduck 15s
}
# Do not modify other plugins; omitted here.
}
Set the default protocol for the Forward plugin to communicate with upstream VPC DNS servers
NodeLocal DNSCache communicates with CoreDNS using TCP. CoreDNS uses the same protocol as incoming requests when communicating with upstream DNS servers. By default, external domain resolution requests from application containers pass through NodeLocal DNSCache and CoreDNS, then reach VPC DNS servers (100.100.2.136 and 100.100.2.138) over TCP.
VPC DNS servers have limited TCP support. With NodeLocal DNSCache, modify the CoreDNS configuration to prefer UDP for upstream DNS communication and avoid resolution anomalies. Modify the coredns ConfigMap in the kube-system namespace. See Manage ConfigMaps. In the forward plugin, specify prefer_udp as the upstream protocol. After this change, CoreDNS prefers UDP for upstream communication:
# Before modification
forward . /etc/resolv.conf
# After modification
forward . /etc/resolv.conf {
prefer_udp
}
Configure the Ready readiness probe plugin
CoreDNS versions later than 1.5.0 require the ready plugin to enable readiness probes.
-
Open the CoreDNS configuration file:
kubectl -n kube-system edit configmap/coredns -
Check for the
readyline. If it is missing, addready. Press Esc, type:wq!, and then press Enter to save the change and exit.apiVersion: v1 data: Corefile: | .:53 { errors health { lameduck 15s } ready # Add this line if missing, ensuring consistent indentation with Kubernetes. kubernetes cluster.local in-addr.arpa ip6.arpa { pods verified fallthrough in-addr.arpa ip6.arpa } prometheus :9153 forward . /etc/resolv.conf { max_concurrent 1000 prefer_udp } cache 30 loop log reload loadbalance } -
Check the CoreDNS pod status and logs. If the logs contain the word
reload, the modification is successful.
Configure the multisocket plugin to enhance CoreDNS resolution performance
CoreDNS v1.12.1 introduced the multisocket plugin. When enabled, CoreDNS uses multiple sockets to listen on the same port, enhancing performance in high-CPU scenarios. See the community documentation.
Enable multisocket in the coredns ConfigMap:
.:53 {
...
prometheus :9153
multisocket [NUM_SOCKETS]
forward . /etc/resolv.conf
...
}
NUM_SOCKETS specifies the number of sockets that listen on the same port.
Align NUM_SOCKETS with estimated CPU usage, CPU resource limits, and available cluster resources. For example:
-
If CoreDNS consumes 4 cores at its peak and 8 cores are available, set
NUM_SOCKETSto 2. -
If CoreDNS consumes 8 cores at its peak and 64 cores are available, set
NUM_SOCKETSto 8.
Test different settings and measure QPS and load to determine the optimal configuration.
If you do not specify NUM_SOCKETS, CoreDNS uses GOMAXPROCS by default, which equals the CoreDNS pod CPU limit or the node CPU core count when no limit is set.