All Products
Search
Document Center

Container Service for Kubernetes:Deploy stable, high-performance unmanaged CoreDNS

Last Updated:Jun 17, 2026

Configure pod count, resources, scheduling, and node isolation to prevent CoreDNS outages in unmanaged mode.

In unmanaged mode, CoreDNS availability and performance depend on pod count, resource limits, scheduling, and node distribution. Default settings suit small clusters; production workloads require tuning.

Potential impacts

Misconfigured or under-resourced CoreDNS leads to two categories of problems:

  • Availability: incorrect scheduling creates node- or zone-level single points of failure. Insufficient resources cause pod eviction and DNS outages.

  • Performance: resource contention on shared nodes increases response latency. High node load causes I/O packet loss and DNS request failures.

Adjust CoreDNS pod count

Important

Because UDP lacks retransmission, scaling in or restarting CoreDNS — especially when IPVS defects cause packet loss — can trigger cluster-wide DNS resolution timeouts or failures lasting up to five minutes. See Troubleshooting DNS resolution issues.

Important

Do not use horizontal pod autoscaling (HPA) or CronHPA for CoreDNS. Frequent scale-in causes resolution failures.

Assess DNS pressure

Before adjusting replica count, assess DNS pressure. Tools such as DNSPerf can measure DNS load.

If you cannot measure DNS pressure directly, use these guidelines:

  • Run at least 2 CoreDNS pods with resource limits of at least 1 core and 1 GB memory.

  • DNS resolution QPS scales linearly with CPU consumption. With NodeLocal DNSCache, each CPU core handles over 10,000 queries per second (QPS). Different workloads have widely varying QPS needs, so monitor the peak CPU usage of each CoreDNS pod; if any pod exceeds one core during business peak hours, scale out the replicas.

  • Without load data, start with 1 pod per 8 nodes as a baseline.

Note

Scaling out only helps when nodes have sufficient resources. If nodes are low on memory, add nodes or increase per-node resources instead.

Once you know your target replica count, use automatic adjustment (recommended) or scale manually.

Configure automatic adjustment (recommended)

The cluster-proportional-autoscaler adjusts CoreDNS replicas based on cluster size. Unlike HPA, it does not rely on CPU metrics or perform disruptive scale-in. Default ratio: 1 pod per 8 nodes.

Replica count formula: replicas = max(ceil(cores × 1/coresPerReplica), ceil(nodes × 1/nodesPerReplica)). The min and max parameters cap the count at 2–100.

Deploy the 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

Scale manually

To set a specific replica count:

kubectl scale --replicas=<target> deployment/coredns -n kube-system # Replace <target> with the target number of pods.

Adjust CoreDNS pod specifications

In an ACK Pro cluster, the default CoreDNS pod configuration is:

Resource Default limit
CPU No limit
Memory 2 GiB

Set the CPU limit to 4096m (minimum 1024m) based on your observed peak usage.

Important

Changing CoreDNS pod specifications restarts pods, which may cause brief DNS latency spikes or failures. Perform this during off-peak hours.

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

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

  3. On the Networking tab, find CoreDNS and click Configuration.

    image

  4. Modify the CoreDNS configuration and click OK.

    image

Deploy on a dedicated node pool

A dedicated node pool isolates CoreDNS from other workloads and prevents resource contention.

Important

Rescheduling CoreDNS pods restarts them, which may cause brief DNS latency spikes or failures. Perform this during off-peak hours.

Create a dedicated node pool

When creating the node pool, follow these guidelines:

  • CoreDNS is network-intensive, not compute-intensive. Use network-enhanced instances with a recommended size of 4 cores and 8 GB memory.

  • The node pool must have at least 2 nodes, since CoreDNS runs 2 pods by default.

  • Add a taint and label to prevent other pods from running on these nodes. For example, use system-addon: system-addon as both the taint key-value pair and label, with Effect set to NoSchedule.

See Create and manage node pools.

Schedule CoreDNS pods to the node pool

  1. On the Add-ons page, find the CoreDNS card and click Configuration.

  2. In the NodeSelector section, add the label of the dedicated node pool.

    Do not delete existing NodeSelector labels.

    image.png

  3. In the Tolerations section, add a toleration that matches the node pool's taint.

    image.png

  4. Click OK, then verify that CoreDNS pods are running on the dedicated nodes:

    kubectl -n kube-system get pod -o wide --show-labels | grep coredns

Use scheduling policies for high availability

To protect DNS availability, CoreDNS uses two scheduling policies by default:

  • Pod anti-affinity (node-level): prevents two CoreDNS pods from running on the same node. If a node fails, DNS remains available on other nodes.

  • Topology-aware scheduling (zone-level): distributes CoreDNS pods across availability zones, preventing zone-level single points of failure that pod anti-affinity alone cannot address.

Important

These policies apply only during initial scheduling. If node or zone configurations change, find the coredns Deployment in the ACK console and click Redeploy.

Pod anti-affinity

CoreDNS uses a requiredDuringSchedulingIgnoredDuringExecution anti-affinity rule to prevent two CoreDNS pods from sharing a node. This requires at least 2 nodes with sufficient resources, excluding:

  • k8s.aliyun.com: true — nodes with node autoscaling enabled

  • type: virtual-kubelet — virtual nodes

  • alibabacloud.com/lingjun-worker: true — Lingjun nodes

The default affinity configuration is:

      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              # virtual nodes have this label
              - key: type
                operator: NotIn
                values:
                - virtual-kubelet
              # lingjun worker nodes have this label
              - key: alibabacloud.com/lingjun-worker
                operator: NotIn
                values:
                - "true"
          preferredDuringSchedulingIgnoredDuringExecution:
          - preference:
              matchExpressions:
              # autoscaled nodes have this label
              - key: k8s.aliyun.com
                operator: NotIn
                values:
                - "true"
            weight: 100
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: k8s-app
                operator: In
                values:
                - kube-dns
            topologyKey: kubernetes.io/hostname

Topology-aware scheduling

By default, CoreDNS uses topology-aware scheduling to spread pods across zones. The whenUnsatisfiable: DoNotSchedule setting enforces this — pods won't be scheduled if the zone balance condition can't be met.

For this to work reliably:

  • Your cluster must have nodes in at least 2 different zones, each with at least 1 node that has sufficient resources for CoreDNS.

  • All nodes must have the topology.kubernetes.io/zone label (applied by default). Missing or inconsistent labels cause scheduling failures or uneven distribution.

  • Upgrade your cluster to v1.27 or later and CoreDNS to v1.12.1.3 or later. Earlier cluster versions do not support matchLabelKeys, so a CoreDNS rolling update may end with pods unevenly distributed across zones and may even leave some zones uncovered. See the matchLabelKeys configuration described below.

CoreDNS versions earlier than v1.12.1.3 use this topology spread constraint:

topologySpreadConstraints:
- labelSelector:
    matchLabels:
      k8s-app: kube-dns
  maxSkew: 1
  topologyKey: topology.kubernetes.io/zone
  whenUnsatisfiable: DoNotSchedule
Important

The pod count difference between any two zones cannot exceed maxSkew (default 1). The labelSelector counts pods from both new and old ReplicaSets, so to satisfy maxSkew=1, the scheduler favors zones with fewer total pods. After old pods terminate, new pods may concentrate in a few zones.

CoreDNS v1.12.1.3 and later fixes this with matchLabelKeys (Kubernetes v1.27+):

topologySpreadConstraints:
- labelSelector:
    matchLabels:
      k8s-app: kube-dns
  matchLabelKeys:
  - pod-template-hash
  nodeTaintsPolicy: Honor
  maxSkew: 1
  topologyKey: topology.kubernetes.io/zone
  whenUnsatisfiable: DoNotSchedule

Adding matchLabelKeys: [pod-template-hash] scopes the constraint to the current ReplicaSet, so rolling updates distribute pods evenly across zones.