Files
T
jschoubben f1941304cc ADRs 0164-0166 and issue 190: the container runtime gets a module, a seat and declared settings
Proposed for the operator's review: settings declared with defaults and cost (0164),
container-runtime as a kernel capability (0165), node-container-runtime seat with the
host creating containers through its holder (0166), and the runtime's file written by
modules that are not its own (190).
2026-10-01 23:13:18 +02:00

4.8 KiB
Raw Blame History

status, opened, located-in, fixed-by, amended-design
status opened located-in fixed-by amended-design
located 2026-10-01
mesh-catalog modules/dnsmasq
mesh-controller internal/overlay/generator.go
mesh-controller internal/catalogue/resolve.go (checkResources)

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). It also declares the runtime's service, reloaded when that file changes. It was added on 2026-09-30 to fix issue 110, 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 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 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 gives the runtime a module that holds its seat and owns its file and service. ADR 0164 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.