Sitelet https://github.com/kubernetes/kops/pull/18478
Skip to content

nodeup: load ip_set module and disable firewalld on RHEL10 - #18478

Merged
k8s-ci-robot merged 1 commit into
kubernetes:masterfrom
rifelpet:disable-firewalld-rhel10
Jun 18, 2026
Merged

k8s-ci-robot merged 1 commit into
kubernetes:masterfrom
rifelpet:disable-firewalld-rhel10

Conversation

@rifelpet

Copy link
Copy Markdown
Member

Summary

Two related fixes for kops nodeup on the ForceNftables() distros (RHEL 10+, Rocky 10+):

  1. Load the ip_set kernel module alongside nf_tables / nf_conntrack in loadKernelModules.
  2. Stop and mask firewalld.service via a new step on FirewallBuilder, gated on Distribution.ForceNftables().

Together these unblock the failing Calico cells in the e2e-kops-grid-calico-{rhel10,rocky10}* grid, which produce two distinct failure modes today.

Problem

Mode 1 — Felix ipsetsManager panics (arm64 cells)

Calico v3.31's Felix unconditionally starts an ipsetsManager that shells out to ipset list -name during dataplane resync, even when NFTablesMode: Enabled is in effect. On RHEL 10-family arm64 kernels the ip_set module isn't auto-loaded, so the netlink request returns EINVAL and Felix panics in a tight loop, taking calico-node with it. Every node reports CrashLoopBackOff, validation fails after ~25 min, Up returns exit 1.

The relevant Felix log on a failing node:

[ERROR] felix/ipsets.go:758: Bad return code from 'ipset list -name'. stderr="ipset v7.11: Kernel error received: Invalid argument"
[PANIC] felix/ipsets.go:416: Failed to update IP sets after multiple retries.

lsmod on the same node confirms ip_set is absent while nf_tables and nf_conntrack (already modprobed by kops) are present.

Example failing jobs:

Mode 2 — BGP keepalives killed by firewalld interaction (GCE x86_64 cells)

On the GCE-optimized Rocky Linux 10 image, firewalld.service starts at boot: Starting firewalld.service - firewalld - dynamic firewall daemon..., and the resulting nft ruleset contains a populated table inet firewalld with default-reject filter_INPUT and filter_FORWARD policies plus a ct state invalid drop rule. firewalld's periodic-reload behavior plus that ct state invalid drop race against Calico's BPF-mode INPUT chain rule:

meta mark & 0x05000000 == 0x05000000 meta l4proto tcp ... reject with tcp reset

which TCP-RSTs any BGP keepalive that arrives after the session's conntrack entry has been dropped. BIRD then logs Error: Hold timer expired on all peers simultaneously and the mesh never recovers. Cluster validation succeeds but e2e tests time out at the 60-minute kubetest2 cap.

This pattern persists even with networking.calico.nftablesMode: Enabled set (the field added in #18452), confirming the flap isn't caused by Felix's nft_compat usage. the host-level firewalld is the remaining disturbance.

Example failing builds:

Why only the GCE image

Empirical comparison from this investigation's own artifacts:

Image firewalld.service started? table inet firewalld in nft?
GCE rocky-linux-cloud/rocky-linux-10-optimized-gcp-v20260526 (x86_64) yes yes
AWS 309956199498/RHEL-10.1.0_HVM-...arm64-... (Red Hat AMI) no absent

The CIQ-built GCE-optimized spin ships firewalld active; the Red Hat AWS AMIs and the upstream Rocky GenericCloud qcow2 don't. Disabling firewalld in nodeup is therefore a no-op on the AWS path and a fix on the GCE path.

Fix

upup/pkg/fi/nodeup/command.go — loadKernelModules: append ip_set to the ForceNftables() modprobe list. modprobe already logs warnings on failure rather than aborting nodeup, so the call is safe on hosts where the module package isn't installed.

nodeup/pkg/model/firewall.go — new disableFirewalld(c) step: mirrors the existing disableNMCloudSetup pattern. it writes a marker file under /etc/kops/ and uses OnChangeExecute to run systemctl disable --now firewalld.service and systemctl mask firewalld.service, both wrapped in bash -c '... 2>/dev/null; true' so they're safe no-ops on images where firewalld isn't installed. Gated on b.Distribution.ForceNftables().

Precedent for unconditionally disabling firewalld

  • Calico requirements doc: "If your Linux distribution comes with installed Firewalld or another iptables manager it should be disabled."
  • RKE2 known issues: "firewalld should be disabled on systems running RKE2."
  • OpenShift: disables firewalld on every RHEL worker (openshift-ansible #11824).
  • AWS RHEL/Rocky 10 image team: strips firewalld from the AMI.

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Jun 17, 2026
@k8s-ci-robot
k8s-ci-robot requested review from hakman and olemarkus June 17, 2026 03:06
Two related fixes for Calico on the ForceNftables() distros (RHEL10+,
Rocky10+, etc.).

Load the ip_set kernel module alongside nf_tables and nf_conntrack.
Calico's Felix unconditionally starts an ipsetsManager that shells out
to "ipset list -name" during dataplane resync, even when NFTablesMode
is Enabled. On RHEL10-family kernels ip_set is not auto-loaded, so the
ipset call returns EINVAL and Felix panics in a tight loop, crashing
calico-node and blocking cluster Up on every arm64 grid cell.

Disable and mask firewalld via a new disableFirewalld step on
FirewallBuilder, gated on Distribution.ForceNftables(). firewalld's
default-reject filter_INPUT/filter_FORWARD policies and periodic-reload
behavior conflict with the iptables/nftables rules CNIs install for
pod and service traffic; Calico's own requirements doc and RKE2 both
document that firewalld must be disabled on hosts running these CNIs.
The disable/mask sequence is idempotent and a no-op where firewalld is
not installed, so this is net-neutral on the cloud images that already
strip firewalld (AWS RHEL/Rocky AMIs, Rocky GenericCloud) and net-
positive on the GCE-optimized Rocky 10 image where firewalld ships
active and breaks Calico BGP keepalives in BPF mode.
@rifelpet
rifelpet force-pushed the disable-firewalld-rhel10 branch from 3af5728 to 6869831 Compare June 18, 2026 16:11
@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jun 18, 2026
@k8s-ci-robot

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: hakman

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 18, 2026
@hakman

hakman commented Jun 18, 2026

Copy link
Copy Markdown
Member

/override pull-kops-e2e-k8s-gce-ipalias

@k8s-ci-robot

Copy link
Copy Markdown
Contributor

@hakman: Overrode contexts on behalf of hakman: pull-kops-e2e-k8s-gce-ipalias

Details

In response to this:

/override pull-kops-e2e-k8s-gce-ipalias

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@k8s-ci-robot
k8s-ci-robot merged commit 340689d into kubernetes:master Jun 18, 2026
26 checks passed
k8s-ci-robot added a commit that referenced this pull request Jun 18, 2026
…78-origin-release-1.36

Automated cherry pick of #18478: nodeup: load ip_set module and disable firewalld on RHEL10
k8s-ci-robot added a commit that referenced this pull request Jun 19, 2026
…78-origin-release-1.35

Automated cherry pick of #18478: nodeup: load ip_set module and disable firewalld on RHEL10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. area/nodeup cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants