1e8d46b258
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.
31 lines
1.1 KiB
Desktop File
31 lines
1.1 KiB
Desktop File
[Unit]
|
|
Description=OpenFUT STAGING: publish the anchor container network namespace to /run/netns/openfut-staging
|
|
Documentation=file:///home/alex/OpenFUT/scripts/systemd/README.md
|
|
After=docker.service
|
|
Requires=docker.service
|
|
|
|
# Re-resolved on every start, so this unit is also the REPAIR action after the
|
|
# anchor container is recreated: `systemctl restart openfut-staging-netns` plus
|
|
# a restart of the dependants re-enters the current namespace.
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=5
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
RemainAfterExit=yes
|
|
|
|
# Resolves the anchor BY NAME, never by a stored pid, and exits non-zero when
|
|
# the anchor is absent — which is what makes the dependants' Requires= a real
|
|
# admission gate rather than decoration.
|
|
ExecStart=/home/alex/OpenFUT/scripts/systemd/openfut-netns-bind.sh openfut-staging-anchor openfut-staging
|
|
|
|
# No ExecStop unmount: the namespace belongs to the container's lifetime, and
|
|
# tearing the bind mount down under a live Core/host would strand them.
|
|
|
|
StandardOutput=journal
|
|
StandardError=journal
|
|
SyslogIdentifier=openfut-staging-netns
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|