diff --git a/pkg/controller/namespace/BUILD b/pkg/controller/namespace/BUILD index caec5746a95..002f3f9a7dd 100644 --- a/pkg/controller/namespace/BUILD +++ b/pkg/controller/namespace/BUILD @@ -27,6 +27,7 @@ go_library( "//staging/src/k8s.io/client-go/metadata:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/client-go/util/workqueue:go_default_library", + "//vendor/golang.org/x/time/rate:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], ) diff --git a/pkg/controller/namespace/namespace_controller.go b/pkg/controller/namespace/namespace_controller.go index 4972aecaeb1..7cd6ab2cbb1 100644 --- a/pkg/controller/namespace/namespace_controller.go +++ b/pkg/controller/namespace/namespace_controller.go @@ -20,6 +20,8 @@ import ( "fmt" "time" + "golang.org/x/time/rate" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -71,7 +73,7 @@ func NewNamespaceController( // create the controller so we can inject the enqueue function namespaceController := &NamespaceController{ - queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "namespace"), + queue: workqueue.NewNamedRateLimitingQueue(nsControllerRateLimiter(), "namespace"), namespacedResourcesDeleter: deletion.NewNamespacedResourcesDeleter(kubeClient.CoreV1().Namespaces(), metadataClient, kubeClient.CoreV1(), discoverResourcesFn, finalizerToken), } @@ -99,6 +101,18 @@ func NewNamespaceController( return namespaceController } +// nsControllerRateLimiter is tuned for a faster than normal recycle time with default backoff speed and default overall +// requeing speed. We do this so that namespace cleanup is reliably faster and we know that the number of namespaces being +// deleted is smaller than total number of other namespace scoped resources in a cluster. +func nsControllerRateLimiter() workqueue.RateLimiter { + return workqueue.NewMaxOfRateLimiter( + // this ensures that we retry namespace deletion at least every minute, never longer. + workqueue.NewItemExponentialFailureRateLimiter(5*time.Millisecond, 60*time.Second), + // 10 qps, 100 bucket size. This is only for retry speed and its only the overall factor (not per item) + &workqueue.BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(10), 100)}, + ) +} + // enqueueNamespace adds an object to the controller work queue // obj could be an *v1.Namespace, or a DeletionFinalStateUnknown item. func (nm *NamespaceController) enqueueNamespace(obj interface{}) {