@@ -34,22 +34,13 @@ yaml_quote() {
3434 printf " '%s'" " $( printf ' %s' " $1 " | sed " s/'/''/g" ) "
3535}
3636
37- # ---------------------------------------------------------------------------
38- # Select iptables backend
39- # ---------------------------------------------------------------------------
40- # Some kernels (e.g. Jetson Linux 5.15-tegra) have the nf_tables subsystem
41- # but lack the nft_compat bridge that allows flannel and kube-proxy to use
42- # xt extension modules (xt_comment, xt_conntrack). Detect this by probing
43- # whether xt_comment is usable via the current iptables backend. If the
44- # probe fails, switch to iptables-legacy. Set USE_IPTABLES_LEGACY=1
45- # externally to skip the probe and force the legacy backend.
4637# ---------------------------------------------------------------------------
4738# Check br_netfilter kernel module
4839# ---------------------------------------------------------------------------
4940# br_netfilter makes the kernel pass bridge (pod-to-pod) traffic through
50- # iptables. Without it, kube-proxy's DNAT rules for ClusterIP services are
51- # never applied to pod traffic, so pods cannot reach services such as
52- # kube-dns (10.43.0.10), breaking all in-cluster DNS resolution .
41+ # netfilter ( iptables or nftables) . Without it, kube-proxy's DNAT rules for
42+ # ClusterIP services are never applied to pod traffic, so pods cannot reach
43+ # services such as kube-dns (10.43.0.10), breaking all in-cluster DNS.
5344#
5445# The module must be loaded on the HOST before the container starts —
5546# containers cannot load kernel modules themselves. If it is missing, log a
@@ -65,25 +56,37 @@ if [ ! -f /proc/sys/net/bridge/bridge-nf-call-iptables ]; then
6556 echo " echo br_netfilter | sudo tee /etc/modules-load.d/br_netfilter.conf" >&2
6657fi
6758
68- if [ -z " ${USE_IPTABLES_LEGACY:- } " ]; then
69- if iptables -t filter -N _xt_probe 2> /dev/null; then
70- _probe_rc=0
71- iptables -t filter -A _xt_probe -m comment --comment " probe" -j ACCEPT \
72- 2> /dev/null || _probe_rc=$?
73- iptables -t filter -D _xt_probe -m comment --comment " probe" -j ACCEPT \
74- 2> /dev/null || true
75- iptables -t filter -X _xt_probe 2> /dev/null || true
76- [ " $_probe_rc " -ne 0 ] && USE_IPTABLES_LEGACY=1
59+ # ---------------------------------------------------------------------------
60+ # Select iptables backend (Docker only)
61+ # ---------------------------------------------------------------------------
62+ # Under Podman with nftables kube-proxy mode, the iptables backend probe is
63+ # unnecessary — kube-proxy uses nft directly. Flannel still uses the iptables
64+ # binary but through the nft compat shim which doesn't need the xt probe.
65+ #
66+ # Under Docker (or unset runtime), probe whether xt_comment is usable. Some
67+ # kernels (e.g. Jetson Linux 5.15-tegra) have nf_tables but lack the
68+ # nft_compat bridge. If the probe fails, switch to iptables-legacy.
69+ if [ " ${CONTAINER_RUNTIME:- } " != " podman" ]; then
70+ if [ -z " ${USE_IPTABLES_LEGACY:- } " ]; then
71+ if iptables -t filter -N _xt_probe 2> /dev/null; then
72+ _probe_rc=0
73+ iptables -t filter -A _xt_probe -m comment --comment " probe" -j ACCEPT \
74+ 2> /dev/null || _probe_rc=$?
75+ iptables -t filter -D _xt_probe -m comment --comment " probe" -j ACCEPT \
76+ 2> /dev/null || true
77+ iptables -t filter -X _xt_probe 2> /dev/null || true
78+ [ " $_probe_rc " -ne 0 ] && USE_IPTABLES_LEGACY=1
79+ fi
7780 fi
78- fi
7981
80- if [ " ${USE_IPTABLES_LEGACY:- 0} " = " 1" ]; then
81- echo " iptables nf_tables xt extension bridge unavailable — switching to iptables-legacy"
82- if update-alternatives --set iptables /usr/sbin/iptables-legacy 2> /dev/null &&
83- update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy 2> /dev/null; then
84- echo " Now using iptables-legacy mode"
85- else
86- echo " Warning: could not switch to iptables-legacy — cluster networking may fail"
82+ if [ " ${USE_IPTABLES_LEGACY:- 0} " = " 1" ]; then
83+ echo " iptables nf_tables xt extension bridge unavailable — switching to iptables-legacy"
84+ if update-alternatives --set iptables /usr/sbin/iptables-legacy 2> /dev/null &&
85+ update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy 2> /dev/null; then
86+ echo " Now using iptables-legacy mode"
87+ else
88+ echo " Warning: could not switch to iptables-legacy — cluster networking may fail"
89+ fi
8790 fi
8891fi
8992
@@ -174,13 +177,20 @@ setup_dns_proxy() {
174177 echo " Configured k3s DNS to use ${CONTAINER_IP} (proxied to Docker DNS)"
175178}
176179
177- if ! setup_dns_proxy; then
178- echo " DNS proxy setup failed, falling back to public DNS servers"
179- echo " Note: this may not work on Docker Desktop (Mac/Windows)"
180- cat > " $RESOLV_CONF " << EOF
180+ if [ " ${CONTAINER_RUNTIME:- } " = " podman" ]; then
181+ # Podman DNS is directly routable (aardvark-dns or host DNS) — no proxy
182+ # needed. Copy the container's resolv.conf so k3s has a stable path.
183+ cp /etc/resolv.conf " $RESOLV_CONF "
184+ echo " Podman detected — using host DNS resolution (no proxy needed)"
185+ else
186+ if ! setup_dns_proxy; then
187+ echo " DNS proxy setup failed, falling back to public DNS servers"
188+ echo " Note: this may not work on Docker Desktop (Mac/Windows)"
189+ cat > " $RESOLV_CONF " << EOF
181190nameserver 8.8.8.8
182191nameserver 8.8.4.4
183192EOF
193+ fi
184194fi
185195
186196# ---------------------------------------------------------------------------
632642# On kernels where xt_comment is unavailable, kube-router's network policy
633643# controller panics at startup. Disable it when the iptables-legacy probe
634644# triggered; sandbox isolation is enforced by the NSSH1 HMAC handshake instead.
635- if [ " ${USE_IPTABLES_LEGACY:- 0} " = " 1" ]; then
645+ # Under Podman with nftables kube-proxy, the xt probe is skipped entirely so
646+ # USE_IPTABLES_LEGACY is never set — network policy stays enabled.
647+ if [ " ${USE_IPTABLES_LEGACY:- 0} " = " 1" ] && [ " ${CONTAINER_RUNTIME:- } " != " podman" ]; then
636648 EXTRA_KUBELET_ARGS=" $EXTRA_KUBELET_ARGS --disable-network-policy"
637649fi
638650
@@ -659,8 +671,23 @@ if [ -n "${OPENSHELL_NODE_NAME:-}" ]; then
659671 echo " Using deterministic k3s node name: ${OPENSHELL_NODE_NAME} "
660672fi
661673
674+ # ---------------------------------------------------------------------------
675+ # Select kube-proxy mode
676+ # ---------------------------------------------------------------------------
677+ # 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.
680+ EXTRA_KUBE_PROXY_ARGS=" "
681+ if [ " ${CONTAINER_RUNTIME:- } " = " podman" ]; then
682+ echo " Podman detected — using nftables kube-proxy mode"
683+ EXTRA_KUBE_PROXY_ARGS=" --kube-proxy-arg=proxy-mode=nftables"
684+ fi
685+
662686# Execute k3s with explicit resolv-conf passed as a kubelet arg.
663687# k3s v1.35.2+ no longer accepts --resolv-conf as a top-level server flag;
664688# it must be passed via --kubelet-arg instead.
665689# shellcheck disable=SC2086
666- exec /bin/k3s " $@ " $NODE_NAME_ARG --kubelet-arg=resolv-conf=" $RESOLV_CONF " $EXTRA_KUBELET_ARGS
690+ exec /bin/k3s " $@ " $NODE_NAME_ARG \
691+ --kubelet-arg=resolv-conf=" $RESOLV_CONF " \
692+ $EXTRA_KUBELET_ARGS \
693+ $EXTRA_KUBE_PROXY_ARGS
0 commit comments