Skip to content

Instantly share code, notes, and snippets.

Last active June 12, 2020 02:16
Show Gist options
  • Save frimik/d54df89ed3fc9d5c75e5ad93d6353f37 to your computer and use it in GitHub Desktop.
Save frimik/d54df89ed3fc9d5c75e5ad93d6353f37 to your computer and use it in GitHub Desktop.
k3d ubuntu systemd-resolved DNS hacks

DNS Hack for Ubuntu

The problem

Going on and off VPN, things work, then they don't work... general annoying. Containers can't resolve... and when you might make containers resolve, then containers in containers (k3d) can't resolve...

It seems I got things working... I can go on and off VPN, name resolution works essentially the same on the Host as in Docker and the Kubernetes (k3d) nodes and the k3d kubernetes containers.

On the host I have per-interface DNS servers via systemd-resolved that takes care of it.

/etc/resolv.conf points to which is systemd-resolved. resolvectl status should show individual DNS servers per Link. Example tun0 (which may be your VPN interface) vs wlp2s0 (which may be your Wireless interface).

Patching k3d to take --dns parameter

First of all, I've patched k3d so I can start it with a --dns parameter. Same as docker run --dns.

So, I run it with k3d create --dns, essentially pointing it to my socat Dns Proxy (explained below).

All the steps and assumptions explained

  1. You have systemd-resolved listening on loopback:

    # sudo netstat -nlp | grep systemd-resol
    tcp        0      0 *               LISTEN      5021/systemd-resolv
    udp        0      0 *                           5021/systemd-resolv
  2. Your docker0 interface has an IP:

    # ip addr show docker0 | awk '$1 ~ /^inet$/ { print $2 }'
  3. Start an socat DNS proxy forwarding from the docker network to systemd-resolved:

    # export DOCKER_GATEWAY_IP=; hostname; echo "Proxying port 53 to systemd-resolved ..."; sudo socat -v UDP-LISTEN:53,fork,reuseaddr,bind=$DOCKER_GATEWAY_IP UDP:
    Proxying port 53 ...

    Note: A TCP proxy is also needed for full support, but we'll start with this.

  4. The Kubernetes (K3D/K3S) master node has an IP on the internal flannel network:

    # hostname; ip addr show cni0 | awk '$1 ~ /^inet$/ { print $2 }'
  5. Run socat on the Kubernetes master (... in Docker) node's flannel interface to proxy DNS to the embedded Docker dns server on address: The bind IP here is but you could make it which is usually the master node's flannel IP.

    docker exec -it k3d-k3s-default-server socat -v UDP-LISTEN:53,fork,reuseaddr,bind= UDP:
  6. Configure CoreDNS' ConfigMap to proxy to this new socat DaemonSet (or Service, however you want to set it up). In this case I point it to the Kubernetes master node flannel interface (cni0) IP:

    apiVersion: v1
      Corefile: |
        .:53 {
            kubernetes cluster.local {
              pods insecure
            prometheus :9153
            proxy .
            cache 30
    kind: ConfigMap
Copy link

YAMLcase commented Jun 12, 2020

See rancher/k3s#462 for CoreDNS customization options (if there are any...)

This looks like something I might try:
k3d-io/k3d#229 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment