From c403fd4481193e3e98d8bccf2b5368484662fbd0 Mon Sep 17 00:00:00 2001 From: "Lubomir I. Ivanov" Date: Thu, 23 Oct 2025 18:22:34 +0200 Subject: [PATCH] kubeadm: validate the KubeletVersion for cgroups v1 By using k8s.io/system-validators v1.12.1 a KubeletVersion can be passed to the CgroupsValidator. The library can then decide if to throw an error or a warning. An error is thrown if the version is >= 1.35. During upgrade pass a KubeletVersion that is with MINOR+1 to account for the target upgrade version. That is just an assumption that the user will upgrade the kubelet too, but it is better to throw an error for this common use case instead of just a warning that is seen after the upgrade command has finished. --- .../app/cmd/phases/upgrade/apply/preflight.go | 2 +- .../app/cmd/phases/upgrade/node/preflight.go | 2 +- cmd/kubeadm/app/preflight/checks.go | 26 ++++++++++++++----- cmd/kubeadm/app/preflight/checks_linux.go | 7 +++-- cmd/kubeadm/app/preflight/checks_other.go | 2 +- 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/cmd/kubeadm/app/cmd/phases/upgrade/apply/preflight.go b/cmd/kubeadm/app/cmd/phases/upgrade/apply/preflight.go index ba0d8adc50f..55a387927bd 100644 --- a/cmd/kubeadm/app/cmd/phases/upgrade/apply/preflight.go +++ b/cmd/kubeadm/app/cmd/phases/upgrade/apply/preflight.go @@ -70,7 +70,7 @@ func runPreflight(c workflow.RunData) error { if err := preflight.RunRootCheckOnly(ignorePreflightErrors); err != nil { return err } - if err := preflight.RunUpgradeChecks(ignorePreflightErrors); err != nil { + if err := preflight.RunUpgradeChecks(utilsexec.New(), ignorePreflightErrors); err != nil { return err } diff --git a/cmd/kubeadm/app/cmd/phases/upgrade/node/preflight.go b/cmd/kubeadm/app/cmd/phases/upgrade/node/preflight.go index 58d06b7c284..43c35d3ecb2 100644 --- a/cmd/kubeadm/app/cmd/phases/upgrade/node/preflight.go +++ b/cmd/kubeadm/app/cmd/phases/upgrade/node/preflight.go @@ -53,7 +53,7 @@ func runPreflight(c workflow.RunData) error { if err := preflight.RunRootCheckOnly(data.IgnorePreflightErrors()); err != nil { return err } - if err := preflight.RunUpgradeChecks(data.IgnorePreflightErrors()); err != nil { + if err := preflight.RunUpgradeChecks(utilsexec.New(), data.IgnorePreflightErrors()); err != nil { return err } diff --git a/cmd/kubeadm/app/preflight/checks.go b/cmd/kubeadm/app/preflight/checks.go index 9b14682ea7b..f6cc2c47421 100644 --- a/cmd/kubeadm/app/preflight/checks.go +++ b/cmd/kubeadm/app/preflight/checks.go @@ -484,7 +484,10 @@ func (subnet HTTPProxyCIDRCheck) Check() (warnings, errorList []error) { } // SystemVerificationCheck defines struct used for running the system verification node check in test/e2e_node/system -type SystemVerificationCheck struct{} +type SystemVerificationCheck struct { + isUpgrade bool + exec utilsexec.Interface +} // Name will return SystemVerification as name for SystemVerificationCheck func (SystemVerificationCheck) Name() string { @@ -493,7 +496,7 @@ func (SystemVerificationCheck) Name() string { // Check runs all individual checks func (sysver SystemVerificationCheck) Check() (warnings, errorList []error) { - klog.V(1).Infoln("running all checks") + klog.V(1).Infoln("running system verification checks") // Create a buffered writer and choose a quite large value (1M) and suppose the output from the system verification test won't exceed the limit // Run the system verification check, but write to out buffered writer instead of stdout bufw := bufio.NewWriterSize(os.Stdout, 1*1024*1024) @@ -505,7 +508,18 @@ func (sysver SystemVerificationCheck) Check() (warnings, errorList []error) { var validators = []system.Validator{ &system.KernelValidator{Reporter: reporter}} - validators = addOSValidator(validators, reporter) + // Account for the KubeletVersion in the CgroupsValidator added + // as part of addOSValidator(). + kubeletVersion, err := GetKubeletVersion(sysver.exec) + if err != nil { + return nil, []error{errors.Wrap(err, "couldn't get kubelet version")} + } + // During upgrade we want to check the next kubelet MINOR version. + // The below approach does not support k8s MAJOR version bumps. + if sysver.isUpgrade { + kubeletVersion = kubeletVersion.WithMinor(kubeletVersion.Minor() + 1) + } + validators = addOSValidator(validators, reporter, kubeletVersion.String()) // Run all validators for _, v := range validators { @@ -1053,7 +1067,7 @@ func addCommonChecks(execer utilsexec.Interface, k8sVersion string, nodeReg *kub checks = addSwapCheck(checks) checks = addExecChecks(checks, execer, k8sVersion) checks = append(checks, - SystemVerificationCheck{}, + SystemVerificationCheck{isUpgrade: false, exec: execer}, HostnameCheck{nodeName: nodeReg.Name}, KubeletVersionCheck{KubernetesVersion: k8sVersion, exec: execer}, ServiceCheck{Service: "kubelet", CheckIfActive: false}, @@ -1071,9 +1085,9 @@ func RunRootCheckOnly(ignorePreflightErrors sets.Set[string]) error { } // RunUpgradeChecks initializes checks slice of structs and call RunChecks -func RunUpgradeChecks(ignorePreflightErrors sets.Set[string]) error { +func RunUpgradeChecks(execer utilsexec.Interface, ignorePreflightErrors sets.Set[string]) error { checks := []Checker{ - SystemVerificationCheck{}, + SystemVerificationCheck{isUpgrade: true, exec: execer}, } return RunChecks(checks, os.Stderr, ignorePreflightErrors) diff --git a/cmd/kubeadm/app/preflight/checks_linux.go b/cmd/kubeadm/app/preflight/checks_linux.go index 3e4bb702caf..e5aa7a90779 100644 --- a/cmd/kubeadm/app/preflight/checks_linux.go +++ b/cmd/kubeadm/app/preflight/checks_linux.go @@ -46,8 +46,11 @@ func (mc MemCheck) Check() (warnings, errorList []error) { } // addOSValidator adds a new OSValidator -func addOSValidator(validators []system.Validator, reporter *system.StreamReporter) []system.Validator { - validators = append(validators, &system.OSValidator{Reporter: reporter}, &system.CgroupsValidator{Reporter: reporter}) +func addOSValidator(validators []system.Validator, reporter *system.StreamReporter, kubeletVersion string) []system.Validator { + validators = append(validators, + &system.OSValidator{Reporter: reporter}, + &system.CgroupsValidator{Reporter: reporter, KubeletVersion: kubeletVersion}, + ) return validators } diff --git a/cmd/kubeadm/app/preflight/checks_other.go b/cmd/kubeadm/app/preflight/checks_other.go index d790d7d46f3..9756849ac8c 100644 --- a/cmd/kubeadm/app/preflight/checks_other.go +++ b/cmd/kubeadm/app/preflight/checks_other.go @@ -25,7 +25,7 @@ import ( // addOSValidator adds a new OSValidator // No-op for Darwin (MacOS), Windows. -func addOSValidator(validators []system.Validator, _ *system.StreamReporter) []system.Validator { +func addOSValidator(validators []system.Validator, _ *system.StreamReporter, _ string) []system.Validator { return validators }