Files
OpenFUT/scripts/systemd/openfut-staging-netns-reconcile.service
T
funman300 1e8d46b258 ops(systemd): follow the anchor container's netns across recreation
Recreating the Docker anchor left the supervised Core and host stranded in
the dead namespace while systemd still reported them active — serving
nobody, invisible to any monitoring that trusts unit state. Reproduced on
staging: netns 4026539938 -> 4026540033, both pids unchanged in the old
one, both units "active", traffic ConnectionResetError.

There is no systemd-native edge signal to bind to. Containers do appear as
units, but the scope name embeds the container ID (docker-<id>.scope), which
changes on every recreate, so BindsTo= has no stable target;
NetworkNamespacePath= resolves once at start; a .path unit on /run/netns
would watch the file this tooling maintains. So: a level-triggered reconcile
on a 10s timer, comparing the namespace the services are ACTUALLY in against
the anchor's CURRENT one, acting only on a real difference. That cannot miss
an event while the watcher restarts or dockerd is down, and needs no
debounce — a burst of three recreations produced exactly one rebind. The
trigger stays separable: a docker-events unit could invoke the same script.

Anchor absent stops the dependants rather than falling back to host
networking; docker unavailable logs once and retries on the next tick.

Two defects found while testing and fixed here:
- mount --bind STACKS when the old mount is busy, silently leaking nsfs
  entries; the bind helper now drains stale mounts in a loop.
- reconcile must stop -> rebind -> start, not rebind -> restart: a running
  service holds the old namespace open and makes the umount fail busy.

Staging also gained a faithful anchor container so the reproduction is
structural rather than mocked. Economy state was byte-identical across every
lifecycle test. Production units are templates only and remain uninstalled.
2026-08-22 21:14:23 +00:00

23 lines
910 B
Desktop File

[Unit]
Description=OpenFUT STAGING: reconcile services with the anchor container network namespace
Documentation=file:///home/alex/OpenFUT/scripts/systemd/README.md
After=docker.service
Wants=docker.service
# Deliberately NO Requires=docker.service: a docker outage must be a quiet
# retry, not a failed unit. The script itself decides that and exits 0.
[Service]
Type=oneshot
# Level-triggered: compares the namespace the services are ACTUALLY in against
# the anchor's CURRENT one, so a burst of container events collapses into at
# most one rebind per tick and no separate debounce is needed.
ExecStart=/home/alex/OpenFUT/scripts/systemd/openfut-netns-reconcile.sh \
openfut-staging-anchor openfut-staging \
openfut-staging-netns.service \
openfut-staging-core.service openfut-staging-host.service
StandardOutput=journal
StandardError=journal
SyslogIdentifier=openfut-staging-netns-reconcile