containers/aardvark-dns

Possible to get out of the box (rootful) host-to-container name resolution?

lovette opened this issue · 10 comments

Is this a BUG REPORT or FEATURE REQUEST? (leave only one on its own line)

/kind feature

Description

I'm curious whether the new Podman 4 network stack components can be leveraged to enable (rootful) host-to-container/pod name resolution.

Most of my projects are rootful and single host (and run at boot by systemd), so being able to resolve the name to an IP as soon as the container starts would be so helpful.

I'm dreaming of:

% sudo podman run --detach --name myredis redis
% ping myredis
PING 10.88.0.25 (10.88.0.25) 56(84) bytes of data.
64 bytes from 10.88.0.25: icmp_seq=1 ttl=64 time=0.066 ms

or:

% sudo podman pod create --name mypod
% sudo podman run --detach --name myredis --pod mypod redis
% ping mypod
PING 10.88.0.25 (10.88.0.25) 56(84) bytes of data.
64 bytes from 10.88.0.25: icmp_seq=1 ttl=64 time=0.066 ms

Currently I achieve this by creating a custom network and using --ip to assign each pod/container a static IP that I add to /etc/hosts.

% sudo podman container inspect -f "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}\t{{.Name}}" myredis >> /etc/hosts

Perhaps this functionality is venturing into the world of "service discovery" so I may be asking too much of podman. But since most of my projects are single host and have simple needs, expanding my footprint to include minikube/k3s/etc. feels like overkill.

baude commented

Interesting notion. Just some initial thoughts. With aardvark-dns, we were careful to enforce name lookups based on network connectivity and to not return an answer that the 'asker' about something they should not know about. So what happens here?

  1. would every user on the system see everyone's entries?
  2. would this only be for rootfull?
  3. would we have a --host-dns switch to enable it on the host
  4. how would we avoid collision with real dns services?

My understanding is ports on rootless containers are currently only addressable through the host IP, so there'd be no expectation of name resolution when rootless. When rootful, modifying /etc/hosts affects all users, so I'd say DNS host-to-pod name resolution would also be system wide.

I have casual knowledge of how name resolution works, but perhaps a --host-dns switch could add the container/pod name to aardvark-dns and then reference that daemon via loopback address in resolv.conf?

When I inquired today on Discord, @flouthoc replied they had a "first draft" operational. I'd be curious to hear more about that.

@lovette I believe the use case you have mentioned is possible to implement from what i can see from my side. There could be some edge-cases but we could think around it, one for sure is which @baude mentioned. I have possible answers for some of them.

  • how would we avoid collision with real dns services?: maybe we can enable forwarding in such case by default and not return NXDOMAIN for non-matching entries when case is --host-dns.
  • would every user on the system see everyone's entries?: yes following is only possible if host can see all entries.

I think we can still give this option but its up to the user to make sure that they set and use aardvark-dns as their resolver on host and aardvark-dns will do no changes on host by itself. So either user could do it manually or we have explicit option like --host-dns which updates host's /etc/resolv.conf.

Anyways I think all this have to be implemented on aardvark-dns side. So i believe we could move this issue to aardvark-dns.

@lovette But i'd also love to know what is your use-case with this ? Are you trying to implement k8s like services ?

The bigger problem is that aardvark will not be running if no containers with dns entries are up. So even if you add the server ip to /etc/resolv.conf it will not work when you boot for example until the podman containers are started. This is a problem when systemd-resolved is used on the host because it will skip all servers that are unreachable and not try them again until you restart systemd-resolved.

@Luap99 I think for systemd-resolvers it works if you recreate the symlink to /etc/resolv.conf or reload but in any case it would be hard to do for rootless users and like i mentioned before i think its best that user's themselves take ownership of configuring resolver.

I don't know if its a good idea for a tool to attempt modifying host's resolver by itself, it would be much easier if podman could just return an IP address of aardvark-dns and let users do the rest by themselves although tt would be a toll on UX though.

Maybe something like

  • podman aardvark-dns status <---- shows if aardvark is running or not
  • podman aardvark-dns get-ip --host-dns <---- gives a ip address which users can use on their host

We should not expose this in podman. This makes it more complicated with almost no extra benefit.
If someone wants to use aardvark from the host this is fine but I do not think aardvark should be used as main resolver on the host. You can always run dig @bridgeip myname.

Also we want to change the port from 53 to something different, so in this case it is impossible to use it as system resolver in /etc/resolv.conf.

Also we want to change the port from 53 to something different, so in this case it is impossible to use it as system resolver in /etc/resolv.conf.

Yes in future if we start listening on other port this might be an issue but we could always spawn an extra listener on :53 if --host-dns is set on podman. But still I would not be in favor of taking charge of host's /etc/resolv.conf it would be better if user does it by themselves.

But i'd also love to know what is your use-case with this ? Are you trying to implement k8s like services?

At its most basic, I'd just like to remove the manual act of assigning containers a static IP and adding to /etc/hosts.

(Another approach I've pondered is trying to find a "container just started/stopped" event that I could hook into and have a script munge /etc/hosts automatically.)

We should not expose this in podman.

It does seem this is more in the realm of aardvark than podman. I don't have a mental map of how podman, netavark and aardvark-dns work together. Any chance there's a writeup somewhere that explains how container networking works under the hood?

I don't mind a small bit of DNS configuration. AFAICT, my system isn't running any DNS daemons (systemd-resolved, dnsmasq.) Just whatever NetworkManager is doing.

% cat /etc/resolv.conf 
# Generated by NetworkManager
nameserver 1.1.1.1
nameserver 1.0.0.1
j0057 commented

I would like to run Unbound on the host as caching DNS forwarder, to resolve names under some subdomains at a specific resolver, for example resolvers reachable over Wireguard or AnyConnect VPNs. It would be pretty easy to make Unbound forward certain queries to a bridge IP where an instance of Aardvark is listening -- for this to work the only thing currently missing is to be able to make Aardvark authoritative for names in a specific specific subdomain, not unqualified names like it's doing right now.

The same is doable with Dnsmasq and I suppose systemd-networkd as well, though I haven't tested it.

j0057 commented

Update: I found out that Aardvark is serving names under the dns.podman. domain, this already makes it possible to forward requests for names in that domain from the system resolver to Aardvark.

What doesn't work though is that containers can be part of more than one network, and all of these networks are resolved under dns.podman. and the answer depends on which bridge IP is used to send the request:

# podman network create testnet1 --subnet 10.89.1.0/24
testnet1
# podman network create testnet2 --subnet 10.89.2.0/24
testnet2
# podman run --rm -it --name alpine --net testnet1 --net testnet2 docker.io/library/alpine:latest
...

In another terminal:

$ dig +short @10.89.1.1 alpine.dns.podman
10.89.1.2
$ dig +short @10.89.2.1 alpine.dns.podman
10.89.2.2

It would help if there also were names like alpine.testnet1.dns.podman and alpine.testnet2.dns.podman, and netavark then always responded with the address in that network. If netavark had a way to configure the dns.podman bit, you could even make it possible to resolve these names from other hosts in the network!