Skip to content

Commit

Permalink
fix: pre-create nftables chain to make kubelet use nftables
Browse files Browse the repository at this point in the history
In Talos, kubelet (and kube-proxy) images use `iptables-wrapper` script
to detect which version of `iptables` (legacy or NFT) to use.

The script assumes that `kubelet` runs on the host, and uses whatever
version of `iptables` which is being used by the host. In Talos,
`kubelet` runs in a container which has same `iptables-wrapper` script,
and it defaults to `legacy` mode in our case.

We can't check the `kubelet` image, as it would affect all Talos
version, so instead pre-create the chains/tables in `nftables` so that
kubelet will pick up `nft` version of `iptables`, and `kube-proxy` will
do the same.

Without this fix, the problem arises from the mix of `nft` used by Talos
for the firewall and Kubernetes world relying on `legacy` (`xtables`).

Fixes siderolabs/kubelet#77

See https://github.com/kubernetes-sigs/iptables-wrappers/blob/e139a115350974aac8a82ec4b815d2845f86997e/iptables-wrapper-installer.sh#L102-L130

Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
(cherry picked from commit ff2c427)
  • Loading branch information
smira committed Apr 12, 2024
1 parent abf302f commit 41a54e8
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
10 changes: 10 additions & 0 deletions hack/release.toml
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,16 @@ machine:
title = "Platforms"
description = """\
Talos Linux now supports [Akamai Connected Cloud](https://www.linode.com/) provider (platform `akamai`).
"""

[notes.iptables]
title = "IPTables"
description = """\
Talos Linux now forces `kubelet` and `kube-proxy` to use `iptables-nft` instead of `iptables-legacy` (`xtables`) which was the default
before Talos 1.7.0.
Container images based on `iptables-wrapper` should work without changes, but if there was a direct call to `legacy` mode of `iptables`, make sure
to update to use `iptables-nft`.
"""

[make_deps]
Expand Down
35 changes: 35 additions & 0 deletions internal/app/machined/pkg/controllers/network/nftables_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ func (ctrl *NfTablesChainController) Run(ctx context.Context, r controller.Runti

var conn nftables.Conn

if err := ctrl.preCreateIptablesNFTable(logger, &conn); err != nil {
return fmt.Errorf("error pre-creating iptables-nft table: %w", err)
}

list, err := safe.ReaderListAll[*network.NfTablesChain](ctx, r)
if err != nil {
return fmt.Errorf("error listing nftables chains: %w", err)
Expand Down Expand Up @@ -176,3 +180,34 @@ func (ctrl *NfTablesChainController) Run(ctx context.Context, r controller.Runti
r.ResetRestartBackoff()
}
}

func (ctrl *NfTablesChainController) preCreateIptablesNFTable(logger *zap.Logger, conn *nftables.Conn) error {
// Pre-create the iptables-nft table, if it doesn't exist.
// This is required to ensure that the iptables universal binary prefers iptables-nft over
// iptables-legacy can be used to manage the nftables rules.
tables, err := conn.ListTablesOfFamily(nftables.TableFamilyIPv4)
if err != nil {
return fmt.Errorf("error listing existing nftables tables: %w", err)
}

if slices.IndexFunc(tables, func(t *nftables.Table) bool { return t.Name == "mangle" }) != -1 {
return nil
}

table := &nftables.Table{
Family: nftables.TableFamilyIPv4,
Name: "mangle",
}
conn.AddTable(table)

chain := &nftables.Chain{
Name: "KUBE-IPTABLES-HINT",
Table: table,
Type: nftables.ChainTypeNAT,
}
conn.AddChain(chain)

logger.Info("pre-created iptables-nft table 'mangle'/'KUBE-IPTABLES-HINT'")

return nil
}

0 comments on commit 41a54e8

Please sign in to comment.