From 83cd0ebf797d01ac5b0c4613b7690dfaa65dc81a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan-Luis=20de=20Sousa-Valadas=20Casta=C3=B1o?= Date: Wed, 9 Oct 2024 12:53:27 +0200 Subject: [PATCH] Extract iptables binary staging to iptablesutils MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPLB potentially will need to create some iptables rules for its userspace proxy, hence this code should be in iptablesutils rather than pkg/worker/kubelet. Signed-off-by: Juan-Luis de Sousa-Valadas CastaƱo --- internal/pkg/iptablesutils/iptables.go | 58 +++++++++++++++++++++++ pkg/component/worker/kernelsetup.go | 3 +- pkg/component/worker/kernelsetup_linux.go | 9 ---- pkg/component/worker/kubelet.go | 38 ++------------- 4 files changed, 64 insertions(+), 44 deletions(-) diff --git a/internal/pkg/iptablesutils/iptables.go b/internal/pkg/iptablesutils/iptables.go index 9ad4dc3c0190..18389f86c4b8 100644 --- a/internal/pkg/iptablesutils/iptables.go +++ b/internal/pkg/iptablesutils/iptables.go @@ -20,10 +20,14 @@ import ( "bufio" "errors" "fmt" + "os" "os/exec" "path/filepath" + "runtime" "strings" + "github.com/k0sproject/k0s/pkg/assets" + "github.com/k0sproject/k0s/pkg/constant" "github.com/sirupsen/logrus" ) @@ -32,6 +36,60 @@ const ( ModeLegacy = "legacy" ) +// ExtractIPTablesBinaries extracts the iptables binaries from the k0s binary and makes the symlinks +// to the backend detected by DetectHostIPTablesMode. +// ExtractIPTablesBinaries only works on linux, if called in another OS it will return an error. +func ExtractIPTablesBinaries(k0sBinDir string, iptablesMode string) (error, string) { + if runtime.GOOS != "linux" { + return fmt.Errorf("iptables extraction is only supported on linux"), "" + } + + cmds := []string{"kubelet", "xtables-legacy-multi", "xtables-nft-multi"} + for _, cmd := range cmds { + err := assets.Stage(k0sBinDir, cmd, constant.BinDirMode) + if err != nil { + return err, "" + } + } + if iptablesMode == "" || iptablesMode == "auto" { + var err error + iptablesMode, err = DetectHostIPTablesMode(k0sBinDir) + if err != nil { + if kernelMajorVersion() < 5 { + iptablesMode = ModeLegacy + } else { + iptablesMode = ModeNFT + } + logrus.WithError(err).Infof("Failed to detect iptables mode, using iptables-%s by default", iptablesMode) + } + } + logrus.Infof("using iptables-%s", iptablesMode) + oldpath := fmt.Sprintf("xtables-%s-multi", iptablesMode) + for _, symlink := range []string{"iptables", "iptables-save", "iptables-restore", "ip6tables", "ip6tables-save", "ip6tables-restore"} { + symlinkPath := filepath.Join(k0sBinDir, symlink) + + // remove if it exist and ignore error if it doesn't + _ = os.Remove(symlinkPath) + + err := os.Symlink(oldpath, symlinkPath) + if err != nil { + return fmt.Errorf("failed to create symlink %s: %w", symlink, err), "" + } + } + + return nil, iptablesMode +} +func kernelMajorVersion() byte { + if runtime.GOOS != "linux" { + return 0 + } + data, err := os.ReadFile("/proc/sys/kernel/osrelease") + if err != nil { + return 0 + } + return data[0] - '0' +} + // DetectHostIPTablesMode figure out whether iptables-legacy or iptables-nft is in use on the host. // Follows the same logic as kube-proxy/kube-route. // See: https://github.com/kubernetes-sigs/iptables-wrappers/blob/master/iptables-wrapper-installer.sh diff --git a/pkg/component/worker/kernelsetup.go b/pkg/component/worker/kernelsetup.go index 11b1ef6f2cb1..232d23058582 100644 --- a/pkg/component/worker/kernelsetup.go +++ b/pkg/component/worker/kernelsetup.go @@ -19,5 +19,4 @@ limitations under the License. package worker // KernelSetup comment -func KernelSetup() {} -func KernelMajorVersion() byte { return 0 } +func KernelSetup() {} diff --git a/pkg/component/worker/kernelsetup_linux.go b/pkg/component/worker/kernelsetup_linux.go index de81d06850f6..980ed1cde569 100644 --- a/pkg/component/worker/kernelsetup_linux.go +++ b/pkg/component/worker/kernelsetup_linux.go @@ -80,12 +80,3 @@ func KernelSetup() { enableSysCtl("net/bridge/bridge-nf-call-iptables") enableSysCtl("net/bridge/bridge-nf-call-ip6tables") } - -// KernelMajorVersion returns the major version number of the running kernel -func KernelMajorVersion() byte { - data, err := os.ReadFile("/proc/sys/kernel/osrelease") - if err != nil { - return 0 - } - return data[0] - '0' -} diff --git a/pkg/component/worker/kubelet.go b/pkg/component/worker/kubelet.go index 70c0102169f9..a89c2d6b76c7 100644 --- a/pkg/component/worker/kubelet.go +++ b/pkg/component/worker/kubelet.go @@ -81,46 +81,18 @@ type kubeletConfig struct { // Init extracts the needed binaries func (k *Kubelet) Init(_ context.Context) error { - cmds := []string{"kubelet", "xtables-legacy-multi", "xtables-nft-multi"} if runtime.GOOS == "windows" { - cmds = []string{"kubelet.exe"} + err := assets.Stage(k.K0sVars.BinDir, "kubelet.exe", constant.BinDirMode) + return err } - for _, cmd := range cmds { - err := assets.Stage(k.K0sVars.BinDir, cmd, constant.BinDirMode) + if runtime.GOOS == "linux" { + err, iptablesMode := iptablesutils.ExtractIPTablesBinaries(k.K0sVars.BinDir, k.IPTablesMode) if err != nil { return err } - } - - if runtime.GOOS == "linux" { - iptablesMode := k.IPTablesMode - if iptablesMode == "" || iptablesMode == "auto" { - var err error - iptablesMode, err = iptablesutils.DetectHostIPTablesMode(k.K0sVars.BinDir) - if err != nil { - if KernelMajorVersion() < 5 { - iptablesMode = iptablesutils.ModeLegacy - } else { - iptablesMode = iptablesutils.ModeNFT - } - logrus.WithError(err).Infof("Failed to detect iptables mode, using iptables-%s by default", iptablesMode) - } - } - logrus.Infof("using iptables-%s", iptablesMode) - oldpath := fmt.Sprintf("xtables-%s-multi", iptablesMode) - for _, symlink := range []string{"iptables", "iptables-save", "iptables-restore", "ip6tables", "ip6tables-save", "ip6tables-restore"} { - symlinkPath := filepath.Join(k.K0sVars.BinDir, symlink) - - // remove if it exist and ignore error if it doesn't - _ = os.Remove(symlinkPath) - - err := os.Symlink(oldpath, symlinkPath) - if err != nil { - return fmt.Errorf("failed to create symlink %s: %w", symlink, err) - } - } + k.IPTablesMode = iptablesMode } k.dataDir = filepath.Join(k.K0sVars.DataDir, "kubelet")