From a14aabf21e65329468639f0806869eea8499782d Mon Sep 17 00:00:00 2001 From: Neeraj Krishna Gopalakrishna Date: Wed, 22 Oct 2025 10:20:42 +0530 Subject: [PATCH 01/12] OCPNODE-3719: Add autosizing as default --- manifests/default-autosizing-master-kubeletconfig.yaml | 9 +++++++++ manifests/default-autosizing-worker-kubeletconfig.yaml | 9 +++++++++ 2 files changed, 18 insertions(+) create mode 100644 manifests/default-autosizing-master-kubeletconfig.yaml create mode 100644 manifests/default-autosizing-worker-kubeletconfig.yaml diff --git a/manifests/default-autosizing-master-kubeletconfig.yaml b/manifests/default-autosizing-master-kubeletconfig.yaml new file mode 100644 index 0000000000..c2e09be3d7 --- /dev/null +++ b/manifests/default-autosizing-master-kubeletconfig.yaml @@ -0,0 +1,9 @@ +apiVersion: machineconfiguration.openshift.io/v1 +kind: KubeletConfig +metadata: + name: default-autosizing-master +spec: + autoSizingReserved: true + machineConfigPoolSelector: + matchLabels: + pools.operator.machineconfiguration.openshift.io/master: "" diff --git a/manifests/default-autosizing-worker-kubeletconfig.yaml b/manifests/default-autosizing-worker-kubeletconfig.yaml new file mode 100644 index 0000000000..853c774799 --- /dev/null +++ b/manifests/default-autosizing-worker-kubeletconfig.yaml @@ -0,0 +1,9 @@ +apiVersion: machineconfiguration.openshift.io/v1 +kind: KubeletConfig +metadata: + name: default-autosizing-worker +spec: + autoSizingReserved: true + machineConfigPoolSelector: + matchLabels: + pools.operator.machineconfiguration.openshift.io/worker: "" From 8a88afafdfedfca4b00d248778f5780566f83038 Mon Sep 17 00:00:00 2001 From: Neeraj Krishna Gopalakrishna Date: Wed, 22 Oct 2025 12:05:39 +0530 Subject: [PATCH 02/12] OCPNODE-3719: Add autosizing as default --- ...0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml | 0 ...0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename manifests/default-autosizing-master-kubeletconfig.yaml => install/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml (100%) rename manifests/default-autosizing-worker-kubeletconfig.yaml => install/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml (100%) diff --git a/manifests/default-autosizing-master-kubeletconfig.yaml b/install/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml similarity index 100% rename from manifests/default-autosizing-master-kubeletconfig.yaml rename to install/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml diff --git a/manifests/default-autosizing-worker-kubeletconfig.yaml b/install/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml similarity index 100% rename from manifests/default-autosizing-worker-kubeletconfig.yaml rename to install/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml From 4fd16fe3e95985eabe1bd8f667b454baf0ccd732 Mon Sep 17 00:00:00 2001 From: Neeraj Krishna Gopalakrishna Date: Wed, 22 Oct 2025 15:28:19 +0530 Subject: [PATCH 03/12] OCPNODE-3719: Add autosizing as default --- pkg/operator/operator.go | 1 + pkg/operator/sync.go | 54 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/pkg/operator/operator.go b/pkg/operator/operator.go index 5b5e31f7a0..2e9f95250c 100644 --- a/pkg/operator/operator.go +++ b/pkg/operator/operator.go @@ -509,6 +509,7 @@ func (optr *Operator) sync(key string) error { {"MachineConfiguration", optr.syncMachineConfiguration}, {"MachineConfigNode", optr.syncMachineConfigNodes}, {"MachineConfigPools", optr.syncMachineConfigPools}, + {"DefaultKubeletConfigs", optr.syncDefaultKubeletConfigs}, {"MachineConfigDaemon", optr.syncMachineConfigDaemon}, {"MachineConfigController", optr.syncMachineConfigController}, {"MachineConfigServer", optr.syncMachineConfigServer}, diff --git a/pkg/operator/sync.go b/pkg/operator/sync.go index 1cf5309f55..da5266e4d2 100644 --- a/pkg/operator/sync.go +++ b/pkg/operator/sync.go @@ -761,6 +761,60 @@ func (optr *Operator) syncMachineConfigPools(config *renderConfig, _ *configv1.C return nil } +// syncDefaultKubeletConfigs applies default autosizing KubeletConfigs for new cluster installations. +// It only applies these configs during initial cluster bringup to enable AutoSizingReserved=true +// for both master and worker pools. Upgraded clusters will not have these configs applied. +func (optr *Operator) syncDefaultKubeletConfigs(config *renderConfig, _ *configv1.ClusterOperator) error { + // Only apply default configs during initial cluster bringup + if !optr.inClusterBringup { + klog.V(4).Info("Skipping default KubeletConfig sync - cluster is not in bringup mode") + return nil + } + + klog.Info("Applying default autosizing KubeletConfigs for new installation") + + // List of default autosizing kubeletconfig manifests + defaultKubeletConfigs := []string{ + "manifests/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml", + "manifests/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml", + } + + for _, kcPath := range defaultKubeletConfigs { + // Render the manifest + kcBytes, err := renderAsset(config, kcPath) + if err != nil { + // If manifest doesn't exist in install directory, skip it + // This handles cases where the manifests may not be in the container yet + klog.Warningf("Could not render default KubeletConfig manifest %s: %v", kcPath, err) + continue + } + + // Read the KubeletConfig + kc := mcoResourceRead.ReadKubeletConfigV1OrDie(kcBytes) + + // Check if a KubeletConfig with this name already exists + _, err = optr.mckLister.Get(kc.Name) + if err == nil { + // Config already exists, skip creation + klog.V(4).Infof("Default KubeletConfig %s already exists, skipping", kc.Name) + continue + } else if !apierrors.IsNotFound(err) { + // Some other error occurred + return fmt.Errorf("error checking for existing KubeletConfig %s: %w", kc.Name, err) + } + + // Apply the KubeletConfig + _, _, err = mcoResourceApply.ApplyKubeletConfig(optr.client.MachineconfigurationV1(), kc) + if err != nil { + return fmt.Errorf("failed to apply default KubeletConfig %s: %w", kc.Name, err) + } + + klog.Infof("Successfully applied default autosizing KubeletConfig: %s", kc.Name) + } + + return nil +} + // we need to mimic this func (optr *Operator) syncMachineConfigNodes(_ *renderConfig, _ *configv1.ClusterOperator) error { if !optr.fgHandler.Enabled(features.FeatureGateMachineConfigNodes) { From e78c9b6454804ad1bfaec99f61b054312518610f Mon Sep 17 00:00:00 2001 From: Neeraj Krishna Gopalakrishna Date: Wed, 22 Oct 2025 16:07:10 +0530 Subject: [PATCH 04/12] OCPNODE-3719: Add autosizing as default --- pkg/operator/sync.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pkg/operator/sync.go b/pkg/operator/sync.go index da5266e4d2..3df605da3d 100644 --- a/pkg/operator/sync.go +++ b/pkg/operator/sync.go @@ -41,6 +41,7 @@ import ( features "github.com/openshift/api/features" mcoac "github.com/openshift/client-go/operator/applyconfigurations/operator/v1" + mcfgclientscheme "github.com/openshift/client-go/machineconfiguration/clientset/versioned/scheme" "github.com/openshift/library-go/pkg/operator/resource/resourceapply" "github.com/openshift/library-go/pkg/operator/resource/resourceread" mcoResourceApply "github.com/openshift/machine-config-operator/lib/resourceapply" @@ -789,8 +790,11 @@ func (optr *Operator) syncDefaultKubeletConfigs(config *renderConfig, _ *configv continue } - // Read the KubeletConfig - kc := mcoResourceRead.ReadKubeletConfigV1OrDie(kcBytes) + // Unmarshal the YAML into a KubeletConfig object + var kc mcfgv1.KubeletConfig + if err := runtime.DecodeInto(mcfgclientscheme.Codecs.UniversalDecoder(), kcBytes, &kc); err != nil { + return fmt.Errorf("failed to decode KubeletConfig from %s: %w", kcPath, err) + } // Check if a KubeletConfig with this name already exists _, err = optr.mckLister.Get(kc.Name) @@ -803,10 +807,10 @@ func (optr *Operator) syncDefaultKubeletConfigs(config *renderConfig, _ *configv return fmt.Errorf("error checking for existing KubeletConfig %s: %w", kc.Name, err) } - // Apply the KubeletConfig - _, _, err = mcoResourceApply.ApplyKubeletConfig(optr.client.MachineconfigurationV1(), kc) + // Create the KubeletConfig directly using the client + _, err = optr.client.MachineconfigurationV1().KubeletConfigs().Create(context.TODO(), &kc, metav1.CreateOptions{}) if err != nil { - return fmt.Errorf("failed to apply default KubeletConfig %s: %w", kc.Name, err) + return fmt.Errorf("failed to create default KubeletConfig %s: %w", kc.Name, err) } klog.Infof("Successfully applied default autosizing KubeletConfig: %s", kc.Name) From de63850ae66d84f9fe8b72953e7a9c94a73900f8 Mon Sep 17 00:00:00 2001 From: Neeraj Krishna Gopalakrishna Date: Wed, 22 Oct 2025 18:41:53 +0530 Subject: [PATCH 05/12] OCPNODE-3719: Add autosizing as default --- pkg/controller/kubelet-config/helpers.go | 2 + .../kubelet_config_bootstrap_test.go | 122 ++++++++++++++++++ pkg/operator/operator.go | 1 - pkg/operator/sync.go | 58 --------- pkg/operator/sync_test.go | 2 +- 5 files changed, 125 insertions(+), 60 deletions(-) diff --git a/pkg/controller/kubelet-config/helpers.go b/pkg/controller/kubelet-config/helpers.go index 50c0c597ab..fcf2f5cf44 100644 --- a/pkg/controller/kubelet-config/helpers.go +++ b/pkg/controller/kubelet-config/helpers.go @@ -518,9 +518,11 @@ func generateKubeletIgnFiles(kubeletConfig *mcfgv1.KubeletConfig, originalKubeCo logLevelIgnition = createNewKubeletLogLevelIgnition(*kubeletConfig.Spec.LogLevel) } if kubeletConfig.Spec.AutoSizingReserved != nil && len(userDefinedSystemReserved) == 0 { + klog.Infof("KubeletConfig %s: autoSizingReserved is set to %t", kubeletConfig.Name, *kubeletConfig.Spec.AutoSizingReserved) autoSizingReservedIgnition = createNewKubeletDynamicSystemReservedIgnition(kubeletConfig.Spec.AutoSizingReserved, userDefinedSystemReserved) } if len(userDefinedSystemReserved) > 0 { + klog.Infof("KubeletConfig %s: using user-defined systemReserved values: %v", kubeletConfig.Name, userDefinedSystemReserved) autoSizingReservedIgnition = createNewKubeletDynamicSystemReservedIgnition(nil, userDefinedSystemReserved) } diff --git a/pkg/controller/kubelet-config/kubelet_config_bootstrap_test.go b/pkg/controller/kubelet-config/kubelet_config_bootstrap_test.go index 1d83e9a5ab..df228bb5fc 100644 --- a/pkg/controller/kubelet-config/kubelet_config_bootstrap_test.go +++ b/pkg/controller/kubelet-config/kubelet_config_bootstrap_test.go @@ -242,3 +242,125 @@ func TestAddKubeletCfgAfterBootstrapKubeletCfg(t *testing.T) { }) } } + +func TestAutoSizingReservedBootstrap(t *testing.T) { + for _, platform := range []configv1.PlatformType{configv1.AWSPlatformType, configv1.NonePlatformType} { + t.Run(string(platform), func(t *testing.T) { + cc := newControllerConfig(ctrlcommon.ControllerConfigName, platform) + pools := []*mcfgv1.MachineConfigPool{ + helpers.NewMachineConfigPool("worker", nil, helpers.WorkerSelector, "v0"), + helpers.NewMachineConfigPool("master", nil, helpers.MasterSelector, "v0"), + } + + // Test with AutoSizingReserved set to true (new installation behavior) + autoSizingTrue := true + cfgs := []*mcfgv1.KubeletConfig{ + { + ObjectMeta: metav1.ObjectMeta{Name: "default-autosizing-worker"}, + Spec: mcfgv1.KubeletConfigSpec{ + AutoSizingReserved: &autoSizingTrue, + MachineConfigPoolSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "pools.operator.machineconfiguration.openshift.io/worker": "", + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "default-autosizing-master"}, + Spec: mcfgv1.KubeletConfigSpec{ + AutoSizingReserved: &autoSizingTrue, + MachineConfigPoolSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "pools.operator.machineconfiguration.openshift.io/master": "", + }, + }, + }, + }, + } + + fgHandler := ctrlcommon.NewFeatureGatesHardcodedHandler([]osev1.FeatureGateName{"Example"}, nil) + mcs, err := RunKubeletBootstrap("../../../templates", cfgs, cc, fgHandler, nil, pools, nil) + require.NoError(t, err) + require.Len(t, mcs, 2) + + // Verify that AutoSizingReserved configuration is present in the generated MachineConfigs + for _, mc := range mcs { + verifyAutoSizingReservedInMC(t, mc, true) + } + }) + } +} + +func TestAutoSizingReservedNotSetForUpgrade(t *testing.T) { + // Test scenario: Existing cluster upgrade - no KubeletConfig with AutoSizingReserved + // This simulates an upgraded cluster where the default KubeletConfig manifests don't exist + for _, platform := range []configv1.PlatformType{configv1.AWSPlatformType, configv1.NonePlatformType} { + t.Run(string(platform), func(t *testing.T) { + cc := newControllerConfig(ctrlcommon.ControllerConfigName, platform) + pools := []*mcfgv1.MachineConfigPool{ + helpers.NewMachineConfigPool("worker", nil, helpers.WorkerSelector, "v0"), + } + + // User creates a custom KubeletConfig without AutoSizingReserved (simulating upgrade scenario) + kc := newKubeletConfig("custom-config", &kubeletconfigv1beta1.KubeletConfiguration{MaxPods: 110}, + metav1.AddLabelToSelector(&metav1.LabelSelector{}, "pools.operator.machineconfiguration.openshift.io/worker", "")) + + // Verify that AutoSizingReserved is not set (nil) in the KubeletConfig before processing + require.Nil(t, kc.Spec.AutoSizingReserved) + + // Process the kubelet config via bootstrap (simulating what happens during upgrade) + fgHandler := ctrlcommon.NewFeatureGatesHardcodedHandler([]osev1.FeatureGateName{"Example"}, nil) + mcs, err := RunKubeletBootstrap("../../../templates", []*mcfgv1.KubeletConfig{kc}, cc, fgHandler, nil, pools, nil) + require.NoError(t, err) + require.Len(t, mcs, 1) + + // Verify the generated MachineConfig does not have AutoSizingReserved enabled + // since the KubeletConfig didn't specify it + verifyAutoSizingNotEnabledInMC(t, mcs[0]) + }) + } +} + +func verifyAutoSizingNotEnabledInMC(t *testing.T, mc *mcfgv1.MachineConfig) { + ignCfg, err := ctrlcommon.ParseAndConvertConfig(mc.Spec.Config.Raw) + require.NoError(t, err) + + // Look for the node-sizing-enabled.env file + for _, file := range ignCfg.Storage.Files { + if file.Path == "/etc/node-sizing-enabled.env" { + conf, err := ctrlcommon.DecodeIgnitionFileContents(file.Contents.Source, file.Contents.Compression) + require.NoError(t, err) + // If AutoSizingReserved was not explicitly set, it should be false + require.Contains(t, string(conf), "NODE_SIZING_ENABLED=false") + return + } + } + // It's also acceptable if the file doesn't exist when AutoSizingReserved is not set +} + +func verifyAutoSizingReservedInMC(t *testing.T, mc *mcfgv1.MachineConfig, expectedValue bool) { + ignCfg, err := ctrlcommon.ParseAndConvertConfig(mc.Spec.Config.Raw) + require.NoError(t, err) + + // Look for the node-sizing-enabled.env file + var foundFile bool + for _, file := range ignCfg.Storage.Files { + if file.Path == "/etc/node-sizing-enabled.env" { + foundFile = true + conf, err := ctrlcommon.DecodeIgnitionFileContents(file.Contents.Source, file.Contents.Compression) + require.NoError(t, err) + + if expectedValue { + require.Contains(t, string(conf), "NODE_SIZING_ENABLED=true") + } else { + require.Contains(t, string(conf), "NODE_SIZING_ENABLED=false") + } + break + } + } + + if expectedValue { + require.True(t, foundFile, "Expected /etc/node-sizing-enabled.env file to be present in MachineConfig") + } +} diff --git a/pkg/operator/operator.go b/pkg/operator/operator.go index 2e9f95250c..5b5e31f7a0 100644 --- a/pkg/operator/operator.go +++ b/pkg/operator/operator.go @@ -509,7 +509,6 @@ func (optr *Operator) sync(key string) error { {"MachineConfiguration", optr.syncMachineConfiguration}, {"MachineConfigNode", optr.syncMachineConfigNodes}, {"MachineConfigPools", optr.syncMachineConfigPools}, - {"DefaultKubeletConfigs", optr.syncDefaultKubeletConfigs}, {"MachineConfigDaemon", optr.syncMachineConfigDaemon}, {"MachineConfigController", optr.syncMachineConfigController}, {"MachineConfigServer", optr.syncMachineConfigServer}, diff --git a/pkg/operator/sync.go b/pkg/operator/sync.go index 3df605da3d..1cf5309f55 100644 --- a/pkg/operator/sync.go +++ b/pkg/operator/sync.go @@ -41,7 +41,6 @@ import ( features "github.com/openshift/api/features" mcoac "github.com/openshift/client-go/operator/applyconfigurations/operator/v1" - mcfgclientscheme "github.com/openshift/client-go/machineconfiguration/clientset/versioned/scheme" "github.com/openshift/library-go/pkg/operator/resource/resourceapply" "github.com/openshift/library-go/pkg/operator/resource/resourceread" mcoResourceApply "github.com/openshift/machine-config-operator/lib/resourceapply" @@ -762,63 +761,6 @@ func (optr *Operator) syncMachineConfigPools(config *renderConfig, _ *configv1.C return nil } -// syncDefaultKubeletConfigs applies default autosizing KubeletConfigs for new cluster installations. -// It only applies these configs during initial cluster bringup to enable AutoSizingReserved=true -// for both master and worker pools. Upgraded clusters will not have these configs applied. -func (optr *Operator) syncDefaultKubeletConfigs(config *renderConfig, _ *configv1.ClusterOperator) error { - // Only apply default configs during initial cluster bringup - if !optr.inClusterBringup { - klog.V(4).Info("Skipping default KubeletConfig sync - cluster is not in bringup mode") - return nil - } - - klog.Info("Applying default autosizing KubeletConfigs for new installation") - - // List of default autosizing kubeletconfig manifests - defaultKubeletConfigs := []string{ - "manifests/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml", - "manifests/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml", - } - - for _, kcPath := range defaultKubeletConfigs { - // Render the manifest - kcBytes, err := renderAsset(config, kcPath) - if err != nil { - // If manifest doesn't exist in install directory, skip it - // This handles cases where the manifests may not be in the container yet - klog.Warningf("Could not render default KubeletConfig manifest %s: %v", kcPath, err) - continue - } - - // Unmarshal the YAML into a KubeletConfig object - var kc mcfgv1.KubeletConfig - if err := runtime.DecodeInto(mcfgclientscheme.Codecs.UniversalDecoder(), kcBytes, &kc); err != nil { - return fmt.Errorf("failed to decode KubeletConfig from %s: %w", kcPath, err) - } - - // Check if a KubeletConfig with this name already exists - _, err = optr.mckLister.Get(kc.Name) - if err == nil { - // Config already exists, skip creation - klog.V(4).Infof("Default KubeletConfig %s already exists, skipping", kc.Name) - continue - } else if !apierrors.IsNotFound(err) { - // Some other error occurred - return fmt.Errorf("error checking for existing KubeletConfig %s: %w", kc.Name, err) - } - - // Create the KubeletConfig directly using the client - _, err = optr.client.MachineconfigurationV1().KubeletConfigs().Create(context.TODO(), &kc, metav1.CreateOptions{}) - if err != nil { - return fmt.Errorf("failed to create default KubeletConfig %s: %w", kc.Name, err) - } - - klog.Infof("Successfully applied default autosizing KubeletConfig: %s", kc.Name) - } - - return nil -} - // we need to mimic this func (optr *Operator) syncMachineConfigNodes(_ *renderConfig, _ *configv1.ClusterOperator) error { if !optr.fgHandler.Enabled(features.FeatureGateMachineConfigNodes) { diff --git a/pkg/operator/sync_test.go b/pkg/operator/sync_test.go index 158f262c38..c69e7fd6ce 100644 --- a/pkg/operator/sync_test.go +++ b/pkg/operator/sync_test.go @@ -402,4 +402,4 @@ func buildMachineConfigurationWithBootImageUpdateEnabled() *opv1.MachineConfigur func buildMachineConfigurationWithNoBootImageConfiguration() *opv1.MachineConfiguration { return &opv1.MachineConfiguration{Spec: opv1.MachineConfigurationSpec{ManagedBootImages: apihelpers.GetManagedBootImagesWithNoConfiguration()}, ObjectMeta: metav1.ObjectMeta{Name: "cluster"}} -} +} \ No newline at end of file From 2dbdd4710e4debf86d09962b013ebbb2dce5a986 Mon Sep 17 00:00:00 2001 From: Neeraj Krishna Gopalakrishna Date: Wed, 22 Oct 2025 21:34:52 +0530 Subject: [PATCH 06/12] OCPNODE-3719: Add autosizing as default --- pkg/controller/bootstrap/bootstrap.go | 7 +++++++ pkg/controller/kubelet-config/helpers.go | 10 ++++++++++ .../kubelet-config/kubelet_config_bootstrap.go | 8 ++++++++ 3 files changed, 25 insertions(+) diff --git a/pkg/controller/bootstrap/bootstrap.go b/pkg/controller/bootstrap/bootstrap.go index ac7d92dfcc..edc0f0b57c 100644 --- a/pkg/controller/bootstrap/bootstrap.go +++ b/pkg/controller/bootstrap/bootstrap.go @@ -226,11 +226,18 @@ func (b *Bootstrap) Run(destDir string) error { klog.Infof("Successfully generated MachineConfigs from node.Configs.") if len(kconfigs) > 0 { + klog.Infof("Bootstrap: found %d KubeletConfig(s) in manifests, processing...", len(kconfigs)) + for i, kc := range kconfigs { + klog.Infof("Bootstrap: KubeletConfig[%d]: name=%s, autoSizingReserved=%v", i, kc.Name, kc.Spec.AutoSizingReserved) + } kconfigs, err := kubeletconfig.RunKubeletBootstrap(b.templatesDir, kconfigs, cconfig, fgHandler, nodeConfig, pools, apiServer) if err != nil { return err } configs = append(configs, kconfigs...) + klog.Infof("Bootstrap: successfully generated %d MachineConfig(s) from KubeletConfigs", len(kconfigs)) + } else { + klog.Infof("Bootstrap: no KubeletConfigs found in manifests, skipping kubelet config bootstrap") } klog.Infof("Successfully generated MachineConfigs from kubelet configs.") diff --git a/pkg/controller/kubelet-config/helpers.go b/pkg/controller/kubelet-config/helpers.go index fcf2f5cf44..f679782cab 100644 --- a/pkg/controller/kubelet-config/helpers.go +++ b/pkg/controller/kubelet-config/helpers.go @@ -461,6 +461,7 @@ func kubeletConfigToIgnFile(cfg *kubeletconfigv1beta1.KubeletConfiguration) (*ig // generateKubeletIgnFiles generates the Ignition files from the kubelet config func generateKubeletIgnFiles(kubeletConfig *mcfgv1.KubeletConfig, originalKubeConfig *kubeletconfigv1beta1.KubeletConfiguration) (*ign3types.File, *ign3types.File, *ign3types.File, error) { + klog.Infof("generateKubeletIgnFiles: starting for KubeletConfig %s", kubeletConfig.Name) var ( kubeletIgnition *ign3types.File logLevelIgnition *ign3types.File @@ -469,6 +470,7 @@ func generateKubeletIgnFiles(kubeletConfig *mcfgv1.KubeletConfig, originalKubeCo userDefinedSystemReserved := make(map[string]string) if kubeletConfig.Spec.KubeletConfig != nil && kubeletConfig.Spec.KubeletConfig.Raw != nil { + klog.Infof("generateKubeletIgnFiles: KubeletConfig %s has custom kubelet config, decoding", kubeletConfig.Name) specKubeletConfig, err := DecodeKubeletConfig(kubeletConfig.Spec.KubeletConfig.Raw) if err != nil { return nil, nil, nil, fmt.Errorf("could not deserialize the new Kubelet config: %w", err) @@ -477,16 +479,19 @@ func generateKubeletIgnFiles(kubeletConfig *mcfgv1.KubeletConfig, originalKubeCo if val, ok := specKubeletConfig.SystemReserved["memory"]; ok { userDefinedSystemReserved["memory"] = val delete(specKubeletConfig.SystemReserved, "memory") + klog.Infof("generateKubeletIgnFiles: KubeletConfig %s has user-defined systemReserved memory: %s", kubeletConfig.Name, val) } if val, ok := specKubeletConfig.SystemReserved["cpu"]; ok { userDefinedSystemReserved["cpu"] = val delete(specKubeletConfig.SystemReserved, "cpu") + klog.Infof("generateKubeletIgnFiles: KubeletConfig %s has user-defined systemReserved cpu: %s", kubeletConfig.Name, val) } if val, ok := specKubeletConfig.SystemReserved["ephemeral-storage"]; ok { userDefinedSystemReserved["ephemeral-storage"] = val delete(specKubeletConfig.SystemReserved, "ephemeral-storage") + klog.Infof("generateKubeletIgnFiles: KubeletConfig %s has user-defined systemReserved ephemeral-storage: %s", kubeletConfig.Name, val) } // FeatureGates must be set from the FeatureGate. @@ -502,6 +507,7 @@ func generateKubeletIgnFiles(kubeletConfig *mcfgv1.KubeletConfig, originalKubeCo originalKubeConfig.ProtectKernelDefaults = false } // Merge the Old and New + klog.Infof("generateKubeletIgnFiles: merging custom kubelet config for KubeletConfig %s", kubeletConfig.Name) err = mergo.Merge(originalKubeConfig, specKubeletConfig, mergo.WithOverride) if err != nil { return nil, nil, nil, fmt.Errorf("could not merge original config and new config: %w", err) @@ -509,12 +515,14 @@ func generateKubeletIgnFiles(kubeletConfig *mcfgv1.KubeletConfig, originalKubeCo } // Encode the new config into an Ignition File + klog.Infof("generateKubeletIgnFiles: encoding kubelet config to ignition file for KubeletConfig %s", kubeletConfig.Name) kubeletIgnition, err := kubeletConfigToIgnFile(originalKubeConfig) if err != nil { return nil, nil, nil, fmt.Errorf("could not encode JSON: %w", err) } if kubeletConfig.Spec.LogLevel != nil { + klog.Infof("generateKubeletIgnFiles: creating log level ignition for KubeletConfig %s with level %d", kubeletConfig.Name, *kubeletConfig.Spec.LogLevel) logLevelIgnition = createNewKubeletLogLevelIgnition(*kubeletConfig.Spec.LogLevel) } if kubeletConfig.Spec.AutoSizingReserved != nil && len(userDefinedSystemReserved) == 0 { @@ -526,5 +534,7 @@ func generateKubeletIgnFiles(kubeletConfig *mcfgv1.KubeletConfig, originalKubeCo autoSizingReservedIgnition = createNewKubeletDynamicSystemReservedIgnition(nil, userDefinedSystemReserved) } + klog.Infof("generateKubeletIgnFiles: completed for KubeletConfig %s (kubeletIgnition=%v, logLevelIgnition=%v, autoSizingReservedIgnition=%v)", + kubeletConfig.Name, kubeletIgnition != nil, logLevelIgnition != nil, autoSizingReservedIgnition != nil) return kubeletIgnition, logLevelIgnition, autoSizingReservedIgnition, nil } diff --git a/pkg/controller/kubelet-config/kubelet_config_bootstrap.go b/pkg/controller/kubelet-config/kubelet_config_bootstrap.go index 2dced82bab..be10f008b2 100644 --- a/pkg/controller/kubelet-config/kubelet_config_bootstrap.go +++ b/pkg/controller/kubelet-config/kubelet_config_bootstrap.go @@ -10,6 +10,7 @@ import ( "github.com/openshift/machine-config-operator/pkg/version" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/klog/v2" ) // RunKubeletBootstrap generates MachineConfig objects for mcpPools that would have been generated by syncKubeletConfig @@ -18,6 +19,7 @@ func RunKubeletBootstrap(templateDir string, kubeletConfigs []*mcfgv1.KubeletCon managedKeyExist := make(map[string]bool) // Validate the KubeletConfig CR if exists for _, kubeletConfig := range kubeletConfigs { + klog.Infof("RunKubeletBootstrap: validating KubeletConfig %s", kubeletConfig.Name) if err := validateUserKubeletConfig(kubeletConfig); err != nil { return nil, err } @@ -26,6 +28,7 @@ func RunKubeletBootstrap(templateDir string, kubeletConfigs []*mcfgv1.KubeletCon nodeConfig = createNewDefaultNodeconfig() } for _, kubeletConfig := range kubeletConfigs { + klog.Infof("RunKubeletBootstrap: processing KubeletConfig %s with autoSizingReserved=%v", kubeletConfig.Name, kubeletConfig.Spec.AutoSizingReserved) // use selector since label matching part of a KubeletConfig is not handled during the bootstrap selector, err := metav1.LabelSelectorAsSelector(kubeletConfig.Spec.MachineConfigPoolSelector) if err != nil { @@ -33,22 +36,27 @@ func RunKubeletBootstrap(templateDir string, kubeletConfigs []*mcfgv1.KubeletCon } for _, pool := range mcpPools { + klog.Infof("RunKubeletBootstrap: checking pool %s for KubeletConfig %s", pool.Name, kubeletConfig.Name) // If a pool with a nil or empty selector creeps in, it should match nothing, not everything. // skip the pool if no matched label for kubeletconfig if selector.Empty() || !selector.Matches(labels.Set(pool.Labels)) { + klog.Infof("RunKubeletBootstrap: pool %s does not match selector for KubeletConfig %s, skipping", pool.Name, kubeletConfig.Name) continue } role := pool.Name + klog.Infof("RunKubeletBootstrap: pool %s matches KubeletConfig %s, generating MachineConfig", pool.Name, kubeletConfig.Name) originalKubeConfig, err := generateOriginalKubeletConfigWithFeatureGates(controllerConfig, templateDir, role, fgHandler, apiServer) if err != nil { return nil, err } + klog.Infof("RunKubeletBootstrap: generated original kubelet config for role %s", role) // updating the originalKubeConfig based on the nodeConfig on a worker node if role == ctrlcommon.MachineConfigPoolWorker { updateOriginalKubeConfigwithNodeConfig(nodeConfig, originalKubeConfig) } if kubeletConfig.Spec.TLSSecurityProfile != nil { + klog.Infof("RunKubeletBootstrap: applying TLS security profile for KubeletConfig %s", kubeletConfig.Name) // Inject TLS Options from Spec observedMinTLSVersion, observedCipherSuites := ctrlcommon.GetSecurityProfileCiphers(kubeletConfig.Spec.TLSSecurityProfile) originalKubeConfig.TLSMinVersion = observedMinTLSVersion From 78f6c2ff6d24522417ba1bd4b0305cd48c4b3543 Mon Sep 17 00:00:00 2001 From: Neeraj Krishna Gopalakrishna Date: Thu, 23 Oct 2025 06:46:20 +0530 Subject: [PATCH 07/12] OCPNODE-3719: Add autosizing as default --- ...00_80_machine-config_07_master-kubeletconfig-autosizing.yaml | 2 +- ...00_80_machine-config_07_worker-kubeletconfig-autosizing.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/install/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml b/install/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml index c2e09be3d7..76af6dc299 100644 --- a/install/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml +++ b/install/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml @@ -3,7 +3,7 @@ kind: KubeletConfig metadata: name: default-autosizing-master spec: - autoSizingReserved: true + autoSizingReserved: false machineConfigPoolSelector: matchLabels: pools.operator.machineconfiguration.openshift.io/master: "" diff --git a/install/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml b/install/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml index 853c774799..73b057e7ae 100644 --- a/install/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml +++ b/install/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml @@ -3,7 +3,7 @@ kind: KubeletConfig metadata: name: default-autosizing-worker spec: - autoSizingReserved: true + autoSizingReserved: false machineConfigPoolSelector: matchLabels: pools.operator.machineconfiguration.openshift.io/worker: "" From d7d5846efbda870039cd6fe27c0fa8a3ff2acacd Mon Sep 17 00:00:00 2001 From: Neeraj Krishna Gopalakrishna Date: Thu, 23 Oct 2025 12:53:41 +0530 Subject: [PATCH 08/12] OCPNODE-3719: Add autosizing as default --- ...00_80_machine-config_07_master-kubeletconfig-autosizing.yaml | 2 +- ...00_80_machine-config_07_worker-kubeletconfig-autosizing.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/install/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml b/install/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml index 76af6dc299..c2e09be3d7 100644 --- a/install/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml +++ b/install/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml @@ -3,7 +3,7 @@ kind: KubeletConfig metadata: name: default-autosizing-master spec: - autoSizingReserved: false + autoSizingReserved: true machineConfigPoolSelector: matchLabels: pools.operator.machineconfiguration.openshift.io/master: "" diff --git a/install/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml b/install/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml index 73b057e7ae..853c774799 100644 --- a/install/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml +++ b/install/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml @@ -3,7 +3,7 @@ kind: KubeletConfig metadata: name: default-autosizing-worker spec: - autoSizingReserved: false + autoSizingReserved: true machineConfigPoolSelector: matchLabels: pools.operator.machineconfiguration.openshift.io/worker: "" From 37084913b37b9903b96311405f2879a92705c995 Mon Sep 17 00:00:00 2001 From: Neeraj Krishna Gopalakrishna Date: Thu, 23 Oct 2025 18:37:49 +0530 Subject: [PATCH 09/12] OCPNODE-3719: Add autosizing as default --- ...ig_07_master-kubeletconfig-autosizing.yaml | 9 --------- ...ig_07_worker-kubeletconfig-autosizing.yaml | 9 --------- pkg/daemon/update.go | 19 +++++++++++-------- .../kubelet-auto-node-sizing-enabled.yaml | 4 ++-- .../units/kubelet-auto-node-size.service.yaml | 3 ++- 5 files changed, 15 insertions(+), 29 deletions(-) delete mode 100644 install/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml delete mode 100644 install/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml diff --git a/install/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml b/install/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml deleted file mode 100644 index c2e09be3d7..0000000000 --- a/install/0000_80_machine-config_07_master-kubeletconfig-autosizing.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: machineconfiguration.openshift.io/v1 -kind: KubeletConfig -metadata: - name: default-autosizing-master -spec: - autoSizingReserved: true - machineConfigPoolSelector: - matchLabels: - pools.operator.machineconfiguration.openshift.io/master: "" diff --git a/install/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml b/install/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml deleted file mode 100644 index 853c774799..0000000000 --- a/install/0000_80_machine-config_07_worker-kubeletconfig-autosizing.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: machineconfiguration.openshift.io/v1 -kind: KubeletConfig -metadata: - name: default-autosizing-worker -spec: - autoSizingReserved: true - machineConfigPoolSelector: - matchLabels: - pools.operator.machineconfiguration.openshift.io/worker: "" diff --git a/pkg/daemon/update.go b/pkg/daemon/update.go index e7c91edcd3..b03bff4569 100644 --- a/pkg/daemon/update.go +++ b/pkg/daemon/update.go @@ -1863,27 +1863,30 @@ func (dn *Daemon) deleteStaleData(oldIgnConfig, newIgnConfig ign3types.Config) e newFileSet[f.Path] = struct{}{} } - // need to skip these on upgrade if they are in a MC, or else we will remove all certs! - certsToSkip := []string{ + // need to skip these on upgrade if they are in a MC, + // or else we will remove all certs! + // also required to ensure that clusters with node sizing disabled are not affected + filesToSkip := []string{ userCABundleFilePath, caBundleFilePath, cloudCABundleFilePath, + "/etc/node-sizing-enabled.env", } for _, f := range oldIgnConfig.Storage.Files { if _, ok := newFileSet[f.Path]; ok { continue } - skipBecauseCert := false - for _, cert := range certsToSkip { - if cert == f.Path { - skipBecauseCert = true + mustSkip := false + for _, fileToSkip := range filesToSkip { + if fileToSkip == f.Path { + mustSkip = true break } } if strings.Contains(filepath.Dir(f.Path), imageCAFilePath) { - skipBecauseCert = true + mustSkip = true } - if skipBecauseCert { + if mustSkip { continue } if _, err := os.Stat(noOrigFileStampName(f.Path)); err == nil { diff --git a/templates/common/_base/files/kubelet-auto-node-sizing-enabled.yaml b/templates/common/_base/files/kubelet-auto-node-sizing-enabled.yaml index d1c72a540f..1d9a1ba5cc 100644 --- a/templates/common/_base/files/kubelet-auto-node-sizing-enabled.yaml +++ b/templates/common/_base/files/kubelet-auto-node-sizing-enabled.yaml @@ -1,8 +1,8 @@ mode: 0644 -path: "/etc/node-sizing-enabled.env" +path: "/etc/auto-node-sizing-enabled.env" contents: inline: | - NODE_SIZING_ENABLED=false + NODE_SIZING_ENABLED=true SYSTEM_RESERVED_MEMORY=1Gi SYSTEM_RESERVED_CPU=500m SYSTEM_RESERVED_ES=1Gi \ No newline at end of file diff --git a/templates/common/_base/units/kubelet-auto-node-size.service.yaml b/templates/common/_base/units/kubelet-auto-node-size.service.yaml index 4c5dd79072..e48f611ce9 100644 --- a/templates/common/_base/units/kubelet-auto-node-size.service.yaml +++ b/templates/common/_base/units/kubelet-auto-node-size.service.yaml @@ -11,7 +11,8 @@ contents: | # Need oneshot to delay kubelet Type=oneshot RemainAfterExit=yes - EnvironmentFile=/etc/node-sizing-enabled.env + EnvironmentFile=/etc/auto-node-sizing-enabled.env + EnvironmentFile=-/etc/node-sizing-enabled.env ExecStart=/bin/bash /usr/local/sbin/dynamic-system-reserved-calc.sh ${NODE_SIZING_ENABLED} ${SYSTEM_RESERVED_MEMORY} ${SYSTEM_RESERVED_CPU} ${SYSTEM_RESERVED_ES} [Install] RequiredBy=kubelet-dependencies.target From 18277073224ea2b7828d9cca7601dd5d3427f9b6 Mon Sep 17 00:00:00 2001 From: Neeraj Krishna Gopalakrishna Date: Thu, 23 Oct 2025 18:39:51 +0530 Subject: [PATCH 10/12] OCPNODE-3719: Add autosizing as default --- pkg/controller/kubelet-config/helpers.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pkg/controller/kubelet-config/helpers.go b/pkg/controller/kubelet-config/helpers.go index f679782cab..3550438c9a 100644 --- a/pkg/controller/kubelet-config/helpers.go +++ b/pkg/controller/kubelet-config/helpers.go @@ -42,7 +42,7 @@ func createNewKubeletDynamicSystemReservedIgnition(autoSystemReserved *bool, use var systemReservedEphemeralStorage string if autoSystemReserved == nil { - autoNodeSizing = "false" + autoNodeSizing = "true" } else { autoNodeSizing = strconv.FormatBool(*autoSystemReserved) } @@ -68,7 +68,7 @@ func createNewKubeletDynamicSystemReservedIgnition(autoSystemReserved *bool, use config := fmt.Sprintf("NODE_SIZING_ENABLED=%s\nSYSTEM_RESERVED_MEMORY=%s\nSYSTEM_RESERVED_CPU=%s\nSYSTEM_RESERVED_ES=%s\n", autoNodeSizing, systemReservedMemory, systemReservedCPU, systemReservedEphemeralStorage) - r := ctrlcommon.NewIgnFileBytesOverwriting("/etc/node-sizing-enabled.env", []byte(config)) + r := ctrlcommon.NewIgnFileBytesOverwriting("/etc/auto-node-sizing-enabled.env", []byte(config)) return &r } @@ -528,8 +528,7 @@ func generateKubeletIgnFiles(kubeletConfig *mcfgv1.KubeletConfig, originalKubeCo if kubeletConfig.Spec.AutoSizingReserved != nil && len(userDefinedSystemReserved) == 0 { klog.Infof("KubeletConfig %s: autoSizingReserved is set to %t", kubeletConfig.Name, *kubeletConfig.Spec.AutoSizingReserved) autoSizingReservedIgnition = createNewKubeletDynamicSystemReservedIgnition(kubeletConfig.Spec.AutoSizingReserved, userDefinedSystemReserved) - } - if len(userDefinedSystemReserved) > 0 { + } else if len(userDefinedSystemReserved) > 0 { klog.Infof("KubeletConfig %s: using user-defined systemReserved values: %v", kubeletConfig.Name, userDefinedSystemReserved) autoSizingReservedIgnition = createNewKubeletDynamicSystemReservedIgnition(nil, userDefinedSystemReserved) } From a995643e5ba89c31df23fe83afbc69155c38d973 Mon Sep 17 00:00:00 2001 From: Neeraj Krishna Gopalakrishna Date: Thu, 23 Oct 2025 18:45:15 +0530 Subject: [PATCH 11/12] OCPNODE-3719: Add autosizing as default --- .../kubelet_config_bootstrap.go | 8 -- .../kubelet_config_bootstrap_test.go | 122 ------------------ 2 files changed, 130 deletions(-) diff --git a/pkg/controller/kubelet-config/kubelet_config_bootstrap.go b/pkg/controller/kubelet-config/kubelet_config_bootstrap.go index be10f008b2..2dced82bab 100644 --- a/pkg/controller/kubelet-config/kubelet_config_bootstrap.go +++ b/pkg/controller/kubelet-config/kubelet_config_bootstrap.go @@ -10,7 +10,6 @@ import ( "github.com/openshift/machine-config-operator/pkg/version" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - "k8s.io/klog/v2" ) // RunKubeletBootstrap generates MachineConfig objects for mcpPools that would have been generated by syncKubeletConfig @@ -19,7 +18,6 @@ func RunKubeletBootstrap(templateDir string, kubeletConfigs []*mcfgv1.KubeletCon managedKeyExist := make(map[string]bool) // Validate the KubeletConfig CR if exists for _, kubeletConfig := range kubeletConfigs { - klog.Infof("RunKubeletBootstrap: validating KubeletConfig %s", kubeletConfig.Name) if err := validateUserKubeletConfig(kubeletConfig); err != nil { return nil, err } @@ -28,7 +26,6 @@ func RunKubeletBootstrap(templateDir string, kubeletConfigs []*mcfgv1.KubeletCon nodeConfig = createNewDefaultNodeconfig() } for _, kubeletConfig := range kubeletConfigs { - klog.Infof("RunKubeletBootstrap: processing KubeletConfig %s with autoSizingReserved=%v", kubeletConfig.Name, kubeletConfig.Spec.AutoSizingReserved) // use selector since label matching part of a KubeletConfig is not handled during the bootstrap selector, err := metav1.LabelSelectorAsSelector(kubeletConfig.Spec.MachineConfigPoolSelector) if err != nil { @@ -36,27 +33,22 @@ func RunKubeletBootstrap(templateDir string, kubeletConfigs []*mcfgv1.KubeletCon } for _, pool := range mcpPools { - klog.Infof("RunKubeletBootstrap: checking pool %s for KubeletConfig %s", pool.Name, kubeletConfig.Name) // If a pool with a nil or empty selector creeps in, it should match nothing, not everything. // skip the pool if no matched label for kubeletconfig if selector.Empty() || !selector.Matches(labels.Set(pool.Labels)) { - klog.Infof("RunKubeletBootstrap: pool %s does not match selector for KubeletConfig %s, skipping", pool.Name, kubeletConfig.Name) continue } role := pool.Name - klog.Infof("RunKubeletBootstrap: pool %s matches KubeletConfig %s, generating MachineConfig", pool.Name, kubeletConfig.Name) originalKubeConfig, err := generateOriginalKubeletConfigWithFeatureGates(controllerConfig, templateDir, role, fgHandler, apiServer) if err != nil { return nil, err } - klog.Infof("RunKubeletBootstrap: generated original kubelet config for role %s", role) // updating the originalKubeConfig based on the nodeConfig on a worker node if role == ctrlcommon.MachineConfigPoolWorker { updateOriginalKubeConfigwithNodeConfig(nodeConfig, originalKubeConfig) } if kubeletConfig.Spec.TLSSecurityProfile != nil { - klog.Infof("RunKubeletBootstrap: applying TLS security profile for KubeletConfig %s", kubeletConfig.Name) // Inject TLS Options from Spec observedMinTLSVersion, observedCipherSuites := ctrlcommon.GetSecurityProfileCiphers(kubeletConfig.Spec.TLSSecurityProfile) originalKubeConfig.TLSMinVersion = observedMinTLSVersion diff --git a/pkg/controller/kubelet-config/kubelet_config_bootstrap_test.go b/pkg/controller/kubelet-config/kubelet_config_bootstrap_test.go index df228bb5fc..1d83e9a5ab 100644 --- a/pkg/controller/kubelet-config/kubelet_config_bootstrap_test.go +++ b/pkg/controller/kubelet-config/kubelet_config_bootstrap_test.go @@ -242,125 +242,3 @@ func TestAddKubeletCfgAfterBootstrapKubeletCfg(t *testing.T) { }) } } - -func TestAutoSizingReservedBootstrap(t *testing.T) { - for _, platform := range []configv1.PlatformType{configv1.AWSPlatformType, configv1.NonePlatformType} { - t.Run(string(platform), func(t *testing.T) { - cc := newControllerConfig(ctrlcommon.ControllerConfigName, platform) - pools := []*mcfgv1.MachineConfigPool{ - helpers.NewMachineConfigPool("worker", nil, helpers.WorkerSelector, "v0"), - helpers.NewMachineConfigPool("master", nil, helpers.MasterSelector, "v0"), - } - - // Test with AutoSizingReserved set to true (new installation behavior) - autoSizingTrue := true - cfgs := []*mcfgv1.KubeletConfig{ - { - ObjectMeta: metav1.ObjectMeta{Name: "default-autosizing-worker"}, - Spec: mcfgv1.KubeletConfigSpec{ - AutoSizingReserved: &autoSizingTrue, - MachineConfigPoolSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "pools.operator.machineconfiguration.openshift.io/worker": "", - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "default-autosizing-master"}, - Spec: mcfgv1.KubeletConfigSpec{ - AutoSizingReserved: &autoSizingTrue, - MachineConfigPoolSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "pools.operator.machineconfiguration.openshift.io/master": "", - }, - }, - }, - }, - } - - fgHandler := ctrlcommon.NewFeatureGatesHardcodedHandler([]osev1.FeatureGateName{"Example"}, nil) - mcs, err := RunKubeletBootstrap("../../../templates", cfgs, cc, fgHandler, nil, pools, nil) - require.NoError(t, err) - require.Len(t, mcs, 2) - - // Verify that AutoSizingReserved configuration is present in the generated MachineConfigs - for _, mc := range mcs { - verifyAutoSizingReservedInMC(t, mc, true) - } - }) - } -} - -func TestAutoSizingReservedNotSetForUpgrade(t *testing.T) { - // Test scenario: Existing cluster upgrade - no KubeletConfig with AutoSizingReserved - // This simulates an upgraded cluster where the default KubeletConfig manifests don't exist - for _, platform := range []configv1.PlatformType{configv1.AWSPlatformType, configv1.NonePlatformType} { - t.Run(string(platform), func(t *testing.T) { - cc := newControllerConfig(ctrlcommon.ControllerConfigName, platform) - pools := []*mcfgv1.MachineConfigPool{ - helpers.NewMachineConfigPool("worker", nil, helpers.WorkerSelector, "v0"), - } - - // User creates a custom KubeletConfig without AutoSizingReserved (simulating upgrade scenario) - kc := newKubeletConfig("custom-config", &kubeletconfigv1beta1.KubeletConfiguration{MaxPods: 110}, - metav1.AddLabelToSelector(&metav1.LabelSelector{}, "pools.operator.machineconfiguration.openshift.io/worker", "")) - - // Verify that AutoSizingReserved is not set (nil) in the KubeletConfig before processing - require.Nil(t, kc.Spec.AutoSizingReserved) - - // Process the kubelet config via bootstrap (simulating what happens during upgrade) - fgHandler := ctrlcommon.NewFeatureGatesHardcodedHandler([]osev1.FeatureGateName{"Example"}, nil) - mcs, err := RunKubeletBootstrap("../../../templates", []*mcfgv1.KubeletConfig{kc}, cc, fgHandler, nil, pools, nil) - require.NoError(t, err) - require.Len(t, mcs, 1) - - // Verify the generated MachineConfig does not have AutoSizingReserved enabled - // since the KubeletConfig didn't specify it - verifyAutoSizingNotEnabledInMC(t, mcs[0]) - }) - } -} - -func verifyAutoSizingNotEnabledInMC(t *testing.T, mc *mcfgv1.MachineConfig) { - ignCfg, err := ctrlcommon.ParseAndConvertConfig(mc.Spec.Config.Raw) - require.NoError(t, err) - - // Look for the node-sizing-enabled.env file - for _, file := range ignCfg.Storage.Files { - if file.Path == "/etc/node-sizing-enabled.env" { - conf, err := ctrlcommon.DecodeIgnitionFileContents(file.Contents.Source, file.Contents.Compression) - require.NoError(t, err) - // If AutoSizingReserved was not explicitly set, it should be false - require.Contains(t, string(conf), "NODE_SIZING_ENABLED=false") - return - } - } - // It's also acceptable if the file doesn't exist when AutoSizingReserved is not set -} - -func verifyAutoSizingReservedInMC(t *testing.T, mc *mcfgv1.MachineConfig, expectedValue bool) { - ignCfg, err := ctrlcommon.ParseAndConvertConfig(mc.Spec.Config.Raw) - require.NoError(t, err) - - // Look for the node-sizing-enabled.env file - var foundFile bool - for _, file := range ignCfg.Storage.Files { - if file.Path == "/etc/node-sizing-enabled.env" { - foundFile = true - conf, err := ctrlcommon.DecodeIgnitionFileContents(file.Contents.Source, file.Contents.Compression) - require.NoError(t, err) - - if expectedValue { - require.Contains(t, string(conf), "NODE_SIZING_ENABLED=true") - } else { - require.Contains(t, string(conf), "NODE_SIZING_ENABLED=false") - } - break - } - } - - if expectedValue { - require.True(t, foundFile, "Expected /etc/node-sizing-enabled.env file to be present in MachineConfig") - } -} From c3406c5bc8b8b1b915070e5e952c549857df7186 Mon Sep 17 00:00:00 2001 From: Neeraj Krishna Gopalakrishna Date: Thu, 23 Oct 2025 18:47:05 +0530 Subject: [PATCH 12/12] OCPNODE-3719: Add autosizing as default --- pkg/controller/bootstrap/bootstrap.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pkg/controller/bootstrap/bootstrap.go b/pkg/controller/bootstrap/bootstrap.go index edc0f0b57c..ac7d92dfcc 100644 --- a/pkg/controller/bootstrap/bootstrap.go +++ b/pkg/controller/bootstrap/bootstrap.go @@ -226,18 +226,11 @@ func (b *Bootstrap) Run(destDir string) error { klog.Infof("Successfully generated MachineConfigs from node.Configs.") if len(kconfigs) > 0 { - klog.Infof("Bootstrap: found %d KubeletConfig(s) in manifests, processing...", len(kconfigs)) - for i, kc := range kconfigs { - klog.Infof("Bootstrap: KubeletConfig[%d]: name=%s, autoSizingReserved=%v", i, kc.Name, kc.Spec.AutoSizingReserved) - } kconfigs, err := kubeletconfig.RunKubeletBootstrap(b.templatesDir, kconfigs, cconfig, fgHandler, nodeConfig, pools, apiServer) if err != nil { return err } configs = append(configs, kconfigs...) - klog.Infof("Bootstrap: successfully generated %d MachineConfig(s) from KubeletConfigs", len(kconfigs)) - } else { - klog.Infof("Bootstrap: no KubeletConfigs found in manifests, skipping kubelet config bootstrap") } klog.Infof("Successfully generated MachineConfigs from kubelet configs.")