All Products
Search
Document Center

Container Service for Kubernetes:DNS resolution and caching policies

Last Updated:Jun 17, 2026

ACK DNS queries flow through CoreDNS and NodeLocal DNSCache, with tunable parameters at each layer.

DNS resolution architectures

DNS resolution in ACK depends on where the application runs and whether NodeLocal DNSCache is active.

The timeout and attempts parameters in the diagrams are defined under Resolution policies and Caching policies.

Host-based applications (non-containerized)

Applications running directly on Elastic Compute Service (ECS) instances use the host's /etc/resolv.conf, which points to the Virtual Private Cloud (VPC) DNS servers.

DNS resolution flow 1

Standard containerized pods (dnsPolicy: ClusterFirst)

By default, pods use the ClusterFirst policy. All DNS queries go to the CoreDNS service within the cluster.

DNS resolution flow 2

Pods with NodeLocal DNSCache enabled

When NodeLocal DNSCache is active, pods send queries to a local caching agent on the same node. This provides two benefits:

  • Reduced latency: DNS queries resolve locally, skipping the network hop to CoreDNS.

  • Conntrack table protection: Queries use the local agent without creating conntrack entries, reducing conntrack races and preventing UDP DNS from exhausting the conntrack table.

DNS resolution flow 3

Resolution policies

Client side

These /etc/resolv.conf parameters are interpreted by the glibc resolver. Representative configuration for a ClusterFirst pod:

nameserver 10.x.x.x          # CoreDNS ClusterIP
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5 timeout:5 attempts:2

Default values across deployment environments:

Parameter

Description

Default value in glibc

ECS

Pod with DNSPolicy set to ClusterFirst

Pod with DNSPolicy set to Default

Pod that uses NodeLocal DNSCache

Pod with DNSPolicy set to Default and that uses the host network

nameserver

The DNS server used to resolve domain names.

None

VPC DNS servers

CoreDNS ClusterIP

VPC DNS servers

  • NodeLocal DNSCache IP

  • CoreDNS ClusterIP

VPC DNS servers

search

Non-FQDN domain names are appended with the search suffix to form an FQDN before resolution.

None

None

<ns>.svc.cluster.local svc.cluster.local cluster.local

None

<ns>.svc.cluster.local svc.cluster.local cluster.local

None

ndots:n

If a domain name contains more dots than the ndots value, it is resolved as an FQDN directly. Otherwise, the search suffix is appended before the query.

1

1

5

1

3

1

timeout:n

The timeout for a single DNS resolution request. Unit: seconds.

5

2

5

5

1

2

attempts:n

The maximum number of retries on resolution failure.

2

3

2

2

2

3

rotate

Queries DNS servers in a round-robin manner.

Disabled

Enabled

Disabled

Disabled

Disabled

Enabled

single-request-reopen

When enabled, the resolver reopens the socket between consecutive requests on the same socket.

Disabled

Enabled

Disabled

Disabled

Disabled

Enabled

^①^ The attempts parameter applies only when the server returns SERVFAIL, NOTIMP, or REFUSED, or returns NOERROR without a result. See Attempts parameter request details.

^②^ VPC DNS servers (100.100.2.136 and 100.100.2.138) are the default DNS servers on ECS instances. They resolve PrivateZone and authoritative domain names.

^③^ The CoreDNS ClusterIP is the kube-dns service IP in the kube-system namespace. It resolves internal service names and forwards PrivateZone and authoritative queries.

^④^ NodeLocal DNSCache listens on 169.254.20.10 on each node when the add-on is deployed.

See resolv.conf for additional /etc/resolv.conf options.

Non-standard resolvers

The glibc defaults above apply only when the container uses glibc. Two common exceptions:

  • Alpine (musl libc): Alpine's built-in musl library replaces glibc and behaves differently (see musl libc):

    • Does not honor single-request and single-request-reopen options in /etc/resolv.conf.

    • Alpine 3.3 and earlier do not support the search parameter or search domains, which breaks service discovery.

    • Concurrent requests to multiple DNS servers make NodeLocal DNSCache optimizations ineffective.

    • Concurrent A and AAAA requests on the same socket trigger conntrack race conditions on older kernels, causing intermittent packet loss.

  • Languages with built-in resolvers (Go, Node.js): These runtimes often bypass /etc/resolv.conf and resolve differently from the system resolver.

In-cluster DNS servers

By default, CoreDNS reads its upstream from the ECS /etc/resolv.conf and forwards DNS requests with the built-in forward plugin. NodeLocal DNSCache runs an embedded CoreDNS instance with the same forwarding configuration.

Parameters for the forward plugin (full reference):

Parameter

Description

CoreDNS default value

NodeLocal DNSCache default value

prefer_udp

Uses UDP to communicate with the upstream server when possible.

Enabled

Disabled

force_tcp

Forces TCP for all upstream communication.

Disabled

Enabled

max_fails

Consecutive health check failures before an upstream server is marked unhealthy.

2

2

expire

How long to keep the connection to the upstream server open.

10s

10s

policy

The policy for selecting an upstream server.

random

random

health_check

The health check interval.

0.5s

0.5s

max_concurrent

The maximum number of concurrent upstream connections.

None

None

dial timeout

The timeout for connecting to the upstream server. Decreases dynamically based on actual connection time.

30s

30s

read timeout

The timeout for receiving data from the upstream server.

2s

2s

Caching policies

Client side

Client-side caching varies by container image and application.

In-cluster DNS servers

Cache parameters for CoreDNS and NodeLocal DNSCache in ACK:

Parameter

Description

CoreDNS community default

NodeLocal DNSCache ACK default

CoreDNS ACK default

success Max TTL

The maximum time-to-live (TTL) for cached successful results.

3600s

30s

30s

success Min TTL

The minimum TTL for cached successful results.

5s

5s

5s

success Capacity

The number of successful results to cache.

9984

9984

9984

denial Max TTL

The maximum TTL for cached failed results.

1800s

5s

30s

denial Min TTL

The minimum TTL for cached failed results.

5s

5s

5s

denial Capacity

The number of failed results to cache.

9984

9984

9984

ServerError TTL

The TTL when the upstream server is unavailable.

5s

0s (default is 5s for NodeLocal DNSCache Helm Chart versions earlier than 1.5.0)

0s (default is 5s for CoreDNS versions earlier than 1.8.4.2)

serve_stale

Allows CoreDNS to serve expired cache entries when the upstream is unreachable.

Disabled

Enabled (disabled by default for NodeLocal DNSCache Helm Chart versions earlier than 1.5.0)

Enabled (disabled by default for CoreDNS versions earlier than 1.12.1)

Note

Effective TTL is determined by the result TTL, Max TTL, and Min TTL:

  • If Result TTL > Max TTL, the effective TTL is the Max TTL.

  • If Result TTL < Min TTL, the effective TTL is the Min TTL.

  • If Min TTL ≤ Result TTL ≤ Max TTL, the effective TTL is the Result TTL.

Optimization suggestions

Adjust DNS behavior by editing the pod YAML, CoreDNS ConfigMap, or NodeLocal DNSCache ConfigMap.

Enhance fault tolerance

With dnsPolicy: Default, the container inherits VPC DNS server settings from the ECS /etc/resolv.conf but not the rotate, single-request-reopen, timeout:2, and attempts:3 options. Without these, network jitter can cause intermittent DNS failures.

Inherited configuration:

apiVersion: v1
kind: Pod
metadata:
  name: example
  namespace: default
spec:
  containers:
  - image: registry.cn-hangzhou.aliyuncs.com/example-ns/example:v1
    name: example
  # The dnsPolicy value in the Pod YAML is Default.
  dnsPolicy: Default

# The /etc/resolv.conf file in the container at this time.
# cat /etc/resolv.conf
nameserver 100.100.2.136
nameserver 100.100.2.138

Add dnsConfig to restore the missing fault-tolerance options:

apiVersion: v1
kind: Pod
metadata:
  name: example
  namespace: default
spec:
  containers:
  - image: registry.cn-hangzhou.aliyuncs.com/example-ns/example:v1
    name: example
  # The dnsPolicy value in the pod YAML is Default.
  dnsPolicy: Default
  # Add the following fault tolerance configuration.
  dnsConfig:
    options:
    - name: timeout
      value: "2"
    - name: attempts
      value: "3"
    - name: rotate
    - name: single-request-reopen

# After modification, redeploy the pod. The options parameter is added to /etc/resolv.conf in the container.
# cat /etc/resolv.conf
nameserver 100.100.2.136
nameserver 100.100.2.138
options rotate single-request-reopen timeout:2 attempts:3

High availability with serve_stale

serve_stale lets CoreDNS return expired cache entries when upstream DNS servers are unreachable, preventing resolution failures from transient outages.

serve_stale is enabled by default in CoreDNS unmanaged edition v1.12.1 and later. See RFC-8767.

Configuration format

serve_stale [DURATION] [REFRESH_MODE]
  • DURATION: How long expired entries remain servable after expiry. Default: 1h. Entries expired longer than this without a successful refresh are no longer served.

  • REFRESH_MODE: Controls how CoreDNS handles expired entries:

    • verify: Checks upstream reachability first, returns the fresh entry if available, or falls back to the expired entry. Higher latency on stale responses but avoids serving outdated data when fresh data exists.

    • immediate: Returns the expired entry immediately and refreshes from upstream in the background. Faster but may serve stale data.

Example

Default configuration in CoreDNS unmanaged edition v1.12.1.2 and later:

cache 30 {
  ...
  serve_stale 30s verify
}
Important

Default configuration for CoreDNS unmanaged edition v1.12.1.1-4035d7a99-aliyun:

cache 30 {
  ...
  serve_stale 1h immediate
}

With serve_stale 1h immediate, in extreme scenarios — such as DNS resolution during an iterative headless service update — CoreDNS may return an expired entry. If this occurs frequently, switch to verify.