Skip to content

DNS resolution broken on IPv6-only clusters with Docker: enable_network_magic() is IPv4-only #4152

Description

@matejvasek

Title: DNS resolution broken on IPv6-only clusters with Docker: enable_network_magic() is IPv4-only

What happened:

On an IPv6-only cluster (ipFamily: ipv6) running on Docker, CoreDNS pods cannot resolve external names. The node's /etc/resolv.conf contains nameserver 172.18.0.1 (the IPv4 default gateway), which is unreachable from IPv6-only pods. CoreDNS logs show:

[ERROR] plugin/errors: 2 ghcr.io. AAAA: read udp [fd00:10:244::43]:59624->[172.18.0.1]:53: connect: network is unreachable

The root cause is in enable_network_magic() in the node entrypoint script. It replaces Docker's embedded DNS (127.0.0.11) with the IPv4 default gateway:

docker_host_ip=$(ip -4 route show default | cut -d' ' -f3)

This is hardcoded to IPv4. On an IPv6-only cluster, the resulting nameserver (172.18.0.1) is unreachable from pods that only have IPv6 addresses.

Note: even if the entrypoint used ip -6 route show default to get the IPv6 gateway (fc00:f853:ccd:e793::1), DNS still wouldn't work because Docker's DNS proxy does not listen on the IPv6 bridge gateway address (see moby/moby#41651). So the entrypoint fix alone is not sufficient — but it is a prerequisite for any future Docker fix to work.

What you expected to happen:

CoreDNS pods on an IPv6-only cluster should be able to forward DNS queries to an upstream resolver. The entrypoint should configure at least one IPv6-reachable nameserver in /etc/resolv.conf when the cluster uses ipFamily: ipv6.

How to reproduce it (as minimally and precisely as possible):

cat <<EOF | kind create cluster --name test --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
  ipFamily: ipv6
EOF

# Check resolv.conf — only has IPv4 nameserver
docker exec test-control-plane cat /etc/resolv.conf
# nameserver 172.18.0.1

# The original Docker resolv.conf had 127.0.0.11
docker exec test-control-plane cat /etc/resolv.conf.original
# nameserver 127.0.0.11

# CoreDNS pods can't reach the IPv4 nameserver — verify from a debug pod
kubectl run -it --rm debug --image=alpine --restart=Never -- nslookup google.com
# ;; connection timed out; no servers could be reached

kind delete cluster --name test

Anything else we need to know?:

The entrypoint's enable_network_magic() function is entirely IPv4-centric:

  • Uses ip -4 route show default to find the host IP
  • Only patches iptables (not ip6tables)
  • Only resolves host.docker.internal via getent ahostsv4

On Podman this works by accident: Podman's aardvark-dns puts its own IPv6 nameserver in /etc/resolv.conf (not 127.0.0.11), so the sed replacement is a no-op and the working IPv6 nameserver survives.

There is also a Docker-side issue: Docker's DNS proxy only listens on the IPv4 bridge gateway, not the IPv6 one (moby/moby#41651, open since 2020). Even if kind fixed the entrypoint to use the IPv6 gateway, there's currently nothing listening on port 53 there. A complete fix requires both kind and Docker changes.

As a workaround, running a socat DNS proxy on the node bridges the gap:

# Get the node's IPv6 address
NODE_IPV6=$(docker inspect test-control-plane -f '{{.NetworkSettings.Networks.kind.GlobalIPv6Address}}')

# Install socat and start DNS proxies (UDP + TCP)
docker exec test-control-plane bash -c "
  apt-get update -qq >/dev/null 2>&1 && apt-get install -y -qq socat >/dev/null 2>&1
  socat UDP6-LISTEN:53,bind=[${NODE_IPV6}],fork,reuseaddr UDP4:172.18.0.1:53 &
  socat TCP6-LISTEN:53,bind=[${NODE_IPV6}],fork,reuseaddr TCP4:172.18.0.1:53 &
"

# Patch CoreDNS to forward to the node's IPv6 address instead of /etc/resolv.conf
kubectl get cm coredns -n kube-system -o json \
  | sed "s|forward . /etc/resolv.conf|forward . ${NODE_IPV6}|" \
  | kubectl apply -f -
kubectl rollout restart deployment/coredns -n kube-system

Environment:

  • kind version: v0.31.0 (also reproduced with v0.29.0)
  • Runtime info: Docker 29.3.0
  • Kubernetes version: v1.34.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugCategorizes issue or PR as related to a bug.kind/featureCategorizes issue or PR as related to a new feature.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions