79 lines
4.9 KiB
Markdown
79 lines
4.9 KiB
Markdown
---
|
||
status: located
|
||
opened: 2026-10-01
|
||
located-in: [mesh-catalog modules/dnsmasq, mesh-controller internal/overlay/generator.go, mesh-controller internal/catalogue/resolve.go (checkResources)]
|
||
fixed-by:
|
||
amended-design:
|
||
---
|
||
|
||
# 190 — The container runtime's configuration is written by modules that are not the runtime's
|
||
|
||
## What was observed
|
||
|
||
The runtime's configuration file and its service are declared by two parties, neither of which is
|
||
the runtime:
|
||
|
||
- **The resolver module** writes the runtime's `dns` key (the machine's private address) and
|
||
`live-restore` into the runtime's file, written into rather than over
|
||
([ADR 0102](../../02-DECISIONS/0102-the-mesh-writes-into-a-shared-file-never-over-it.md)). It also
|
||
declares the runtime's service, reloaded when that file changes. The `dns` key has been written
|
||
since the resolver module was converted from its predecessor on 2026-09-23; `live-restore` and the
|
||
service were added on 2026-09-30 while fixing
|
||
[issue 110](../110-a-container-on-the-runtimes-own-network-cannot-reach-the-resolver/00-report.md),
|
||
where containers silently resolved through a public resolver.
|
||
- **The private network** writes the runtime's `insecure-registries` into the same file, and declares
|
||
the same service reloaded on it, as [ADR 0082](../../02-DECISIONS/0082-the-registry-is-reached-by-name-and-trusted-by-the-overlay.md)
|
||
and ADR 0102 decided. The controller generates both resources per machine.
|
||
|
||
On the three machines that run the resolver module, both declare one path and one unit. Nothing refuses
|
||
it. The collision check compares the resources of catalogue modules. The private network is computed,
|
||
so its resources are produced when a machine's declaration is composed, and the check never sees them.
|
||
|
||
The machine without the resolver module shows the other half. Its runtime still has the predecessor's
|
||
resolver and `live-restore` off, because the only module that sets them is a DNS server. A machine
|
||
gets a correct container runtime only as a side effect of being given a resolver.
|
||
|
||
## Why this is here
|
||
|
||
The operator ruled it a defect, not a design: **a module does not write another software's
|
||
configuration.** The need behind each write is real. Containers must resolve the mesh's names
|
||
([ADR 0148](../../02-DECISIONS/0148-the-meshs-names-are-resolved-not-copied-into-containers.md) step 2).
|
||
A daemon restart must not stop every container. Every machine on the network must trust the mesh's
|
||
registry. But each of these is a fact the runtime must be *given*, and the module that gives it is the
|
||
runtime's own. With three writers, nobody can say what the file should contain. Two of the facts are
|
||
reloaded when one of them needs a restart (issue 110's first fault). And the moment a module for the
|
||
runtime exists, it is refused on every machine with the resolver, or, through the private network's
|
||
path, accepted without anyone noticing a collision.
|
||
|
||
## What resolves it
|
||
|
||
[ADR 0166](../../02-DECISIONS/0166-the-container-runtime-is-a-node-seat-and-the-host-creates-containers-through-its-holder.md)
|
||
gives the runtime a module that holds its seat and owns its file and service.
|
||
[ADR 0164](../../02-DECISIONS/0164-a-setting-is-declared-with-its-default-its-meaning-and-what-changing-it-costs.md)
|
||
gives that module declared settings with defaults. The fix, once both are accepted:
|
||
|
||
1. The resolver module drops its runtime file and runtime service. It knows nothing of the runtime.
|
||
2. The private network stops generating either resource. ADR 0082's decision stands — being on the
|
||
network is what grants the trust, and no module author is involved — and only *who writes it*
|
||
moves. The mesh gives the registry to the runtime module as a value. ADR 0082 and ADR 0102 each
|
||
get a dated note saying where their mechanism now lives.
|
||
3. The runtime module writes `dns`, `live-restore` and `insecure-registries`, each a declared
|
||
setting with its cost: `dns` costs a restart, which `live-restore` makes harmless.
|
||
4. Steps 1–3 land in one push. A runtime module declaring the file beside a resolver module still
|
||
declaring it is refused.
|
||
5. The collision check sees a computed module's resources as well, so a second writer cannot come
|
||
back through generated code.
|
||
|
||
## Open questions
|
||
|
||
- **How the resolver's address reaches the runtime.** Either the resolver seat (`node-dns-resolver`)
|
||
delivers an address its holder serves, or the runtime module reads a machine fact and the seat
|
||
being held is only a precondition. The first tracks a resolver moving off the private address. The
|
||
second needs nothing new.
|
||
- **What `dns` defaults to on a machine with no resolver seat held.** Nothing, leaving the runtime's
|
||
own behaviour, is the honest default. A public resolver hides exactly the failure issue 110 took a
|
||
day to find.
|
||
- **The adopted machine's predecessor values.** The runtime module adopting a file with a
|
||
hand-written `dns` and `live-restore: false` replaces both. That is intended, and is the one
|
||
restart the operator must make on that machine.
|