Record what a container can see of the mesh's names, and what it cannot

Found by a container failing to resolve a name every machine could: a container
gets its own hosts file holding only its own hostname, and on the machine it
always worked, which is what made it easy to miss.

Declared containers are given the names. A container somebody starts by hand is
not the mesh's to configure — which is a second, different reason to want a
resolver, recorded beside the first rather than folded into it.
This commit is contained in:
2026-08-31 11:29:25 +02:00
parent 35ce23fb76
commit a3cee17d48
+35
View File
@@ -250,6 +250,41 @@ name and overlay address.
database before its own DNS existed; with [ADR 0004](../../02-DECISIONS/0004-a-node-and-how-it-joins.md)
nothing needs a name before the link, and a fallback nothing needs is a path nothing tests.
### Names, and what a container can see
*2026-08-31, from a container that could not resolve a name every machine could.*
Internal names are `<node>.internal` — the suffix is the one IANA reserved in 2024, so a name that
leaks into a public resolver fails rather than reaching a stranger's machine. They are computed
centrally, because a name set needs every node at once, and written to each machine's hosts file.
**A file rather than a resolver**, and the reasoning holds: it works on every Linux, needs no
package, and has no failure mode of its own. The stated trigger for a daemon was *names that are
not one-per-node* — service names, wildcards.
**But a container does not inherit the machine's names.** It gets its own hosts file holding only
its own hostname. So every name the mesh wrote was invisible to the majority of things that need
one — and *on the machine it always worked*, which is exactly what made it easy to miss. It was
found by a database client on one node failing to resolve another node, on a mesh where both names
were correct and present on both machines.
**So the mesh gives its names to the containers it declares**, written into each container's own
hosts file by the runtime. That extends the file decision rather than overturning it. Given by the
mesh and not chosen by a module: a module that listed the machines would go stale the day one
joins, and a module that did not would be one whose containers cannot reach anything by name.
**The boundary, which is deliberate and worth stating:** *declared* containers. A container
somebody starts by hand is not the mesh's to configure, and reaching into every container on a
machine — declared or not — is what a nameserver in `resolv.conf` would be for.
**That is now the second reason to want a resolver**, and it is a different one from the trigger
above. Both remain unmet needs rather than plans:
| | |
|---|---|
| names that are not one-per-node | `postgres.internal` meaning *wherever the database is* |
| containers the mesh did not declare | anything a person or another tool starts on a node |
## 3 — Exposure
Settled by [ADR 0007](../../02-DECISIONS/0007-connectivity.md); summarised here because