All Products
Search
Document Center

Container Service for Kubernetes:Best practices for DNS in Kubernetes clusters

Last Updated:Jun 24, 2026

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:

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>, where service-name is the Service name.

    • For cross-namespace Service access, use <service-name>.<namespace-name>, where namespace-name is the Service namespace.

    • For external domains, use fully qualified domain names (FQDNs). Append a trailing dot (.) to specify absolute addresses and avoid invalid search domain 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.local

        After 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.10

        A "." as the first search domain treats all domain requests as FQDNs and resolves them directly without unnecessary search attempts.

        Important

        Set dnsPolicy to None for this configuration to take effect.

        Complete workload example

        apiVersion: apps/v1
        kind: Deployment
        metadata:
          labels:
            app: nginx
          name: nginx
          namespace: default
        spec:
          progressDeadlineSeconds: 600
          replicas: 3
          revisionHistoryLimit: 10
          selector:
            matchLabels:
              app: nginx
          strategy:
            rollingUpdate:
              maxSurge: 25%
              maxUnavailable: 25%
            type: RollingUpdate
          template:
            metadata:
              labels:
                app: nginx
            spec:
              containers:
              - image: registry.openanolis.cn/openanolis/nginx:1.14.1-8.6
                imagePullPolicy: Always
                name: nginx
                resources: {}
                terminationMessagePath: /dev/termination-log
                terminationMessagePolicy: File
              dnsPolicy: None
              dnsConfig:
                nameservers: ["192.168.0.10"]  ## Replace 192.168.0.10 with the actual CoreDNS service clusterIP
                searches:
                - .
                - default.svc.cluster.local
                - svc.cluster.local
                - cluster.local
              hostname: nginx
              restartPolicy: Always
              schedulerName: default-scheduler
              securityContext: {}
              subdomain: subdomain
              terminationGracePeriodSeconds: 30

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:

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.

Important

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.

CoreDNS versions earlier than v1.7.0 have known risks, including but not limited to:

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.

  1. Open the CoreDNS configuration file:

    kubectl -n kube-system edit configmap/coredns
  2. 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.
        }
  3. 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.

Important

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 by max and min limits.

    dns-autoscaler

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: dns-autoscaler
      namespace: kube-system
      labels:
        k8s-app: dns-autoscaler
    spec:
      selector:
        matchLabels:
          k8s-app: dns-autoscaler
      template:
        metadata:
          labels:
            k8s-app: dns-autoscaler
        spec:
          serviceAccountName: admin
          containers:
          - name: autoscaler
            image: registry.cn-hangzhou.aliyuncs.com/acs/cluster-proportional-autoscaler:1.8.4
            resources:
              requests:
                cpu: "200m"
                memory: "150Mi"
            command:
            - /cluster-proportional-autoscaler
            - --namespace=kube-system
            - --configmap=dns-autoscaler
            - --nodelabels=type!=virtual-kubelet
            - --target=Deployment/coredns
            - --default-params={"linear":{"coresPerReplica":64,"nodesPerReplica":8,"min":2,"max":100,"preventSinglePointFailure":true}}
            - --logtostderr=true
            - --v=9
  • 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.

Modify the CoreDNS configuration in the console

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

  2. On the Clusters page, click the name of your cluster. In the left navigation pane, click Add-ons.

  3. Click the Network tab, find the CoreDNS card, and then click Configuration.

  4. Modify the CoreDNS settings and click OK.

    In the CoreDNS parameter configuration dialog box, set resource parameters such as MemoryRequest (for example, 100Mi), CpuRequest (for example, 100m), MemoryLimit (for example, 2Gi), and CpuLimit. Optionally set NodeSelector labels (for example, Key: kubernetes.io/os, Value: linux). Modifying these parameters regenerates the component template YAML and may overwrite kubectl changes.

Schedule CoreDNS pods

Important

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.

Deploy CoreDNS on dedicated nodes using custom parameters

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

  2. On the Clusters page, click the name of your cluster. In the left navigation pane, click Nodes > Nodes.

  3. On the Nodes page, click Manage Labels and Taints.

  4. On the Manage Labels and Taints page, select the target nodes and click Add Label.

    Note

    Select more nodes than CoreDNS replicas to avoid deploying multiple replicas on a single node.

  5. In the Add dialog box, set the following parameters and click OK.

    • Name: node-role-type

    • Value: coredns

  6. In the navigation pane on the left of the cluster management page, select Operations > Add-ons. Search for CoreDNS.

  7. On the CoreDNS card, click Configuration. In the Configuration dialog box, click + Add next to NodeSelector, set the following parameters, and then click OK.

    • Key: node-role-type

    • Value: coredns

    CoreDNS reschedules to nodes with the specified label.

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.

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.

Note

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

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

  2. On the Clusters page, click the name of your cluster. In the left navigation pane, click Network > Services.

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

  4. Delete the sessionAffinity and sessionAffinityConfig fields and all their subkeys. Then, click Update.

    # Delete all the following content.
    sessionAffinity: ClientIP
    sessionAffinityConfig:
      clientIP:
        timeoutSeconds: 10800
  5. 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

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

  2. Open and edit the kube-dns service:

    kubectl -n kube-system edit service kube-dns
  3. 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
  4. 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.

Note

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.

  1. Open the CoreDNS configuration file with kubectl -n kube-system edit configmap coredns.

  2. Delete the autopath @kubernetes line and save the change.

  3. 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 lameduck mode, CoreDNS stops accepting new requests but continues processing existing requests until they complete or the lameduck timeout expires.

Console method

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

  2. On the Clusters page, click the name of your cluster. In the left navigation pane, click Configurations > ConfigMaps.

  3. In the kube-system namespace, click Edit YAML to the right of the coredns configuration item.

  4. Ensure the health plugin is enabled and set the lameduck timeout to 15s per the following configuration. Then, click OK.

  5. .: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

  1. Open the CoreDNS configuration file:

  2. kubectl -n kube-system edit configmap/coredns
  3. Ensure the health plugin is enabled and set lameduck to 15s per the following Corefile:

  4. .: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.
        }
  5. Save and exit after modifying the CoreDNS configuration file.

  6. If CoreDNS runs normally, the graceful shutdown configuration is updated. If pods become abnormal, check pod events and logs to identify the cause.

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.

  1. Open the CoreDNS configuration file:

    kubectl -n kube-system edit configmap/coredns
  2. Check for the ready line. If it is missing, add ready. 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
      }
  3. 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_SOCKETS to 2.

  • If CoreDNS consumes 8 cores at its peak and 64 cores are available, set NUM_SOCKETS to 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.