5 changed files with 74 additions and 0 deletions
@ -0,0 +1,43 @@ |
|||||
|
#!/bin/bash |
||||
|
# |
||||
|
# Resync the host's /etc/resolv.conf into the frozen snapshot that Podman |
||||
|
# bind-mounts into every Network=host container. |
||||
|
# |
||||
|
# Why: with Network=host, Podman copies /etc/resolv.conf at container *creation* |
||||
|
# time into .../userdata/resolv.conf and bind-mounts that copy. It is a snapshot, |
||||
|
# not a view: when the host's DNS servers change (DHCP renewal, renumbering, |
||||
|
# router replacement, ...), every running container keeps querying the old, |
||||
|
# now-dead resolvers — silently, until it is recreated. |
||||
|
# |
||||
|
# Fix: overwrite the snapshot's *content* in place (same inode, so the bind-mount |
||||
|
# stays valid). Both glibc (reloads when the file's mtime changes) and musl |
||||
|
# (stateless, re-reads on every lookup) then pick up the new resolvers at runtime |
||||
|
# with no restart and no downtime. |
||||
|
# |
||||
|
# Scope: Network=host containers ONLY. Bridged containers legitimately point at |
||||
|
# aardvark-dns (e.g. nameserver 10.89.0.1), which already follows the host's DNS |
||||
|
# live; overwriting their resolv.conf would break inter-container name resolution. |
||||
|
|
||||
|
set -Eeuo pipefail |
||||
|
|
||||
|
host_resolv=/etc/resolv.conf |
||||
|
|
||||
|
for id in $(podman ps -q); do |
||||
|
# Only touch containers that share the host network stack. |
||||
|
mode="$(podman inspect --format '{{.HostConfig.NetworkMode}}' "$id" 2>/dev/null)" || continue |
||||
|
[ "$mode" = host ] || continue |
||||
|
|
||||
|
snapshot="$(podman inspect --format '{{.ResolvConfPath}}' "$id" 2>/dev/null)" || continue |
||||
|
[ -n "$snapshot" ] && [ -f "$snapshot" ] || continue |
||||
|
|
||||
|
if ! cmp -s "$host_resolv" "$snapshot"; then |
||||
|
name="$(podman inspect --format '{{.Name}}' "$id" 2>/dev/null || echo "$id")" |
||||
|
echo "Refreshing resolv.conf for container ${name} (${snapshot})" |
||||
|
# In-place truncation: preserves the inode the container has bind-mounted. |
||||
|
if ! cat "$host_resolv" > "$snapshot"; then |
||||
|
echo "Failed to refresh resolv.conf for container ${name}!" >&2 |
||||
|
fi |
||||
|
fi |
||||
|
done |
||||
|
|
||||
|
exit 0 |
||||
@ -0,0 +1,12 @@ |
|||||
|
[Unit] |
||||
|
Description=Watch /etc/resolv.conf and resync it into Network=host containers |
||||
|
Documentation=https://github.com/nmasse-itix/podman-quadlet-cookbook/issues/1 |
||||
|
|
||||
|
[Path] |
||||
|
# Fires on any writer (NetworkManager, manual edit, ...), including atomic |
||||
|
# rename-into-place, since systemd also watches the parent directory. |
||||
|
PathChanged=/etc/resolv.conf |
||||
|
Unit=podman-resolv-conf-sync.service |
||||
|
|
||||
|
[Install] |
||||
|
WantedBy=multi-user.target |
||||
@ -0,0 +1,8 @@ |
|||||
|
[Unit] |
||||
|
Description=Resync /etc/resolv.conf into running Network=host Podman containers |
||||
|
Documentation=https://github.com/nmasse-itix/podman-quadlet-cookbook/issues/1 |
||||
|
# Triggered by podman-resolv-conf-sync.path whenever /etc/resolv.conf changes. |
||||
|
|
||||
|
[Service] |
||||
|
Type=oneshot |
||||
|
ExecStart=/etc/quadlets/base/podman-resolv-conf-sync.sh |
||||
Loading…
Reference in new issue