kube-controller-manager: Decouple TaintManager from NodeLifeCycleController (KEP-3902)

This commit is contained in:
Andrea Tosatto
2023-07-10 14:02:56 +01:00
parent 38ed3ef7b7
commit ccda2d6fd4
14 changed files with 556 additions and 224 deletions

View File

@@ -57,7 +57,7 @@ import (
"k8s.io/component-base/featuregate"
"k8s.io/component-base/logs"
logsapi "k8s.io/component-base/logs/api/v1"
"k8s.io/component-base/metrics/features"
metricsfeatures "k8s.io/component-base/metrics/features"
controllersmetrics "k8s.io/component-base/metrics/prometheus/controllers"
"k8s.io/component-base/metrics/prometheus/slis"
"k8s.io/component-base/term"
@@ -75,12 +75,13 @@ import (
"k8s.io/kubernetes/cmd/kube-controller-manager/names"
kubectrlmgrconfig "k8s.io/kubernetes/pkg/controller/apis/config"
serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/serviceaccount"
)
func init() {
utilruntime.Must(logsapi.AddFeatureGates(utilfeature.DefaultMutableFeatureGate))
utilruntime.Must(features.AddFeatureGates(utilfeature.DefaultMutableFeatureGate))
utilruntime.Must(metricsfeatures.AddFeatureGates(utilfeature.DefaultMutableFeatureGate))
}
const (
@@ -556,6 +557,10 @@ func NewControllerDescriptors() map[string]*ControllerDescriptor {
register(newResourceClaimControllerDescriptor())
register(newLegacyServiceAccountTokenCleanerControllerDescriptor())
register(newValidatingAdmissionPolicyStatusControllerDescriptor())
if utilfeature.DefaultFeatureGate.Enabled(features.SeparateTaintEvictionController) {
// register the flag only if the SeparateTaintEvictionController flag is enabled
register(newTaintEvictionControllerDescriptor())
}
for _, alias := range aliases.UnsortedList() {
if _, ok := controllers[alias]; ok {

View File

@@ -28,8 +28,9 @@ import (
cpnames "k8s.io/cloud-provider/names"
"k8s.io/component-base/featuregate"
featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/kubernetes/cmd/kube-controller-manager/names"
"k8s.io/kubernetes/pkg/features"
"k8s.io/utils/strings/slices"
)
func TestControllerNamesConsistency(t *testing.T) {
@@ -73,6 +74,7 @@ func TestControllerNamesDeclaration(t *testing.T) {
names.TokenCleanerController,
names.NodeIpamController,
names.NodeLifecycleController,
names.TaintEvictionController,
cpnames.ServiceLBController,
cpnames.NodeRouteController,
cpnames.CloudNodeLifecycleController,
@@ -156,3 +158,17 @@ func TestFeatureGatedControllersShouldNotDefineAliases(t *testing.T) {
}
}
}
// TestTaintEvictionControllerDeclaration ensures that it is possible to run taint-manager as a separated controller
// only when the SeparateTaintEvictionController feature is enabled
func TestTaintEvictionControllerDeclaration(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SeparateTaintEvictionController, true)()
if !slices.Contains(KnownControllers(), names.TaintEvictionController) {
t.Errorf("TaintEvictionController should be a registered controller when the SeparateTaintEvictionController feature is enabled")
}
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SeparateTaintEvictionController, false)()
if slices.Contains(KnownControllers(), names.TaintEvictionController) {
t.Errorf("TaintEvictionController should not be a registered controller when the SeparateTaintEvictionController feature is disabled")
}
}

View File

@@ -59,6 +59,7 @@ import (
resourcequotacontroller "k8s.io/kubernetes/pkg/controller/resourcequota"
serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
"k8s.io/kubernetes/pkg/controller/storageversiongc"
"k8s.io/kubernetes/pkg/controller/tainteviction"
ttlcontroller "k8s.io/kubernetes/pkg/controller/ttl"
"k8s.io/kubernetes/pkg/controller/ttlafterfinished"
"k8s.io/kubernetes/pkg/controller/volume/attachdetach"
@@ -219,6 +220,32 @@ func startNodeLifecycleController(ctx context.Context, controllerContext Control
return nil, true, nil
}
func newTaintEvictionControllerDescriptor() *ControllerDescriptor {
return &ControllerDescriptor{
name: names.TaintEvictionController,
initFunc: startTaintEvictionController,
requiredFeatureGates: []featuregate.Feature{
features.SeparateTaintEvictionController,
},
}
}
func startTaintEvictionController(ctx context.Context, controllerContext ControllerContext, controllerName string) (controller.Interface, bool, error) {
taintEvictionController, err := tainteviction.New(
ctx,
// taint-manager uses existing cluster role from node-controller
controllerContext.ClientBuilder.ClientOrDie("node-controller"),
controllerContext.InformerFactory.Core().V1().Pods(),
controllerContext.InformerFactory.Core().V1().Nodes(),
controllerName,
)
if err != nil {
return nil, false, err
}
go taintEvictionController.Run(ctx)
return nil, true, nil
}
func newCloudNodeLifecycleControllerDescriptor() *ControllerDescriptor {
return &ControllerDescriptor{
name: cpnames.CloudNodeLifecycleController,

View File

@@ -68,6 +68,7 @@ const (
TokenCleanerController = "token-cleaner-controller"
NodeIpamController = "node-ipam-controller"
NodeLifecycleController = "node-lifecycle-controller"
TaintEvictionController = "taint-eviction-controller"
PersistentVolumeBinderController = "persistentvolume-binder-controller"
PersistentVolumeAttachDetachController = "persistentvolume-attach-detach-controller"
PersistentVolumeExpanderController = "persistentvolume-expander-controller"