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).
77 lines
4.8 KiB
Markdown
77 lines
4.8 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. It was added on 2026-09-30 to
|
||
fix [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.
|