From 2119741e240ea91dd6d0ef07666aee12355e4cb1 Mon Sep 17 00:00:00 2001 From: xigang Date: Thu, 25 Jun 2026 19:33:46 +0800 Subject: [PATCH] Add concurrent worker support to the disruption controller Signed-off-by: xigang --- api/api-rules/violation_exceptions.list | 2 + .../app/options/disruptioncontroller.go | 58 ++++++++++++ .../app/options/options.go | 9 ++ .../app/options/options_test.go | 19 ++++ cmd/kube-controller-manager/app/policy.go | 4 +- pkg/controller/apis/config/types.go | 4 + .../apis/config/v1alpha1/defaults.go | 3 + pkg/controller/apis/config/v1alpha1/doc.go | 1 + .../v1alpha1/zz_generated.conversion.go | 7 ++ .../apis/config/zz_generated.deepcopy.go | 1 + pkg/controller/disruption/config/doc.go | 19 ++++ pkg/controller/disruption/config/types.go | 25 +++++ .../disruption/config/v1alpha1/conversion.go | 40 ++++++++ .../disruption/config/v1alpha1/defaults.go | 36 ++++++++ .../disruption/config/v1alpha1/doc.go | 21 +++++ .../disruption/config/v1alpha1/register.go | 31 +++++++ .../v1alpha1/zz_generated.conversion.go | 92 +++++++++++++++++++ .../config/zz_generated.deepcopy.go | 38 ++++++++ pkg/controller/disruption/disruption.go | 10 +- pkg/controller/disruption/disruption_test.go | 2 +- pkg/generated/openapi/zz_generated.openapi.go | 34 ++++++- .../config/v1alpha1/types.go | 11 +++ .../config/v1alpha1/zz_generated.deepcopy.go | 17 ++++ .../v1alpha1/zz_generated.model_name.go | 5 + .../integration/disruption/disruption_test.go | 10 +- test/integration/evictions/evictions_test.go | 12 +-- test/integration/util/util.go | 2 +- 27 files changed, 493 insertions(+), 20 deletions(-) create mode 100644 cmd/kube-controller-manager/app/options/disruptioncontroller.go create mode 100644 pkg/controller/disruption/config/doc.go create mode 100644 pkg/controller/disruption/config/types.go create mode 100644 pkg/controller/disruption/config/v1alpha1/conversion.go create mode 100644 pkg/controller/disruption/config/v1alpha1/defaults.go create mode 100644 pkg/controller/disruption/config/v1alpha1/doc.go create mode 100644 pkg/controller/disruption/config/v1alpha1/register.go create mode 100644 pkg/controller/disruption/config/v1alpha1/zz_generated.conversion.go create mode 100644 pkg/controller/disruption/config/zz_generated.deepcopy.go diff --git a/api/api-rules/violation_exceptions.list b/api/api-rules/violation_exceptions.list index ed92daf6f85..fb545d1edda 100644 --- a/api/api-rules/violation_exceptions.list +++ b/api/api-rules/violation_exceptions.list @@ -189,6 +189,7 @@ API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,C API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,DaemonSetControllerConfiguration,ConcurrentDaemonSetSyncs API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,DeploymentControllerConfiguration,ConcurrentDeploymentSyncs API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,DeviceTaintEvictionControllerConfiguration,ConcurrentSyncs +API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,DisruptionControllerConfiguration,ConcurrentDisruptionSyncs API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,EndpointControllerConfiguration,ConcurrentEndpointSyncs API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,EndpointControllerConfiguration,EndpointUpdatesBatchPeriod API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,EndpointSliceControllerConfiguration,ConcurrentServiceEndpointSyncs @@ -217,6 +218,7 @@ API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,K API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,KubeControllerManagerConfiguration,DeploymentController API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,KubeControllerManagerConfiguration,DeprecatedController API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,KubeControllerManagerConfiguration,DeviceTaintEvictionController +API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,KubeControllerManagerConfiguration,DisruptionController API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,KubeControllerManagerConfiguration,EndpointController API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,KubeControllerManagerConfiguration,EndpointSliceController API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,KubeControllerManagerConfiguration,EndpointSliceMirroringController diff --git a/cmd/kube-controller-manager/app/options/disruptioncontroller.go b/cmd/kube-controller-manager/app/options/disruptioncontroller.go new file mode 100644 index 00000000000..7495220e96e --- /dev/null +++ b/cmd/kube-controller-manager/app/options/disruptioncontroller.go @@ -0,0 +1,58 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package options + +import ( + "github.com/spf13/pflag" + + disruptionconfig "k8s.io/kubernetes/pkg/controller/disruption/config" +) + +// DisruptionControllerOptions holds the DisruptionController options. +type DisruptionControllerOptions struct { + *disruptionconfig.DisruptionControllerConfiguration +} + +// AddFlags adds flags related to DisruptionController for controller manager to the specified FlagSet. +func (o *DisruptionControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.Int32Var(&o.ConcurrentDisruptionSyncs, "concurrent-disruption-syncs", o.ConcurrentDisruptionSyncs, "The number of PDB objects that are allowed to sync concurrently. Larger number = more responsive PDB updates, but more CPU (and network) load") +} + +// ApplyTo fills up DisruptionController config with options. +func (o *DisruptionControllerOptions) ApplyTo(cfg *disruptionconfig.DisruptionControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.ConcurrentDisruptionSyncs = o.ConcurrentDisruptionSyncs + + return nil +} + +// Validate checks validation of DisruptionControllerOptions. +func (o *DisruptionControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/cmd/kube-controller-manager/app/options/options.go b/cmd/kube-controller-manager/app/options/options.go index e507ef74eb2..6ed3a36c780 100644 --- a/cmd/kube-controller-manager/app/options/options.go +++ b/cmd/kube-controller-manager/app/options/options.go @@ -73,6 +73,7 @@ type KubeControllerManagerOptions struct { CSRSigningController *CSRSigningControllerOptions DaemonSetController *DaemonSetControllerOptions DeploymentController *DeploymentControllerOptions + DisruptionController *DisruptionControllerOptions DeviceTaintEvictionController *DeviceTaintEvictionControllerOptions ResourceClaimController *ResourceClaimControllerOptions StatefulSetController *StatefulSetControllerOptions @@ -146,6 +147,9 @@ func NewKubeControllerManagerOptions() (*KubeControllerManagerOptions, error) { DeploymentController: &DeploymentControllerOptions{ &componentConfig.DeploymentController, }, + DisruptionController: &DisruptionControllerOptions{ + &componentConfig.DisruptionController, + }, DeviceTaintEvictionController: &DeviceTaintEvictionControllerOptions{ &componentConfig.DeviceTaintEvictionController, }, @@ -271,6 +275,7 @@ func (s *KubeControllerManagerOptions) Flags(allControllers []string, disabledBy s.AttachDetachController.AddFlags(fss.FlagSet(names.PersistentVolumeAttachDetachController)) s.CSRSigningController.AddFlags(fss.FlagSet(names.CertificateSigningRequestSigningController)) s.DeploymentController.AddFlags(fss.FlagSet(names.DeploymentController)) + s.DisruptionController.AddFlags(fss.FlagSet(names.DisruptionController)) s.DeviceTaintEvictionController.AddFlags(fss.FlagSet(names.DeviceTaintEvictionController)) s.ResourceClaimController.AddFlags(fss.FlagSet(names.ResourceClaimController)) s.StatefulSetController.AddFlags(fss.FlagSet(names.StatefulSetController)) @@ -335,6 +340,9 @@ func (s *KubeControllerManagerOptions) ApplyTo(c *kubecontrollerconfig.Config, a if err := s.DeploymentController.ApplyTo(&c.ComponentConfig.DeploymentController); err != nil { return err } + if err := s.DisruptionController.ApplyTo(&c.ComponentConfig.DisruptionController); err != nil { + return err + } if err := s.DeviceTaintEvictionController.ApplyTo(&c.ComponentConfig.DeviceTaintEvictionController); err != nil { return err } @@ -437,6 +445,7 @@ func (s *KubeControllerManagerOptions) Validate(allControllers []string, disable errs = append(errs, s.CSRSigningController.Validate()...) errs = append(errs, s.DaemonSetController.Validate()...) errs = append(errs, s.DeploymentController.Validate()...) + errs = append(errs, s.DisruptionController.Validate()...) errs = append(errs, s.DeviceTaintEvictionController.Validate()...) errs = append(errs, s.ResourceClaimController.Validate()...) errs = append(errs, s.StatefulSetController.Validate()...) diff --git a/cmd/kube-controller-manager/app/options/options_test.go b/cmd/kube-controller-manager/app/options/options_test.go index f1eeb9857e9..539bb922aa3 100644 --- a/cmd/kube-controller-manager/app/options/options_test.go +++ b/cmd/kube-controller-manager/app/options/options_test.go @@ -57,6 +57,7 @@ import ( daemonconfig "k8s.io/kubernetes/pkg/controller/daemon/config" deploymentconfig "k8s.io/kubernetes/pkg/controller/deployment/config" devicetaintevictionconfig "k8s.io/kubernetes/pkg/controller/devicetainteviction/config" + disruptionconfig "k8s.io/kubernetes/pkg/controller/disruption/config" endpointconfig "k8s.io/kubernetes/pkg/controller/endpoint/config" endpointsliceconfig "k8s.io/kubernetes/pkg/controller/endpointslice/config" endpointslicemirroringconfig "k8s.io/kubernetes/pkg/controller/endpointslicemirroring/config" @@ -100,6 +101,7 @@ var args = []string{ "--cluster-signing-legacy-unknown-cert-file=/cluster-signing-legacy-unknown/cert-file", "--cluster-signing-legacy-unknown-key-file=/cluster-signing-legacy-unknown/key-file", "--concurrent-deployment-syncs=10", + "--concurrent-disruption-syncs=10", "--concurrent-device-taint-eviction-syncs=10", "--concurrent-resourceclaim-syncs=10", "--concurrent-daemonset-syncs=10", @@ -270,6 +272,11 @@ func TestAddFlags(t *testing.T) { ConcurrentDeploymentSyncs: 10, }, }, + DisruptionController: &DisruptionControllerOptions{ + &disruptionconfig.DisruptionControllerConfiguration{ + ConcurrentDisruptionSyncs: 10, + }, + }, DeviceTaintEvictionController: &DeviceTaintEvictionControllerOptions{ &devicetaintevictionconfig.DeviceTaintEvictionControllerConfiguration{ ConcurrentSyncs: 10, @@ -629,6 +636,9 @@ func TestApplyTo(t *testing.T) { DeploymentController: deploymentconfig.DeploymentControllerConfiguration{ ConcurrentDeploymentSyncs: 10, }, + DisruptionController: disruptionconfig.DisruptionControllerConfiguration{ + ConcurrentDisruptionSyncs: 10, + }, DeviceTaintEvictionController: devicetaintevictionconfig.DeviceTaintEvictionControllerConfiguration{ ConcurrentSyncs: 10, }, @@ -1274,6 +1284,15 @@ func TestValidateControllersOptions(t *testing.T) { }, }, }, + { + name: "DisruptionControllerOptions", + expectErrors: false, + options: &DisruptionControllerOptions{ + &disruptionconfig.DisruptionControllerConfiguration{ + ConcurrentDisruptionSyncs: 10, + }, + }, + }, { name: "DeviceTaintEvictionControllerOptions", expectErrors: false, diff --git a/cmd/kube-controller-manager/app/policy.go b/cmd/kube-controller-manager/app/policy.go index 7a6b7c004e3..5538ccf6758 100644 --- a/cmd/kube-controller-manager/app/policy.go +++ b/cmd/kube-controller-manager/app/policy.go @@ -65,5 +65,7 @@ func newDisruptionController(ctx context.Context, controllerContext ControllerCo scaleClient, client.Discovery(), ) - return newControllerLoop(dc.Run, controllerName), nil + return newControllerLoop(func(ctx context.Context) { + dc.Run(ctx, int(controllerContext.ComponentConfig.DisruptionController.ConcurrentDisruptionSyncs)) + }, controllerName), nil } diff --git a/pkg/controller/apis/config/types.go b/pkg/controller/apis/config/types.go index fe47ad0f29f..27b96ce8af6 100644 --- a/pkg/controller/apis/config/types.go +++ b/pkg/controller/apis/config/types.go @@ -26,6 +26,7 @@ import ( daemonconfig "k8s.io/kubernetes/pkg/controller/daemon/config" deploymentconfig "k8s.io/kubernetes/pkg/controller/deployment/config" devicetaintevictionconfig "k8s.io/kubernetes/pkg/controller/devicetainteviction/config" + disruptionconfig "k8s.io/kubernetes/pkg/controller/disruption/config" endpointconfig "k8s.io/kubernetes/pkg/controller/endpoint/config" endpointsliceconfig "k8s.io/kubernetes/pkg/controller/endpointslice/config" endpointslicemirroringconfig "k8s.io/kubernetes/pkg/controller/endpointslicemirroring/config" @@ -76,6 +77,9 @@ type KubeControllerManagerConfiguration struct { // DeploymentControllerConfiguration holds configuration for // DeploymentController related features. DeploymentController deploymentconfig.DeploymentControllerConfiguration + // DisruptionControllerConfiguration holds configuration for + // DisruptionController related features. + DisruptionController disruptionconfig.DisruptionControllerConfiguration // DeviceTaintEvictionControllerConfiguration contains elements configuring the device taint eviction controller. DeviceTaintEvictionController devicetaintevictionconfig.DeviceTaintEvictionControllerConfiguration // DeprecatedControllerConfiguration holds configuration for some deprecated diff --git a/pkg/controller/apis/config/v1alpha1/defaults.go b/pkg/controller/apis/config/v1alpha1/defaults.go index 70a6c3d1dfd..f023f79af21 100644 --- a/pkg/controller/apis/config/v1alpha1/defaults.go +++ b/pkg/controller/apis/config/v1alpha1/defaults.go @@ -26,6 +26,7 @@ import ( daemonconfigv1alpha1 "k8s.io/kubernetes/pkg/controller/daemon/config/v1alpha1" deploymentconfigv1alpha1 "k8s.io/kubernetes/pkg/controller/deployment/config/v1alpha1" devicetaintevictionconfigv1alpha1 "k8s.io/kubernetes/pkg/controller/devicetainteviction/config/v1alpha1" + disruptionconfigv1alpha1 "k8s.io/kubernetes/pkg/controller/disruption/config/v1alpha1" endpointconfigv1alpha1 "k8s.io/kubernetes/pkg/controller/endpoint/config/v1alpha1" endpointsliceconfigv1alpha1 "k8s.io/kubernetes/pkg/controller/endpointslice/config/v1alpha1" endpointslicemirroringconfigv1alpha1 "k8s.io/kubernetes/pkg/controller/endpointslicemirroring/config/v1alpha1" @@ -73,6 +74,8 @@ func SetDefaults_KubeControllerManagerConfiguration(obj *kubectrlmgrconfigv1alph daemonconfigv1alpha1.RecommendedDefaultDaemonSetControllerConfiguration(&obj.DaemonSetController) // Use the default RecommendedDefaultDeploymentControllerConfiguration options deploymentconfigv1alpha1.RecommendedDefaultDeploymentControllerConfiguration(&obj.DeploymentController) + // Use the default RecommendedDefaultDisruptionControllerConfiguration options + disruptionconfigv1alpha1.RecommendedDefaultDisruptionControllerConfiguration(&obj.DisruptionController) // Use the default RecommendedDefaultDeviceTaintEvictionControllerConfiguration options devicetaintevictionconfigv1alpha1.RecommendedDefaultDeviceTaintEvictionControllerConfiguration(&obj.DeviceTaintEvictionController) // Use the default RecommendedDefaultResourceClaimControllerConfiguration options diff --git a/pkg/controller/apis/config/v1alpha1/doc.go b/pkg/controller/apis/config/v1alpha1/doc.go index f7df3b6c78e..8f074bde774 100644 --- a/pkg/controller/apis/config/v1alpha1/doc.go +++ b/pkg/controller/apis/config/v1alpha1/doc.go @@ -23,6 +23,7 @@ limitations under the License. // +k8s:conversion-gen=k8s.io/kubernetes/pkg/controller/certificates/signer/config/v1alpha1 // +k8s:conversion-gen=k8s.io/kubernetes/pkg/controller/daemon/config/v1alpha1 // +k8s:conversion-gen=k8s.io/kubernetes/pkg/controller/deployment/config/v1alpha1 +// +k8s:conversion-gen=k8s.io/kubernetes/pkg/controller/disruption/config/v1alpha1 // +k8s:conversion-gen=k8s.io/kubernetes/pkg/controller/endpoint/config/v1alpha1 // +k8s:conversion-gen=k8s.io/kubernetes/pkg/controller/endpointslice/config/v1alpha1 // +k8s:conversion-gen=k8s.io/kubernetes/pkg/controller/garbagecollector/config/v1alpha1 diff --git a/pkg/controller/apis/config/v1alpha1/zz_generated.conversion.go b/pkg/controller/apis/config/v1alpha1/zz_generated.conversion.go index 66511ce3b4f..a8c0611d0ee 100644 --- a/pkg/controller/apis/config/v1alpha1/zz_generated.conversion.go +++ b/pkg/controller/apis/config/v1alpha1/zz_generated.conversion.go @@ -37,6 +37,7 @@ import ( daemonconfigv1alpha1 "k8s.io/kubernetes/pkg/controller/daemon/config/v1alpha1" deploymentconfigv1alpha1 "k8s.io/kubernetes/pkg/controller/deployment/config/v1alpha1" devicetaintevictionconfigv1alpha1 "k8s.io/kubernetes/pkg/controller/devicetainteviction/config/v1alpha1" + disruptionconfigv1alpha1 "k8s.io/kubernetes/pkg/controller/disruption/config/v1alpha1" endpointconfigv1alpha1 "k8s.io/kubernetes/pkg/controller/endpoint/config/v1alpha1" endpointsliceconfigv1alpha1 "k8s.io/kubernetes/pkg/controller/endpointslice/config/v1alpha1" endpointslicemirroringconfigv1alpha1 "k8s.io/kubernetes/pkg/controller/endpointslicemirroring/config/v1alpha1" @@ -159,6 +160,9 @@ func autoConvert_v1alpha1_KubeControllerManagerConfiguration_To_config_KubeContr if err := deploymentconfigv1alpha1.Convert_v1alpha1_DeploymentControllerConfiguration_To_config_DeploymentControllerConfiguration(&in.DeploymentController, &out.DeploymentController, s); err != nil { return err } + if err := disruptionconfigv1alpha1.Convert_v1alpha1_DisruptionControllerConfiguration_To_config_DisruptionControllerConfiguration(&in.DisruptionController, &out.DisruptionController, s); err != nil { + return err + } if err := statefulsetconfigv1alpha1.Convert_v1alpha1_StatefulSetControllerConfiguration_To_config_StatefulSetControllerConfiguration(&in.StatefulSetController, &out.StatefulSetController, s); err != nil { return err } @@ -264,6 +268,9 @@ func autoConvert_config_KubeControllerManagerConfiguration_To_v1alpha1_KubeContr if err := deploymentconfigv1alpha1.Convert_config_DeploymentControllerConfiguration_To_v1alpha1_DeploymentControllerConfiguration(&in.DeploymentController, &out.DeploymentController, s); err != nil { return err } + if err := disruptionconfigv1alpha1.Convert_config_DisruptionControllerConfiguration_To_v1alpha1_DisruptionControllerConfiguration(&in.DisruptionController, &out.DisruptionController, s); err != nil { + return err + } if err := devicetaintevictionconfigv1alpha1.Convert_config_DeviceTaintEvictionControllerConfiguration_To_v1alpha1_DeviceTaintEvictionControllerConfiguration(&in.DeviceTaintEvictionController, &out.DeviceTaintEvictionController, s); err != nil { return err } diff --git a/pkg/controller/apis/config/zz_generated.deepcopy.go b/pkg/controller/apis/config/zz_generated.deepcopy.go index ff15a2b8975..a8c90c7af53 100644 --- a/pkg/controller/apis/config/zz_generated.deepcopy.go +++ b/pkg/controller/apis/config/zz_generated.deepcopy.go @@ -52,6 +52,7 @@ func (in *KubeControllerManagerConfiguration) DeepCopyInto(out *KubeControllerMa out.CSRSigningController = in.CSRSigningController out.DaemonSetController = in.DaemonSetController out.DeploymentController = in.DeploymentController + out.DisruptionController = in.DisruptionController out.DeviceTaintEvictionController = in.DeviceTaintEvictionController out.DeprecatedController = in.DeprecatedController out.EndpointController = in.EndpointController diff --git a/pkg/controller/disruption/config/doc.go b/pkg/controller/disruption/config/doc.go new file mode 100644 index 00000000000..e605045a401 --- /dev/null +++ b/pkg/controller/disruption/config/doc.go @@ -0,0 +1,19 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:deepcopy-gen=package + +package config diff --git a/pkg/controller/disruption/config/types.go b/pkg/controller/disruption/config/types.go new file mode 100644 index 00000000000..4282144cbfc --- /dev/null +++ b/pkg/controller/disruption/config/types.go @@ -0,0 +1,25 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package config + +// DisruptionControllerConfiguration contains elements describing DisruptionController. +type DisruptionControllerConfiguration struct { + // concurrentDisruptionSyncs is the number of PodDisruptionBudget objects that + // are allowed to sync concurrently. Larger number = more responsive PDB + // updates, but more CPU (and network) load. + ConcurrentDisruptionSyncs int32 +} diff --git a/pkg/controller/disruption/config/v1alpha1/conversion.go b/pkg/controller/disruption/config/v1alpha1/conversion.go new file mode 100644 index 00000000000..06372dc6b4b --- /dev/null +++ b/pkg/controller/disruption/config/v1alpha1/conversion.go @@ -0,0 +1,40 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/conversion" + "k8s.io/kube-controller-manager/config/v1alpha1" + disruptionconfig "k8s.io/kubernetes/pkg/controller/disruption/config" +) + +// Important! The public back-and-forth conversion functions for the types in this package +// with DisruptionControllerConfiguration types need to be manually exposed like this in order for +// other packages that reference this package to be able to call these conversion functions +// in an autogenerated manner. +// TODO: Fix the bug in conversion-gen so it automatically discovers these Convert_* functions +// in autogenerated code as well. + +// Convert_v1alpha1_DisruptionControllerConfiguration_To_config_DisruptionControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_DisruptionControllerConfiguration_To_config_DisruptionControllerConfiguration(in *v1alpha1.DisruptionControllerConfiguration, out *disruptionconfig.DisruptionControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_DisruptionControllerConfiguration_To_config_DisruptionControllerConfiguration(in, out, s) +} + +// Convert_config_DisruptionControllerConfiguration_To_v1alpha1_DisruptionControllerConfiguration is an autogenerated conversion function. +func Convert_config_DisruptionControllerConfiguration_To_v1alpha1_DisruptionControllerConfiguration(in *disruptionconfig.DisruptionControllerConfiguration, out *v1alpha1.DisruptionControllerConfiguration, s conversion.Scope) error { + return autoConvert_config_DisruptionControllerConfiguration_To_v1alpha1_DisruptionControllerConfiguration(in, out, s) +} diff --git a/pkg/controller/disruption/config/v1alpha1/defaults.go b/pkg/controller/disruption/config/v1alpha1/defaults.go new file mode 100644 index 00000000000..aafc0b5728c --- /dev/null +++ b/pkg/controller/disruption/config/v1alpha1/defaults.go @@ -0,0 +1,36 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + kubectrlmgrconfigv1alpha1 "k8s.io/kube-controller-manager/config/v1alpha1" +) + +// RecommendedDefaultDisruptionControllerConfiguration defaults a pointer to a +// DisruptionControllerConfiguration struct. This will set the recommended default +// values, but they may be subject to change between API versions. This function +// is intentionally not registered in the scheme as a "normal" `SetDefaults_Foo` +// function to allow consumers of this type to set whatever defaults for their +// embedded configs. Forcing consumers to use these defaults would be problematic +// as defaulting in the scheme is done as part of the conversion, and there would +// be no easy way to opt-out. Instead, if you want to use this defaulting method +// run it in your wrapper struct of this type in its `SetDefaults_` method. +func RecommendedDefaultDisruptionControllerConfiguration(obj *kubectrlmgrconfigv1alpha1.DisruptionControllerConfiguration) { + if obj.ConcurrentDisruptionSyncs == 0 { + obj.ConcurrentDisruptionSyncs = 1 + } +} diff --git a/pkg/controller/disruption/config/v1alpha1/doc.go b/pkg/controller/disruption/config/v1alpha1/doc.go new file mode 100644 index 00000000000..4dc6989b9f8 --- /dev/null +++ b/pkg/controller/disruption/config/v1alpha1/doc.go @@ -0,0 +1,21 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:conversion-gen=k8s.io/kubernetes/pkg/controller/disruption/config +// +k8s:conversion-gen-external-types=k8s.io/kube-controller-manager/config/v1alpha1 + +package v1alpha1 diff --git a/pkg/controller/disruption/config/v1alpha1/register.go b/pkg/controller/disruption/config/v1alpha1/register.go new file mode 100644 index 00000000000..85bbf3effe4 --- /dev/null +++ b/pkg/controller/disruption/config/v1alpha1/register.go @@ -0,0 +1,31 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime" +) + +var ( + // SchemeBuilder is the scheme builder with scheme init functions to run for this API package + SchemeBuilder runtime.SchemeBuilder + // localSchemeBuilder extends the SchemeBuilder instance with the external types. In this package, + // defaulting and conversion init funcs are registered as well. + localSchemeBuilder = &SchemeBuilder + // AddToScheme is a global function that registers this API group & version to a scheme + AddToScheme = localSchemeBuilder.AddToScheme +) diff --git a/pkg/controller/disruption/config/v1alpha1/zz_generated.conversion.go b/pkg/controller/disruption/config/v1alpha1/zz_generated.conversion.go new file mode 100644 index 00000000000..9a5a133ecc3 --- /dev/null +++ b/pkg/controller/disruption/config/v1alpha1/zz_generated.conversion.go @@ -0,0 +1,92 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + unsafe "unsafe" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + configv1alpha1 "k8s.io/kube-controller-manager/config/v1alpha1" + config "k8s.io/kubernetes/pkg/controller/disruption/config" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*configv1alpha1.GroupResource)(nil), (*v1.GroupResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_GroupResource_To_v1_GroupResource(a.(*configv1alpha1.GroupResource), b.(*v1.GroupResource), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1.GroupResource)(nil), (*configv1alpha1.GroupResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_GroupResource_To_v1alpha1_GroupResource(a.(*v1.GroupResource), b.(*configv1alpha1.GroupResource), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*config.DisruptionControllerConfiguration)(nil), (*configv1alpha1.DisruptionControllerConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_DisruptionControllerConfiguration_To_v1alpha1_DisruptionControllerConfiguration(a.(*config.DisruptionControllerConfiguration), b.(*configv1alpha1.DisruptionControllerConfiguration), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*configv1alpha1.DisruptionControllerConfiguration)(nil), (*config.DisruptionControllerConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_DisruptionControllerConfiguration_To_config_DisruptionControllerConfiguration(a.(*configv1alpha1.DisruptionControllerConfiguration), b.(*config.DisruptionControllerConfiguration), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1alpha1_DisruptionControllerConfiguration_To_config_DisruptionControllerConfiguration(in *configv1alpha1.DisruptionControllerConfiguration, out *config.DisruptionControllerConfiguration, s conversion.Scope) error { + out.ConcurrentDisruptionSyncs = in.ConcurrentDisruptionSyncs + return nil +} + +func autoConvert_config_DisruptionControllerConfiguration_To_v1alpha1_DisruptionControllerConfiguration(in *config.DisruptionControllerConfiguration, out *configv1alpha1.DisruptionControllerConfiguration, s conversion.Scope) error { + out.ConcurrentDisruptionSyncs = in.ConcurrentDisruptionSyncs + return nil +} + +func autoConvert_v1alpha1_GroupResource_To_v1_GroupResource(in *configv1alpha1.GroupResource, out *v1.GroupResource, s conversion.Scope) error { + *out = *(*v1.GroupResource)(unsafe.Pointer(in)) + return nil +} + +// Convert_v1alpha1_GroupResource_To_v1_GroupResource is an autogenerated conversion function. +func Convert_v1alpha1_GroupResource_To_v1_GroupResource(in *configv1alpha1.GroupResource, out *v1.GroupResource, s conversion.Scope) error { + return autoConvert_v1alpha1_GroupResource_To_v1_GroupResource(in, out, s) +} + +func autoConvert_v1_GroupResource_To_v1alpha1_GroupResource(in *v1.GroupResource, out *configv1alpha1.GroupResource, s conversion.Scope) error { + *out = *(*configv1alpha1.GroupResource)(unsafe.Pointer(in)) + return nil +} + +// Convert_v1_GroupResource_To_v1alpha1_GroupResource is an autogenerated conversion function. +func Convert_v1_GroupResource_To_v1alpha1_GroupResource(in *v1.GroupResource, out *configv1alpha1.GroupResource, s conversion.Scope) error { + return autoConvert_v1_GroupResource_To_v1alpha1_GroupResource(in, out, s) +} diff --git a/pkg/controller/disruption/config/zz_generated.deepcopy.go b/pkg/controller/disruption/config/zz_generated.deepcopy.go new file mode 100644 index 00000000000..bf28c293e68 --- /dev/null +++ b/pkg/controller/disruption/config/zz_generated.deepcopy.go @@ -0,0 +1,38 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package config + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DisruptionControllerConfiguration) DeepCopyInto(out *DisruptionControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DisruptionControllerConfiguration. +func (in *DisruptionControllerConfiguration) DeepCopy() *DisruptionControllerConfiguration { + if in == nil { + return nil + } + out := new(DisruptionControllerConfiguration) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/controller/disruption/disruption.go b/pkg/controller/disruption/disruption.go index 7d813eaba53..20514c72da2 100644 --- a/pkg/controller/disruption/disruption.go +++ b/pkg/controller/disruption/disruption.go @@ -444,7 +444,7 @@ func verifyGroupKind(controllerRef *metav1.OwnerReference, expectedKind string, return slices.Contains(expectedGroups, gv.Group), nil } -func (dc *DisruptionController) Run(ctx context.Context) { +func (dc *DisruptionController) Run(ctx context.Context, workers int) { defer utilruntime.HandleCrash() logger := klog.FromContext(ctx) @@ -472,9 +472,11 @@ func (dc *DisruptionController) Run(ctx context.Context) { return } - wg.Go(func() { - wait.UntilWithContext(ctx, dc.worker, time.Second) - }) + for range workers { + wg.Go(func() { + wait.UntilWithContext(ctx, dc.worker, time.Second) + }) + } wg.Go(func() { wait.Until(dc.recheckWorker, time.Second, ctx.Done()) }) diff --git a/pkg/controller/disruption/disruption_test.go b/pkg/controller/disruption/disruption_test.go index 4f9fa4b8996..3aad6996e29 100644 --- a/pkg/controller/disruption/disruption_test.go +++ b/pkg/controller/disruption/disruption_test.go @@ -1540,7 +1540,7 @@ func TestStalePodDisruption(t *testing.T) { t.Run(name, func(t *testing.T) { tCtx := ktesting.Init(t) dc, _ := newFakeDisruptionControllerWithTime(tCtx, now) - go dc.Run(tCtx) + go dc.Run(tCtx, 1) if _, err := dc.coreClient.CoreV1().Pods(tc.pod.Namespace).Create(tCtx, tc.pod, metav1.CreateOptions{}); err != nil { t.Fatalf("Failed to create pod: %v", err) } diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 2d296afd1ac..1e195203a60 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -1413,6 +1413,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA kubecontrollermanagerconfigv1alpha1.DeploymentControllerConfiguration{}.OpenAPIModelName(): schema_k8sio_kube_controller_manager_config_v1alpha1_DeploymentControllerConfiguration(ref), kubecontrollermanagerconfigv1alpha1.DeprecatedControllerConfiguration{}.OpenAPIModelName(): schema_k8sio_kube_controller_manager_config_v1alpha1_DeprecatedControllerConfiguration(ref), kubecontrollermanagerconfigv1alpha1.DeviceTaintEvictionControllerConfiguration{}.OpenAPIModelName(): schema_k8sio_kube_controller_manager_config_v1alpha1_DeviceTaintEvictionControllerConfiguration(ref), + kubecontrollermanagerconfigv1alpha1.DisruptionControllerConfiguration{}.OpenAPIModelName(): schema_k8sio_kube_controller_manager_config_v1alpha1_DisruptionControllerConfiguration(ref), kubecontrollermanagerconfigv1alpha1.EndpointControllerConfiguration{}.OpenAPIModelName(): schema_k8sio_kube_controller_manager_config_v1alpha1_EndpointControllerConfiguration(ref), kubecontrollermanagerconfigv1alpha1.EndpointSliceControllerConfiguration{}.OpenAPIModelName(): schema_k8sio_kube_controller_manager_config_v1alpha1_EndpointSliceControllerConfiguration(ref), kubecontrollermanagerconfigv1alpha1.EndpointSliceMirroringControllerConfiguration{}.OpenAPIModelName(): schema_k8sio_kube_controller_manager_config_v1alpha1_EndpointSliceMirroringControllerConfiguration(ref), @@ -67614,6 +67615,28 @@ func schema_k8sio_kube_controller_manager_config_v1alpha1_DeviceTaintEvictionCon } } +func schema_k8sio_kube_controller_manager_config_v1alpha1_DisruptionControllerConfiguration(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "DisruptionControllerConfiguration contains elements describing DisruptionController.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "ConcurrentDisruptionSyncs": { + SchemaProps: spec.SchemaProps{ + Description: "concurrentDisruptionSyncs is the number of PodDisruptionBudget objects that are allowed to sync concurrently. Larger number = more responsive PDB updates, but more CPU (and network) load.", + Default: 0, + Type: []string{"integer"}, + Format: "int32", + }, + }, + }, + Required: []string{"ConcurrentDisruptionSyncs"}, + }, + }, + } +} + func schema_k8sio_kube_controller_manager_config_v1alpha1_EndpointControllerConfiguration(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -67957,6 +67980,13 @@ func schema_k8sio_kube_controller_manager_config_v1alpha1_KubeControllerManagerC Ref: ref(kubecontrollermanagerconfigv1alpha1.DeploymentControllerConfiguration{}.OpenAPIModelName()), }, }, + "DisruptionController": { + SchemaProps: spec.SchemaProps{ + Description: "DisruptionControllerConfiguration holds configuration for DisruptionController related features.", + Default: map[string]interface{}{}, + Ref: ref(kubecontrollermanagerconfigv1alpha1.DisruptionControllerConfiguration{}.OpenAPIModelName()), + }, + }, "StatefulSetController": { SchemaProps: spec.SchemaProps{ Description: "StatefulSetControllerConfiguration holds configuration for StatefulSetController related features.", @@ -68133,11 +68163,11 @@ func schema_k8sio_kube_controller_manager_config_v1alpha1_KubeControllerManagerC }, }, }, - Required: []string{"Generic", "KubeCloudShared", "AttachDetachController", "CSRSigningController", "DaemonSetController", "DeploymentController", "StatefulSetController", "DeprecatedController", "EndpointController", "EndpointSliceController", "EndpointSliceMirroringController", "EphemeralVolumeController", "GarbageCollectorController", "HPAController", "JobController", "CronJobController", "LegacySATokenCleaner", "NamespaceController", "NodeIPAMController", "NodeLifecycleController", "PersistentVolumeBinderController", "PodGCController", "ReplicaSetController", "ReplicationController", "ResourceQuotaController", "SAController", "ServiceController", "TTLAfterFinishedController", "ValidatingAdmissionPolicyStatusController", "DeviceTaintEvictionController", "ResourceClaimController"}, + Required: []string{"Generic", "KubeCloudShared", "AttachDetachController", "CSRSigningController", "DaemonSetController", "DeploymentController", "DisruptionController", "StatefulSetController", "DeprecatedController", "EndpointController", "EndpointSliceController", "EndpointSliceMirroringController", "EphemeralVolumeController", "GarbageCollectorController", "HPAController", "JobController", "CronJobController", "LegacySATokenCleaner", "NamespaceController", "NodeIPAMController", "NodeLifecycleController", "PersistentVolumeBinderController", "PodGCController", "ReplicaSetController", "ReplicationController", "ResourceQuotaController", "SAController", "ServiceController", "TTLAfterFinishedController", "ValidatingAdmissionPolicyStatusController", "DeviceTaintEvictionController", "ResourceClaimController"}, }, }, Dependencies: []string{ - configv1alpha1.KubeCloudSharedConfiguration{}.OpenAPIModelName(), serviceconfigv1alpha1.ServiceControllerConfiguration{}.OpenAPIModelName(), controllermanagerconfigv1alpha1.GenericControllerManagerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.AttachDetachControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.CSRSigningControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.CronJobControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.DaemonSetControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.DeploymentControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.DeprecatedControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.DeviceTaintEvictionControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.EndpointControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.EndpointSliceControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.EndpointSliceMirroringControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.EphemeralVolumeControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.GarbageCollectorControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.HPAControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.JobControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.LegacySATokenCleanerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.NamespaceControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.NodeIPAMControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.NodeLifecycleControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.PersistentVolumeBinderControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.PodGCControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.ReplicaSetControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.ReplicationControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.ResourceClaimControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.ResourceQuotaControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.SAControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.StatefulSetControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.TTLAfterFinishedControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.ValidatingAdmissionPolicyStatusControllerConfiguration{}.OpenAPIModelName()}, + configv1alpha1.KubeCloudSharedConfiguration{}.OpenAPIModelName(), serviceconfigv1alpha1.ServiceControllerConfiguration{}.OpenAPIModelName(), controllermanagerconfigv1alpha1.GenericControllerManagerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.AttachDetachControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.CSRSigningControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.CronJobControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.DaemonSetControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.DeploymentControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.DeprecatedControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.DeviceTaintEvictionControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.DisruptionControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.EndpointControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.EndpointSliceControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.EndpointSliceMirroringControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.EphemeralVolumeControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.GarbageCollectorControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.HPAControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.JobControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.LegacySATokenCleanerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.NamespaceControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.NodeIPAMControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.NodeLifecycleControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.PersistentVolumeBinderControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.PodGCControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.ReplicaSetControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.ReplicationControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.ResourceClaimControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.ResourceQuotaControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.SAControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.StatefulSetControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.TTLAfterFinishedControllerConfiguration{}.OpenAPIModelName(), kubecontrollermanagerconfigv1alpha1.ValidatingAdmissionPolicyStatusControllerConfiguration{}.OpenAPIModelName()}, } } diff --git a/staging/src/k8s.io/kube-controller-manager/config/v1alpha1/types.go b/staging/src/k8s.io/kube-controller-manager/config/v1alpha1/types.go index 79498ed098e..f6d0c6f28eb 100644 --- a/staging/src/k8s.io/kube-controller-manager/config/v1alpha1/types.go +++ b/staging/src/k8s.io/kube-controller-manager/config/v1alpha1/types.go @@ -104,6 +104,9 @@ type KubeControllerManagerConfiguration struct { // DeploymentControllerConfiguration holds configuration for // DeploymentController related features. DeploymentController DeploymentControllerConfiguration + // DisruptionControllerConfiguration holds configuration for + // DisruptionController related features. + DisruptionController DisruptionControllerConfiguration // StatefulSetControllerConfiguration holds configuration for // StatefulSetController related features. StatefulSetController StatefulSetControllerConfiguration @@ -238,6 +241,14 @@ type DeploymentControllerConfiguration struct { ConcurrentDeploymentSyncs int32 } +// DisruptionControllerConfiguration contains elements describing DisruptionController. +type DisruptionControllerConfiguration struct { + // concurrentDisruptionSyncs is the number of PodDisruptionBudget objects that + // are allowed to sync concurrently. Larger number = more responsive PDB + // updates, but more CPU (and network) load. + ConcurrentDisruptionSyncs int32 +} + // StatefulSetControllerConfiguration contains elements describing StatefulSetController. type StatefulSetControllerConfiguration struct { // concurrentStatefulSetSyncs is the number of statefulset objects that are diff --git a/staging/src/k8s.io/kube-controller-manager/config/v1alpha1/zz_generated.deepcopy.go b/staging/src/k8s.io/kube-controller-manager/config/v1alpha1/zz_generated.deepcopy.go index 01020e6a86d..c7e1108c105 100644 --- a/staging/src/k8s.io/kube-controller-manager/config/v1alpha1/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/kube-controller-manager/config/v1alpha1/zz_generated.deepcopy.go @@ -159,6 +159,22 @@ func (in *DeviceTaintEvictionControllerConfiguration) DeepCopy() *DeviceTaintEvi return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DisruptionControllerConfiguration) DeepCopyInto(out *DisruptionControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DisruptionControllerConfiguration. +func (in *DisruptionControllerConfiguration) DeepCopy() *DisruptionControllerConfiguration { + if in == nil { + return nil + } + out := new(DisruptionControllerConfiguration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EndpointControllerConfiguration) DeepCopyInto(out *EndpointControllerConfiguration) { *out = *in @@ -314,6 +330,7 @@ func (in *KubeControllerManagerConfiguration) DeepCopyInto(out *KubeControllerMa out.CSRSigningController = in.CSRSigningController out.DaemonSetController = in.DaemonSetController out.DeploymentController = in.DeploymentController + out.DisruptionController = in.DisruptionController out.StatefulSetController = in.StatefulSetController out.DeprecatedController = in.DeprecatedController out.EndpointController = in.EndpointController diff --git a/staging/src/k8s.io/kube-controller-manager/config/v1alpha1/zz_generated.model_name.go b/staging/src/k8s.io/kube-controller-manager/config/v1alpha1/zz_generated.model_name.go index ae2bc80301d..f7e9275489f 100644 --- a/staging/src/k8s.io/kube-controller-manager/config/v1alpha1/zz_generated.model_name.go +++ b/staging/src/k8s.io/kube-controller-manager/config/v1alpha1/zz_generated.model_name.go @@ -61,6 +61,11 @@ func (in DeviceTaintEvictionControllerConfiguration) OpenAPIModelName() string { return "io.k8s.kube-controller-manager.config.v1alpha1.DeviceTaintEvictionControllerConfiguration" } +// OpenAPIModelName returns the OpenAPI model name for this type. +func (in DisruptionControllerConfiguration) OpenAPIModelName() string { + return "io.k8s.kube-controller-manager.config.v1alpha1.DisruptionControllerConfiguration" +} + // OpenAPIModelName returns the OpenAPI model name for this type. func (in EndpointControllerConfiguration) OpenAPIModelName() string { return "io.k8s.kube-controller-manager.config.v1alpha1.EndpointControllerConfiguration" diff --git a/test/integration/disruption/disruption_test.go b/test/integration/disruption/disruption_test.go index c3ba41c6a60..ae457e293e3 100644 --- a/test/integration/disruption/disruption_test.go +++ b/test/integration/disruption/disruption_test.go @@ -123,7 +123,7 @@ func TestPDBWithScaleSubresource(t *testing.T) { createNs(tCtx, t, nsName, clientSet) informers.Start(tCtx.Done()) - go pdbc.Run(tCtx) + go pdbc.Run(tCtx, 1) crdDefinition := newCustomResourceDefinition() etcd.CreateTestCRDs(t, apiExtensionClient, true, crdDefinition) @@ -255,7 +255,7 @@ func TestEmptySelector(t *testing.T) { createNs(tCtx, t, nsName, clientSet) informers.Start(tCtx.Done()) - go pdbc.Run(tCtx) + go pdbc.Run(tCtx, 1) replicas := 4 minAvailable := intstr.FromInt32(2) @@ -369,7 +369,7 @@ func TestSelectorsForPodsWithoutLabels(t *testing.T) { createNs(tCtx, t, nsName, clientSet) informers.Start(tCtx.Done()) - go pdbc.Run(tCtx) + go pdbc.Run(tCtx, 1) minAvailable := intstr.FromInt32(1) @@ -541,7 +541,7 @@ func TestPatchCompatibility(t *testing.T) { // We can't cancel immediately but later, because when the context is canceled, // the event broadcaster will be shut down . defer tCtx.Cancel("cleaning up") - go pdbc.Run(tCtx) + go pdbc.Run(tCtx, 1) testcases := []struct { name string @@ -646,7 +646,7 @@ func TestStalePodDisruption(t *testing.T) { informers.Start(tCtx.Done()) informers.WaitForCacheSync(tCtx.Done()) - go pdbc.Run(tCtx) + go pdbc.Run(tCtx, 1) cases := map[string]struct { deletePod bool diff --git a/test/integration/evictions/evictions_test.go b/test/integration/evictions/evictions_test.go index 1e3bd481daf..a25c62643dc 100644 --- a/test/integration/evictions/evictions_test.go +++ b/test/integration/evictions/evictions_test.go @@ -75,7 +75,7 @@ func TestConcurrentEvictionRequests(t *testing.T) { defer tCtx.Cancel("test has completed") informers.Start(tCtx.Done()) - go rm.Run(tCtx) + go rm.Run(tCtx, 1) var gracePeriodSeconds int64 = 30 deleteOption := metav1.DeleteOptions{ @@ -188,7 +188,7 @@ func TestTerminalPodEviction(t *testing.T) { defer tCtx.Cancel("test has completed") informers.Start(tCtx.Done()) - go rm.Run(tCtx) + go rm.Run(tCtx, 1) var gracePeriodSeconds int64 = 30 deleteOption := metav1.DeleteOptions{ @@ -259,7 +259,7 @@ func TestEvictionVersions(t *testing.T) { defer tCtx.Cancel("test has completed") informers.Start(tCtx.Done()) - go rm.Run(tCtx) + go rm.Run(tCtx, 1) ns := "default" subresource := "eviction" @@ -372,7 +372,7 @@ func TestEvictionWithFinalizers(t *testing.T) { defer tCtx.Cancel("test has completed") informers.Start(tCtx.Done()) - go rm.Run(tCtx) + go rm.Run(tCtx, 1) pod := newPod("pod") pod.ObjectMeta.Finalizers = []string{"test.k8s.io/finalizer"} @@ -447,7 +447,7 @@ func TestEvictionWithUnhealthyPodEvictionPolicy(t *testing.T) { defer tCtx.Cancel("test has completed") informers.Start(tCtx.Done()) - go rm.Run(tCtx) + go rm.Run(tCtx, 1) pod := newPod("pod") if _, err := clientSet.CoreV1().Pods(ns.Name).Create(context.TODO(), pod, metav1.CreateOptions{}); err != nil { @@ -540,7 +540,7 @@ func TestEvictionWithPrecondition(t *testing.T) { defer tCtx.Cancel("test has completed") informers.Start(tCtx.Done()) - go rm.Run(tCtx) + go rm.Run(tCtx, 1) pod := newPod("pod") pod, err := clientSet.CoreV1().Pods(ns.Name).Create(context.TODO(), pod, metav1.CreateOptions{}) diff --git a/test/integration/util/util.go b/test/integration/util/util.go index a328019b283..8db9317be6d 100644 --- a/test/integration/util/util.go +++ b/test/integration/util/util.go @@ -710,7 +710,7 @@ func InitDisruptionController(t *testing.T, testCtx *TestContext) *disruption.Di informers.Start(testCtx.Scheduler.StopEverything) informers.WaitForCacheSync(testCtx.Scheduler.StopEverything) - go dc.Run(testCtx.Ctx) + go dc.Run(testCtx.Ctx, 1) return dc }