Skip to content

MCO-1661: Feature Gate handling rework #5029

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 41 additions & 52 deletions cmd/machine-config-controller/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"flag"
"fmt"
"os"
"time"

features "github.com/openshift/api/features"
"github.com/openshift/machine-config-operator/cmd/common"
Expand Down Expand Up @@ -82,7 +81,7 @@ func runStartCmd(_ *cobra.Command, _ []string) {
ctrlctx.InformerFactory.Machineconfiguration().V1().MachineConfigPools(),
ctrlctx.ClientBuilder.KubeClientOrDie("node-update-controller"),
ctrlctx.ClientBuilder.MachineConfigClientOrDie("node-update-controller"),
ctrlctx.FeatureGateAccess,
ctrlctx.FeatureGatesHandler,
)

certrotationcontroller, err := certrotationcontroller.New(
Expand All @@ -108,56 +107,46 @@ func runStartCmd(_ *cobra.Command, _ []string) {

close(ctrlctx.InformersStarted)

select {
case <-ctrlctx.FeatureGateAccess.InitialFeatureGatesObserved():
fg, err := ctrlctx.FeatureGateAccess.CurrentFeatureGates()
if err != nil {
klog.Fatalf("unable to get initial features: %v", err)
}

enabled, disabled := ctrlcommon.GetEnabledDisabledFeatures(fg)
klog.Infof("FeatureGates initialized: enabled=%v disabled=%v", enabled, disabled)
if fg.Enabled(features.FeatureGatePinnedImages) && fg.Enabled(features.FeatureGateMachineConfigNodes) {
pinnedImageSet := pinnedimageset.New(
ctrlctx.InformerFactory.Machineconfiguration().V1().PinnedImageSets(),
ctrlctx.InformerFactory.Machineconfiguration().V1().MachineConfigPools(),
ctrlctx.ClientBuilder.KubeClientOrDie("pinned-image-set-controller"),
ctrlctx.ClientBuilder.MachineConfigClientOrDie("pinned-image-set-controller"),
)

go pinnedImageSet.Run(2, ctrlctx.Stop)
// start the informers again to enable feature gated types.
// see comments in SharedInformerFactory interface.
ctrlctx.InformerFactory.Start(ctrlctx.Stop)
}
if fgErr := ctrlctx.FeatureGatesHandler.Connect(ctx); fgErr != nil {
klog.Fatal(fmt.Errorf("failed to connect to feature gates %w", fgErr))
}

if ctrlcommon.IsBootImageControllerRequired(ctrlctx) {
machineSetBootImage := machinesetbootimage.New(
ctrlctx.ClientBuilder.KubeClientOrDie("machine-set-boot-image-controller"),
ctrlctx.ClientBuilder.MachineClientOrDie("machine-set-boot-image-controller"),
ctrlctx.KubeNamespacedInformerFactory.Core().V1().ConfigMaps(),
ctrlctx.MachineInformerFactory.Machine().V1beta1().MachineSets(),
ctrlctx.ConfigInformerFactory.Config().V1().Infrastructures(),
ctrlctx.ClientBuilder.OperatorClientOrDie(componentName),
ctrlctx.OperatorInformerFactory.Operator().V1().MachineConfigurations(),
ctrlctx.FeatureGateAccess,
)
go machineSetBootImage.Run(ctrlctx.Stop)
// start the informers again to enable feature gated types.
// see comments in SharedInformerFactory interface.
ctrlctx.KubeNamespacedInformerFactory.Start(ctrlctx.Stop)
ctrlctx.MachineInformerFactory.Start(ctrlctx.Stop)
ctrlctx.ConfigInformerFactory.Start(ctrlctx.Stop)
ctrlctx.OperatorInformerFactory.Start(ctrlctx.Stop)
}
if ctrlctx.FeatureGatesHandler.Enabled(features.FeatureGatePinnedImages) && ctrlctx.FeatureGatesHandler.Enabled(features.FeatureGateMachineConfigNodes) {
pinnedImageSet := pinnedimageset.New(
ctrlctx.InformerFactory.Machineconfiguration().V1().PinnedImageSets(),
ctrlctx.InformerFactory.Machineconfiguration().V1().MachineConfigPools(),
ctrlctx.ClientBuilder.KubeClientOrDie("pinned-image-set-controller"),
ctrlctx.ClientBuilder.MachineConfigClientOrDie("pinned-image-set-controller"),
)

go pinnedImageSet.Run(2, ctrlctx.Stop)
// start the informers again to enable feature gated types.
// see comments in SharedInformerFactory interface.
ctrlctx.InformerFactory.Start(ctrlctx.Stop)
}

if fg.Enabled(features.FeatureGateOnClusterBuild) {
ctrlctx.OCLInformerFactory.Start(ctrlctx.Stop)
}
if ctrlcommon.IsBootImageControllerRequired(ctrlctx) {
machineSetBootImage := machinesetbootimage.New(
ctrlctx.ClientBuilder.KubeClientOrDie("machine-set-boot-image-controller"),
ctrlctx.ClientBuilder.MachineClientOrDie("machine-set-boot-image-controller"),
ctrlctx.KubeNamespacedInformerFactory.Core().V1().ConfigMaps(),
ctrlctx.MachineInformerFactory.Machine().V1beta1().MachineSets(),
ctrlctx.ConfigInformerFactory.Config().V1().Infrastructures(),
ctrlctx.ClientBuilder.OperatorClientOrDie(componentName),
ctrlctx.OperatorInformerFactory.Operator().V1().MachineConfigurations(),
ctrlctx.FeatureGatesHandler,
)
go machineSetBootImage.Run(ctrlctx.Stop)
// start the informers again to enable feature gated types.
// see comments in SharedInformerFactory interface.
ctrlctx.KubeNamespacedInformerFactory.Start(ctrlctx.Stop)
ctrlctx.MachineInformerFactory.Start(ctrlctx.Stop)
ctrlctx.ConfigInformerFactory.Start(ctrlctx.Stop)
ctrlctx.OperatorInformerFactory.Start(ctrlctx.Stop)
}

case <-time.After(1 * time.Minute):
klog.Errorf("timed out waiting for FeatureGate detection")
os.Exit(1)
if ctrlctx.FeatureGatesHandler.Enabled(features.FeatureGateOnClusterBuild) {
ctrlctx.OCLInformerFactory.Start(ctrlctx.Stop)
}

for _, c := range controllers {
Expand Down Expand Up @@ -215,7 +204,7 @@ func createControllers(ctx *ctrlcommon.ControllerContext) []ctrlcommon.Controlle
ctx.ClientBuilder.KubeClientOrDie("kubelet-config-controller"),
ctx.ClientBuilder.MachineConfigClientOrDie("kubelet-config-controller"),
ctx.ClientBuilder.ConfigClientOrDie("kubelet-config-controller"),
ctx.FeatureGateAccess,
ctx.FeatureGatesHandler,
),
containerruntimeconfig.New(
rootOpts.templates,
Expand All @@ -231,7 +220,7 @@ func createControllers(ctx *ctrlcommon.ControllerContext) []ctrlcommon.Controlle
ctx.ClientBuilder.KubeClientOrDie("container-runtime-config-controller"),
ctx.ClientBuilder.MachineConfigClientOrDie("container-runtime-config-controller"),
ctx.ClientBuilder.ConfigClientOrDie("container-runtime-config-controller"),
ctx.FeatureGateAccess,
ctx.FeatureGatesHandler,
),
// The renderer creates "rendered" MCs from the MC fragments generated by
// the above sub-controllers, which are then consumed by the node controller
Expand All @@ -255,7 +244,7 @@ func createControllers(ctx *ctrlcommon.ControllerContext) []ctrlcommon.Controlle
ctx.ConfigInformerFactory.Config().V1().Schedulers(),
ctx.ClientBuilder.KubeClientOrDie("node-update-controller"),
ctx.ClientBuilder.MachineConfigClientOrDie("node-update-controller"),
ctx.FeatureGateAccess,
ctx.FeatureGatesHandler,
),
)

Expand Down
72 changes: 33 additions & 39 deletions cmd/machine-config-daemon/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ import (
"context"
"errors"
"flag"
"fmt"
"net/url"
"os"
"time"

"github.com/openshift/api/features"

"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/client-go/tools/clientcmd"

features "github.com/openshift/api/features"
"github.com/openshift/machine-config-operator/internal/clients"
ctrlcommon "github.com/openshift/machine-config-operator/pkg/controller/common"
"github.com/openshift/machine-config-operator/pkg/daemon"
Expand Down Expand Up @@ -190,7 +192,7 @@ func runStartCmd(_ *cobra.Command, _ []string) {
ctrlctx.ClientBuilder.OperatorClientOrDie(componentName),
startOpts.kubeletHealthzEnabled,
startOpts.kubeletHealthzEndpoint,
ctrlctx.FeatureGateAccess,
ctrlctx.FeatureGatesHandler,
)
if err != nil {
klog.Fatalf("Failed to initialize: %v", err)
Expand All @@ -204,46 +206,38 @@ func runStartCmd(_ *cobra.Command, _ []string) {
ctrlctx.OperatorInformerFactory.Start(stopCh)
close(ctrlctx.InformersStarted)

select {
case <-ctrlctx.FeatureGateAccess.InitialFeatureGatesObserved():
// ok to start the rest of the informers now that we have observed the initial feature gates
if fgErr := ctrlctx.FeatureGatesHandler.Connect(ctx); fgErr != nil {
klog.Fatal(fmt.Errorf("failed to connect to feature gates %w", fgErr))
}

featureGates, err := ctrlctx.FeatureGateAccess.CurrentFeatureGates()
// ok to start the rest of the informers now that we have observed the initial feature gates
if ctrlctx.FeatureGatesHandler.Enabled(features.FeatureGatePinnedImages) && ctrlctx.FeatureGatesHandler.Enabled(features.FeatureGateMachineConfigNodes) {
klog.Infof("Feature enabled: %s", features.FeatureGatePinnedImages)
criClient, err := cri.NewClient(ctx, constants.DefaultCRIOSocketPath)
if err != nil {
klog.Fatalf("Could not get FG: %v", err)
} else {
klog.Infof("FeatureGates initialized: knownFeatureGates=%v", featureGates.KnownFeatures())
if featureGates.Enabled(features.FeatureGatePinnedImages) && featureGates.Enabled(features.FeatureGateMachineConfigNodes) {
klog.Infof("Feature enabled: %s", features.FeatureGatePinnedImages)
criClient, err := cri.NewClient(ctx, constants.DefaultCRIOSocketPath)
if err != nil {
klog.Fatalf("Failed to initialize CRI client: %v", err)
}

prefetchTimeout := 2 * time.Minute
pinnedImageSetManager := daemon.NewPinnedImageSetManager(
startOpts.nodeName,
criClient,
ctrlctx.ClientBuilder.MachineConfigClientOrDie(componentName),
ctrlctx.InformerFactory.Machineconfiguration().V1().PinnedImageSets(),
ctrlctx.KubeInformerFactory.Core().V1().Nodes(),
ctrlctx.InformerFactory.Machineconfiguration().V1().MachineConfigPools(),
resource.MustParse(constants.MinFreeStorageAfterPrefetch),
constants.DefaultCRIOSocketPath,
constants.KubeletAuthFile,
constants.ContainerRegistryConfPath,
prefetchTimeout,
ctrlctx.FeatureGateAccess,
)

go pinnedImageSetManager.Run(2, stopCh)
// start the informers for the pinned image set again after the feature gate is enabled this is allowed.
// see comments in SharedInformerFactory interface.
ctrlctx.InformerFactory.Start(stopCh)
}
klog.Fatalf("Failed to initialize CRI client: %v", err)
}
case <-time.After(1 * time.Minute):
klog.Fatalf("Could not get FG, timed out: %v", err)

prefetchTimeout := 2 * time.Minute
pinnedImageSetManager := daemon.NewPinnedImageSetManager(
startOpts.nodeName,
criClient,
ctrlctx.ClientBuilder.MachineConfigClientOrDie(componentName),
ctrlctx.InformerFactory.Machineconfiguration().V1().PinnedImageSets(),
ctrlctx.KubeInformerFactory.Core().V1().Nodes(),
ctrlctx.InformerFactory.Machineconfiguration().V1().MachineConfigPools(),
resource.MustParse(constants.MinFreeStorageAfterPrefetch),
constants.DefaultCRIOSocketPath,
constants.KubeletAuthFile,
constants.ContainerRegistryConfPath,
prefetchTimeout,
ctrlctx.FeatureGatesHandler,
)

go pinnedImageSetManager.Run(2, stopCh)
// start the informers for the pinned image set again after the feature gate is enabled this is allowed.
// see comments in SharedInformerFactory interface.
ctrlctx.InformerFactory.Start(stopCh)
}

if err := dn.Run(stopCh, exitCh, errCh); err != nil {
Expand Down
16 changes: 4 additions & 12 deletions cmd/machine-config-operator/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package main
import (
"context"
"flag"
"fmt"
"os"
"time"

"github.com/openshift/machine-config-operator/cmd/common"
"github.com/openshift/machine-config-operator/internal/clients"
Expand Down Expand Up @@ -100,7 +100,7 @@ func runStartCmd(_ *cobra.Command, _ []string) {
ctrlctx.ConfigInformerFactory.Config().V1().ClusterOperators(),
ctrlctx.ClientBuilder.OperatorClientOrDie(componentName),
ctrlctx.OperatorInformerFactory.Operator().V1().MachineConfigurations(),
ctrlctx.FeatureGateAccess,
ctrlctx.FeatureGatesHandler,
ctrlctx.InformerFactory.Machineconfiguration().V1().KubeletConfigs(),
ctrlctx.InformerFactory.Machineconfiguration().V1().ContainerRuntimeConfigs(),
ctrlctx.ConfigInformerFactory.Config().V1().Nodes(),
Expand All @@ -122,16 +122,8 @@ func runStartCmd(_ *cobra.Command, _ []string) {

close(ctrlctx.InformersStarted)

select {
case <-ctrlctx.FeatureGateAccess.InitialFeatureGatesObserved():
featureGates, err := ctrlctx.FeatureGateAccess.CurrentFeatureGates()
if err != nil {
klog.Fatalf("Could not get FG: %v", err)
} else {
klog.Infof("FeatureGates initialized: knownFeatureGates=%v", featureGates.KnownFeatures())
}
case <-time.After(1 * time.Minute):
klog.Fatalf("Could not get FG, timed out: %v", err)
if fgErr := ctrlctx.FeatureGatesHandler.Connect(ctx); fgErr != nil {
klog.Fatal(fmt.Errorf("failed to connect to feature gates %w", fgErr))
}

go controller.Run(2, ctrlctx.Stop)
Expand Down
13 changes: 6 additions & 7 deletions pkg/controller/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
apicfgv1alpha1 "github.com/openshift/api/config/v1alpha1"
mcfgv1 "github.com/openshift/api/machineconfiguration/v1"
apioperatorsv1alpha1 "github.com/openshift/api/operator/v1alpha1"
"github.com/openshift/library-go/pkg/operator/configobserver/featuregates"
ctrlcommon "github.com/openshift/machine-config-operator/pkg/controller/common"
containerruntimeconfig "github.com/openshift/machine-config-operator/pkg/controller/container-runtime-config"
kubeletconfig "github.com/openshift/machine-config-operator/pkg/controller/kubelet-config"
Expand Down Expand Up @@ -170,9 +169,9 @@ func (b *Bootstrap) Run(destDir string) error {
return fmt.Errorf("error: no featuregate found in dir: %q", b.manifestDir)
}

fgAccess, err := featuregates.NewHardcodedFeatureGateAccessFromFeatureGate(featureGate, version.ReleaseVersion)
fgHandler, err := ctrlcommon.NewFeatureGatesCRHandlerImpl(featureGate, version.ReleaseVersion)
if err != nil {
return fmt.Errorf("error creating feature gate access: %w", err)
return fmt.Errorf("error creating feature gates handler: %w", err)
}

iconfigs, err := template.RunBootstrap(b.templatesDir, cconfig, psraw, apiServer)
Expand All @@ -183,7 +182,7 @@ func (b *Bootstrap) Run(destDir string) error {

configs = append(configs, iconfigs...)

rconfigs, err := containerruntimeconfig.RunImageBootstrap(b.templatesDir, cconfig, pools, icspRules, idmsRules, itmsRules, imgCfg, clusterImagePolicies, imagePolicies, fgAccess)
rconfigs, err := containerruntimeconfig.RunImageBootstrap(b.templatesDir, cconfig, pools, icspRules, idmsRules, itmsRules, imgCfg, clusterImagePolicies, imagePolicies, fgHandler)
if err != nil {
return err
}
Expand All @@ -201,7 +200,7 @@ func (b *Bootstrap) Run(destDir string) error {
klog.Infof("Successfully generated MachineConfigs from containerruntime.")

if featureGate != nil {
featureConfigs, err := kubeletconfig.RunFeatureGateBootstrap(b.templatesDir, fgAccess, nodeConfig, cconfig, pools, apiServer)
featureConfigs, err := kubeletconfig.RunFeatureGateBootstrap(b.templatesDir, fgHandler, nodeConfig, cconfig, pools, apiServer)
if err != nil {
return err
}
Expand All @@ -218,7 +217,7 @@ func (b *Bootstrap) Run(destDir string) error {
}
}
if nodeConfig != nil {
nodeConfigs, err := kubeletconfig.RunNodeConfigBootstrap(b.templatesDir, fgAccess, cconfig, nodeConfig, pools, apiServer)
nodeConfigs, err := kubeletconfig.RunNodeConfigBootstrap(b.templatesDir, fgHandler, cconfig, nodeConfig, pools, apiServer)
if err != nil {
return err
}
Expand All @@ -227,7 +226,7 @@ func (b *Bootstrap) Run(destDir string) error {
klog.Infof("Successfully generated MachineConfigs from node.Configs.")

if len(kconfigs) > 0 {
kconfigs, err := kubeletconfig.RunKubeletBootstrap(b.templatesDir, kconfigs, cconfig, fgAccess, nodeConfig, pools, apiServer)
kconfigs, err := kubeletconfig.RunKubeletBootstrap(b.templatesDir, kconfigs, cconfig, fgHandler, nodeConfig, pools, apiServer)
if err != nil {
return err
}
Expand Down
5 changes: 2 additions & 3 deletions pkg/controller/common/controller_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ type ControllerContext struct {
ImageInformerFactory imageinformers.SharedInformerFactory
RouteInformerFactory routeinformers.SharedInformerFactory

FeatureGateAccess featuregates.FeatureGateAccess
FeatureGatesHandler FeatureGatesHandler

AvailableResources map[schema.GroupVersionResource]bool

Expand Down Expand Up @@ -136,7 +136,6 @@ func CreateControllerContext(ctx context.Context, cb *clients.Builder) *Controll
configSharedInformer.Config().V1().ClusterVersions(), configSharedInformer.Config().V1().FeatureGates(),
recorder,
)

go featureGateAccessor.Run(ctx)

return &ControllerContext{
Expand All @@ -157,7 +156,7 @@ func CreateControllerContext(ctx context.Context, cb *clients.Builder) *Controll
InformersStarted: make(chan struct{}),
ResyncPeriod: resyncPeriod(),
KubeMAOSharedInformer: kubeMAOSharedInformer,
FeatureGateAccess: featureGateAccessor,
FeatureGatesHandler: NewFeatureGatesAccessHandler(featureGateAccessor),
ImageInformerFactory: imageSharedInformer,
RouteInformerFactory: routeSharedInformer,
}
Expand Down
Loading