Skip to content

Commit 797bca0

Browse files
authored
Merge pull request #25 from LobsterTrap/fix/flannel-iptables-and-healthcheck
fix(bootstrap): fix nftables healthcheck and warn on missing flannel modules
2 parents 4b67305 + 32f46b7 commit 797bca0

2 files changed

Lines changed: 38 additions & 6 deletions

File tree

deploy/docker/cluster-entrypoint.sh

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -675,12 +675,34 @@ fi
675675
# Select kube-proxy mode
676676
# ---------------------------------------------------------------------------
677677
# Under Podman, use native nftables kube-proxy mode so no legacy iptables
678-
# kernel modules (ip_tables, iptable_nat, etc.) are required on the host.
679-
# Docker retains the default iptables mode for maximum compatibility.
678+
# kernel modules are needed for kube-proxy service routing.
679+
#
680+
# Flannel's embedded traffic manager in k3s v1.35.x still uses the iptables
681+
# binary (no nft backend compiled in). The iptables binary inside the
682+
# container is iptables-legacy, which requires the iptable_nat, iptable_filter,
683+
# and ip_tables kernel modules. Modern distributions (Fedora 43+, RHEL 10+)
684+
# no longer load these modules by default. The RPM %post scriptlet both
685+
# loads the modules immediately and installs a modules-load.d config for
686+
# persistence across reboots. The warning below covers non-RPM installs.
687+
#
688+
# Docker retains the default iptables kube-proxy mode for maximum compatibility.
680689
EXTRA_KUBE_PROXY_ARGS=""
681690
if [ "${CONTAINER_RUNTIME:-}" = "podman" ]; then
682691
echo "Podman detected — using nftables kube-proxy mode"
683692
EXTRA_KUBE_PROXY_ARGS="--kube-proxy-arg=proxy-mode=nftables"
693+
694+
# Verify legacy iptables kernel modules are loaded on the host.
695+
# Flannel's traffic manager calls iptables-legacy for masquerade rules,
696+
# which requires iptable_nat and related modules. The RPM loads these
697+
# at install time and persists them via modules-load.d, but they may be
698+
# absent on non-RPM installs or manually configured systems.
699+
if ! cat /proc/modules 2>/dev/null | grep -q '^iptable_nat '; then
700+
echo "Warning: iptable_nat kernel module is not loaded on the host." >&2
701+
echo " Flannel masquerade rules will fail without it." >&2
702+
echo " Load it now with: sudo modprobe iptable_nat" >&2
703+
echo " To persist across reboots:" >&2
704+
echo " echo iptable_nat | sudo tee /etc/modules-load.d/openshell-flannel.conf" >&2
705+
fi
684706
fi
685707

686708
# Execute k3s with explicit resolv-conf passed as a kubelet arg.

deploy/docker/cluster-healthcheck.sh

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,18 @@ kubectl -n openshell get secret openshell-ssh-handshake >/dev/null 2>&1 || exit
7575
# ---------------------------------------------------------------------------
7676
# Verify the gateway NodePort (30051) is actually accepting TCP connections.
7777
# After a container restart, kube-proxy may need extra time to re-program
78-
# iptables rules for NodePort routing. Without this check the health check
79-
# can pass before the port is routable, causing "Connection refused" on the
80-
# host-mapped port.
78+
# iptables/nftables rules for NodePort routing. Without this check the
79+
# health check can pass before the port is routable, causing "Connection
80+
# refused" on the host-mapped port.
81+
#
82+
# When kube-proxy runs in nftables mode (Podman), NodePort DNAT rules only
83+
# match traffic destined to the node's real IP addresses — loopback
84+
# (127.0.0.1) is not in the nodeport-ips set. Use the node's InternalIP
85+
# so the check works with both iptables and nftables kube-proxy modes.
8186
# ---------------------------------------------------------------------------
82-
timeout 2 bash -c 'echo >/dev/tcp/127.0.0.1/30051' 2>/dev/null || exit 1
87+
NODEPORT_CHECK_IP="127.0.0.1"
88+
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}' 2>/dev/null || true)
89+
if [ -n "$NODE_IP" ]; then
90+
NODEPORT_CHECK_IP="$NODE_IP"
91+
fi
92+
timeout 2 bash -c "echo >/dev/tcp/${NODEPORT_CHECK_IP}/30051" 2>/dev/null || exit 1

0 commit comments

Comments
 (0)