From 912eca9e8b58b3f6eabb515030400c49288995a8 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 30 Jan 2024 17:30:48 -0500 Subject: [PATCH] Reorganize nftables proxy init Move the "nftables is supported" check into a separate function, and call it before the --init-only return. --- pkg/proxy/nftables/proxier.go | 41 +++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/pkg/proxy/nftables/proxier.go b/pkg/proxy/nftables/proxier.go index 0ba4a437363..46cf187bb16 100644 --- a/pkg/proxy/nftables/proxier.go +++ b/pkg/proxy/nftables/proxier.go @@ -215,6 +215,11 @@ func NewProxier(ctx context.Context, ) (*Proxier, error) { logger := klog.LoggerWithValues(klog.FromContext(ctx), "ipFamily", ipFamily) + nft, err := getNFTablesInterface(ipFamily) + if err != nil { + return nil, err + } + if initOnly { logger.Info("System initialized and --init-only specified") return nil, nil @@ -229,17 +234,6 @@ func NewProxier(ctx context.Context, serviceHealthServer := healthcheck.NewServiceHealthServer(hostname, recorder, nodePortAddresses, healthzServer) - var nftablesFamily knftables.Family - if ipFamily == v1.IPv4Protocol { - nftablesFamily = knftables.IPv4Family - } else { - nftablesFamily = knftables.IPv6Family - } - nft, err := knftables.New(nftablesFamily, kubeProxyTable) - if err != nil { - return nil, err - } - proxier := &Proxier{ ipFamily: ipFamily, svcPortMap: make(proxy.ServicePortMap), @@ -270,6 +264,31 @@ func NewProxier(ctx context.Context, return proxier, nil } +// Create a knftables.Interface and check if we can use the nftables proxy mode on this host. +func getNFTablesInterface(ipFamily v1.IPFamily) (knftables.Interface, error) { + var nftablesFamily knftables.Family + if ipFamily == v1.IPv4Protocol { + nftablesFamily = knftables.IPv4Family + } else { + nftablesFamily = knftables.IPv6Family + } + + // We require (or rather, knftables.New does) that the nft binary be version 1.0.1 + // or later, because versions before that would always attempt to parse the entire + // nft ruleset at startup, even if you were only operating on a single table. + // That's bad, because in some cases, new versions of nft have added new rule + // types in ways that triggered bugs in older versions of nft, causing them to + // crash. Thus, if kube-proxy used nft < 1.0.1, it could potentially get locked + // out of its rules because of something some other component had done in a + // completely different table. + nft, err := knftables.New(nftablesFamily, kubeProxyTable) + if err != nil { + return nil, err + } + + return nft, nil +} + // internal struct for string service information type servicePortInfo struct { *proxy.BaseServicePortInfo