Compare commits

...

2 Commits

Author SHA1 Message Date
Nicolas Massé a2cf09eaf1
Merge pull request #12 from nmasse-itix/fix/network-host-resolv-conf 2 weeks ago
Nicolas Massé 9771f18de7 base: resync /etc/resolv.conf into Network=host containers 2 weeks ago
  1. 5
      cookbooks/base/Makefile
  2. 6
      cookbooks/base/README.md
  3. 43
      cookbooks/base/config/podman-resolv-conf-sync.sh
  4. 12
      cookbooks/base/podman-resolv-conf-sync.path
  5. 8
      cookbooks/base/podman-resolv-conf-sync.service

5
cookbooks/base/Makefile

@ -2,8 +2,13 @@
SYSTEMD_MAIN_UNIT_NAMES := var-lib-virtiofs-data.mount SYSTEMD_MAIN_UNIT_NAMES := var-lib-virtiofs-data.mount
SYSTEMD_MAIN_UNIT_NAMES += rpm-ostree-install-qemu-guest-agent.service SYSTEMD_MAIN_UNIT_NAMES += rpm-ostree-install-qemu-guest-agent.service
SYSTEMD_MAIN_UNIT_NAMES += install-tools.service SYSTEMD_MAIN_UNIT_NAMES += install-tools.service
# .path units are not picked up by common.mk's wildcard (only .service/.target/
# .timer/.mount), so install and enable/start it explicitly. It triggers the
# path-scoped podman-resolv-conf-sync.service oneshot.
SYSTEMD_MAIN_UNIT_NAMES += podman-resolv-conf-sync.path
TARGET_FILES += $(TARGET_CHROOT)/etc/quadlets/base/install-tools.d TARGET_FILES += $(TARGET_CHROOT)/etc/quadlets/base/install-tools.d
TARGET_FILES += $(TARGET_CHROOT)/etc/systemd/system/podman-resolv-conf-sync.path
# Include common Makefile # Include common Makefile
include ../../scripts/common.mk include ../../scripts/common.mk

6
cookbooks/base/README.md

@ -8,6 +8,12 @@ The base cookbook provides foundational configuration for Fedora CoreOS systems.
- **tmpfiles configuration**: Sets up required directories such as `/var/lib/virtiofs/data`. - **tmpfiles configuration**: Sets up required directories such as `/var/lib/virtiofs/data`.
- **QEMU guest agent**: Optional installation for better VM integration. - **QEMU guest agent**: Optional installation for better VM integration.
- **SSH key persistence**: Backs up and restores SSH host keys across reboots. - **SSH key persistence**: Backs up and restores SSH host keys across reboots.
- **resolv.conf resync**: Keeps `Network=host` containers in sync with the host's DNS.
With `Network=host`, Podman snapshots `/etc/resolv.conf` at container creation and bind-mounts
the copy, so a later DNS change (e.g. a DHCP renewal) never reaches running containers. A
`systemd.path` unit watches `/etc/resolv.conf` and a oneshot service rewrites each host-network
container's snapshot **in place** (same inode, no restart); bridged containers are left untouched.
See [issue #1](https://github.com/nmasse-itix/podman-quadlet-cookbook/issues/1).
This cookbook is used as an implicit dependency for other cookbooks that run on Fedora CoreOS. This cookbook is used as an implicit dependency for other cookbooks that run on Fedora CoreOS.

43
cookbooks/base/config/podman-resolv-conf-sync.sh

@ -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

12
cookbooks/base/podman-resolv-conf-sync.path

@ -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

8
cookbooks/base/podman-resolv-conf-sync.service

@ -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…
Cancel
Save