diff --git a/staging/src/k8s.io/apiserver/pkg/util/webhook/client.go b/staging/src/k8s.io/apiserver/pkg/util/webhook/client.go index 02bf38ff980..d750c3f7c03 100644 --- a/staging/src/k8s.io/apiserver/pkg/util/webhook/client.go +++ b/staging/src/k8s.io/apiserver/pkg/util/webhook/client.go @@ -131,6 +131,10 @@ func (cm *ClientManager) HookClient(cc ClientConfig) (*rest.RESTClient, error) { } complete := func(cfg *rest.Config) (*rest.RESTClient, error) { + // Avoid client-side rate limiting talking to the webhook backend. + // Rate limiting should happen when deciding how many requests to serve. + cfg.QPS = -1 + // Combine CAData from the config with any existing CA bundle provided if len(cfg.TLSClientConfig.CAData) > 0 { cfg.TLSClientConfig.CAData = append(cfg.TLSClientConfig.CAData, '\n') diff --git a/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook.go b/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook.go index 917d66c9222..d2c6e2273f7 100644 --- a/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook.go +++ b/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook.go @@ -88,6 +88,10 @@ func newGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFact // Set this to something reasonable so request to webhooks don't hang forever. clientConfig.Timeout = requestTimeout + // Avoid client-side rate limiting talking to the webhook backend. + // Rate limiting should happen when deciding how many requests to serve. + clientConfig.QPS = -1 + codec := codecFactory.LegacyCodec(groupVersions...) clientConfig.ContentConfig.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: codec}) diff --git a/test/integration/apiserver/admissionwebhook/admission_test.go b/test/integration/apiserver/admissionwebhook/admission_test.go index 688dd6e3fff..c75366c551e 100644 --- a/test/integration/apiserver/admissionwebhook/admission_test.go +++ b/test/integration/apiserver/admissionwebhook/admission_test.go @@ -566,6 +566,9 @@ func testWebhookAdmission(t *testing.T, watchCache bool) { // Allow the webhook to establish time.Sleep(time.Second) + start := time.Now() + count := 0 + // Test admission on all resources, subresources, and verbs for _, gvr := range gvrsToTest { resource := resourcesByGVR[gvr] @@ -573,6 +576,7 @@ func testWebhookAdmission(t *testing.T, watchCache bool) { for _, verb := range []string{"create", "update", "patch", "connect", "delete", "deletecollection"} { if shouldTestResourceVerb(gvr, resource, verb) { t.Run(verb, func(t *testing.T) { + count++ holder.reset(t) testFunc := getTestFunc(gvr, verb) testFunc(&testContext{ @@ -591,6 +595,12 @@ func testWebhookAdmission(t *testing.T, watchCache bool) { } }) } + + duration := time.Now().Sub(start) + perResourceDuration := time.Duration(int(duration) / count) + if perResourceDuration >= 150*time.Millisecond { + t.Errorf("expected resources to process in < 150ms, average was %v", perResourceDuration) + } } //