@@ -42,6 +42,7 @@ import (
42
42
mcfglistersv1 "github.com/openshift/client-go/machineconfiguration/listers/machineconfiguration/v1"
43
43
"github.com/openshift/library-go/pkg/operator/configobserver/featuregates"
44
44
"github.com/openshift/machine-config-operator/pkg/apihelpers"
45
+ "github.com/openshift/machine-config-operator/pkg/constants"
45
46
ctrlcommon "github.com/openshift/machine-config-operator/pkg/controller/common"
46
47
mtmpl "github.com/openshift/machine-config-operator/pkg/controller/template"
47
48
"github.com/openshift/machine-config-operator/pkg/version"
@@ -528,7 +529,7 @@ func (ctrl *Controller) addAnnotation(cfg *mcfgv1.KubeletConfig, annotationKey,
528
529
// This function is not meant to be invoked concurrently with the same key.
529
530
//
530
531
//nolint:gocyclo
531
- func (ctrl * Controller ) syncKubeletConfig (key string ) error {
532
+ func (ctrl * Controller ) syncKubeletConfig (key string ) ( retErr error ) {
532
533
startTime := time .Now ()
533
534
klog .V (4 ).Infof ("Started syncing kubeletconfig %q (%v)" , key , startTime )
534
535
defer func () {
@@ -595,6 +596,13 @@ func (ctrl *Controller) syncKubeletConfig(key string) error {
595
596
return ctrl .syncStatusOnly (cfg , err , "could not get the TLSSecurityProfile from %v: %v" , ctrlcommon .APIServerInstanceName , err )
596
597
}
597
598
599
+ updatedPools := []string {}
600
+
601
+ featureGates , renderedVersions , err := generateFeatureMap (ctrl .featureGateAccess , openshiftOnlyFeatureGates ... )
602
+ if err != nil {
603
+ return fmt .Errorf ("could not generate features map: %w" , err )
604
+ }
605
+
598
606
for _ , pool := range mcpPools {
599
607
if pool .Spec .Configuration .Name == "" {
600
608
updateDelay := 5 * time .Second
@@ -629,11 +637,6 @@ func (ctrl *Controller) syncKubeletConfig(key string) error {
629
637
return fmt .Errorf ("could not get ControllerConfig %w" , err )
630
638
}
631
639
632
- featureGates , err := generateFeatureMap (ctrl .featureGateAccess , openshiftOnlyFeatureGates ... )
633
- if err != nil {
634
- return fmt .Errorf ("could not generate features map: %w" , err )
635
- }
636
-
637
640
originalKubeConfig , err := generateOriginalKubeletConfigWithFeatureGates (cc , ctrl .templatesDir , role , featureGates , apiServer )
638
641
if err != nil {
639
642
return ctrl .syncStatusOnly (cfg , err , "could not get original kubelet config: %v" , err )
@@ -725,13 +728,65 @@ func (ctrl *Controller) syncKubeletConfig(key string) error {
725
728
}
726
729
klog .Infof ("Applied KubeletConfig %v on MachineConfigPool %v" , key , pool .Name )
727
730
ctrlcommon .UpdateStateMetric (ctrlcommon .MCCSubControllerState , "machine-config-controller-kubelet-config" , "Sync Kubelet Config" , pool .Name )
731
+ updatedPools = append (updatedPools , pool .Name )
728
732
}
733
+ go ctrl .writebackMinimumKubeletVersionIfAppropriate (updatedPools , renderedVersions , nodeConfig , func () ([]* mcfgv1.MachineConfigPool , error ) {
734
+ return ctrl .getPoolsForKubeletConfig (cfg )
735
+ })
729
736
if err := ctrl .cleanUpDuplicatedMC (managedKubeletConfigKeyPrefix ); err != nil {
730
737
return err
731
738
}
732
739
return ctrl .syncStatusOnly (cfg , nil )
733
740
}
734
741
742
+ func (ctrl * Controller ) writebackMinimumKubeletVersionIfAppropriate (updatedPools []string , renderedVersions []configv1.RequiredMinimumComponentVersion , node * osev1.Node , poolGetter func () ([]* mcfgv1.MachineConfigPool , error )) {
743
+ renderedKubeletVersion := ""
744
+ for _ , cv := range renderedVersions {
745
+ if cv .Component == configv1 .RequiredMinimumComponentKubelet {
746
+ renderedKubeletVersion = cv .Version
747
+ }
748
+ }
749
+ if node .Spec .MinimumKubeletVersion == node .Status .MinimumKubeletVersion ||
750
+ node .Status .MinimumKubeletVersion == renderedKubeletVersion ||
751
+ node .Spec .MinimumKubeletVersion != renderedKubeletVersion {
752
+ klog .InfoS ("Skipping writeback to nodes.config.Status.MinimumKubeletVersion because situation not correct" ,
753
+ "nodes.config.Spec.MinimumKubeletVerison" , node .Spec .MinimumKubeletVersion ,
754
+ "nodes.config.Status.MinimumKubeletVerison" , node .Status .MinimumKubeletVersion ,
755
+ "renderedKubeletVersion" , renderedKubeletVersion )
756
+ return
757
+ }
758
+
759
+ poolsUpdated := map [string ]bool {}
760
+ for _ , poolName := range updatedPools {
761
+ poolsUpdated [poolName ] = false
762
+ }
763
+ // This featuregate rollout was done as a result of a new minimum kubelet version rolling out, which means we need to wait for at least one
764
+ // node in each MCP to finish updating before we set the spec.
765
+ if err := wait .ExponentialBackoff (constants .NodeUpdateBackoff , func () (bool , error ) {
766
+ // no do-while :(
767
+ mcps , err := poolGetter ()
768
+ if err != nil {
769
+ return true , err
770
+ }
771
+ allUpdated := true
772
+ for _ , mcp := range mcps {
773
+ if mcp .Status .UpdatedMachineCount > 0 {
774
+ poolsUpdated [mcp .Name ] = true
775
+ } else if _ , updated := poolsUpdated [mcp .Name ]; ! updated {
776
+ allUpdated = false
777
+ }
778
+ }
779
+ return allUpdated , nil
780
+ }); err != nil {
781
+ klog .Errorf ("Failed to update rendered kubelet version: %v" , err )
782
+ }
783
+
784
+ node .Status .MinimumKubeletVersion = renderedKubeletVersion
785
+ if _ , err := ctrl .configClient .ConfigV1 ().Nodes ().Update (context .TODO (), node , metav1.UpdateOptions {}); err != nil {
786
+ klog .Errorf ("Failed to update node object for rendered kubelet version: %v" , err )
787
+ }
788
+ }
789
+
735
790
// cleanUpDuplicatedMC removes the MC of non-updated GeneratedByControllerVersionKey if its name contains 'generated-kubelet'.
736
791
// BZ 1955517: upgrade when there are more than one configs, the duplicated and upgraded MC will be generated (func getManagedKubeletConfigKey())
737
792
// MC with old GeneratedByControllerVersionKey fails the upgrade.
0 commit comments