diff --git a/vertical-pod-autoscaler/pkg/admission-controller/README.md b/vertical-pod-autoscaler/pkg/admission-controller/README.md index 9e8b67c5b93..2338c73c7db 100644 --- a/vertical-pod-autoscaler/pkg/admission-controller/README.md +++ b/vertical-pod-autoscaler/pkg/admission-controller/README.md @@ -34,6 +34,8 @@ up the changes: ```sudo systemctl restart kubelet.service``` by setting `--register-by-url=true` and passing `--webhook-address` and `--webhook-port`. 1. You can specify a minimum TLS version with `--min-tls-version` with acceptable values being `tls1_2` (default), or `tls1_3`. 1. You can also specify a comma or colon separated list of ciphers for the server to use with `--tls-ciphers` if `--min-tls-version` is set to `tls1_2`. +1. You can optionally provide a of comma separated list of namespaces for the webhook + to ignore using `--webhook-ignore-namespaces`. ## Implementation diff --git a/vertical-pod-autoscaler/pkg/admission-controller/config.go b/vertical-pod-autoscaler/pkg/admission-controller/config.go index 231d7772bfd..9accae78792 100644 --- a/vertical-pod-autoscaler/pkg/admission-controller/config.go +++ b/vertical-pod-autoscaler/pkg/admission-controller/config.go @@ -75,7 +75,7 @@ func configTLS(serverCert, serverKey []byte, minTlsVersion, ciphers string) *tls // register this webhook admission controller with the kube-apiserver // by creating MutatingWebhookConfiguration. -func selfRegistration(clientset *kubernetes.Clientset, caCert []byte, namespace, serviceName, url string, registerByURL bool, timeoutSeconds int32) { +func selfRegistration(clientset *kubernetes.Clientset, caCert []byte, namespace, serviceName, url string, registerByURL bool, timeoutSeconds int32, ignoredNamespaces []string) { time.Sleep(10 * time.Second) client := clientset.AdmissionregistrationV1().MutatingWebhookConfigurations() _, err := client.Get(context.TODO(), webhookConfigName, metav1.GetOptions{}) @@ -96,6 +96,15 @@ func selfRegistration(clientset *kubernetes.Clientset, caCert []byte, namespace, sideEffects := admissionregistration.SideEffectClassNone failurePolicy := admissionregistration.Ignore RegisterClientConfig.CABundle = caCert + namespaceSelector := metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "kubernetes.io/metadata.name", + Operator: metav1.LabelSelectorOpNotIn, + Values: ignoredNamespaces, + }, + }, + } webhookConfig := &admissionregistration.MutatingWebhookConfiguration{ ObjectMeta: metav1.ObjectMeta{ Name: webhookConfigName, @@ -122,10 +131,11 @@ func selfRegistration(clientset *kubernetes.Clientset, caCert []byte, namespace, }, }, }, - FailurePolicy: &failurePolicy, - ClientConfig: RegisterClientConfig, - SideEffects: &sideEffects, - TimeoutSeconds: &timeoutSeconds, + FailurePolicy: &failurePolicy, + ClientConfig: RegisterClientConfig, + SideEffects: &sideEffects, + TimeoutSeconds: &timeoutSeconds, + NamespaceSelector: &namespaceSelector, }, }, } diff --git a/vertical-pod-autoscaler/pkg/admission-controller/main.go b/vertical-pod-autoscaler/pkg/admission-controller/main.go index 7dde2245d62..21476b7520d 100644 --- a/vertical-pod-autoscaler/pkg/admission-controller/main.go +++ b/vertical-pod-autoscaler/pkg/admission-controller/main.go @@ -21,6 +21,7 @@ import ( "fmt" "net/http" "os" + "strings" "time" apiv1 "k8s.io/api/core/v1" @@ -62,19 +63,20 @@ var ( ciphers = flag.String("tls-ciphers", "", "A comma-separated or colon-separated list of ciphers to accept. Only works when min-tls-version is set to tls1_2.") minTlsVersion = flag.String("min-tls-version", "tls1_2", "The minimum TLS version to accept. Must be set to either tls1_2 (default) or tls1_3.") - port = flag.Int("port", 8000, "The port to listen on.") - address = flag.String("address", ":8944", "The address to expose Prometheus metrics.") - kubeconfig = flag.String("kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.") - kubeApiQps = flag.Float64("kube-api-qps", 5.0, `QPS limit when making requests to Kubernetes apiserver`) - kubeApiBurst = flag.Float64("kube-api-burst", 10.0, `QPS burst limit when making requests to Kubernetes apiserver`) - namespace = os.Getenv("NAMESPACE") - serviceName = flag.String("webhook-service", "vpa-webhook", "Kubernetes service under which webhook is registered. Used when registerByURL is set to false.") - webhookAddress = flag.String("webhook-address", "", "Address under which webhook is registered. Used when registerByURL is set to true.") - webhookPort = flag.String("webhook-port", "", "Server Port for Webhook") - webhookTimeout = flag.Int("webhook-timeout-seconds", 30, "Timeout in seconds that the API server should wait for this webhook to respond before failing.") - registerWebhook = flag.Bool("register-webhook", true, "If set to true, admission webhook object will be created on start up to register with the API server.") - registerByURL = flag.Bool("register-by-url", false, "If set to true, admission webhook will be registered by URL (webhookAddress:webhookPort) instead of by service name") - vpaObjectNamespace = flag.String("vpa-object-namespace", apiv1.NamespaceAll, "Namespace to search for VPA objects. Empty means all namespaces will be used.") + port = flag.Int("port", 8000, "The port to listen on.") + address = flag.String("address", ":8944", "The address to expose Prometheus metrics.") + kubeconfig = flag.String("kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.") + kubeApiQps = flag.Float64("kube-api-qps", 5.0, `QPS limit when making requests to Kubernetes apiserver`) + kubeApiBurst = flag.Float64("kube-api-burst", 10.0, `QPS burst limit when making requests to Kubernetes apiserver`) + namespace = os.Getenv("NAMESPACE") + serviceName = flag.String("webhook-service", "vpa-webhook", "Kubernetes service under which webhook is registered. Used when registerByURL is set to false.") + webhookAddress = flag.String("webhook-address", "", "Address under which webhook is registered. Used when registerByURL is set to true.") + webhookPort = flag.String("webhook-port", "", "Server Port for Webhook") + webhookTimeout = flag.Int("webhook-timeout-seconds", 30, "Timeout in seconds that the API server should wait for this webhook to respond before failing.") + registerWebhook = flag.Bool("register-webhook", true, "If set to true, admission webhook object will be created on start up to register with the API server.") + registerByURL = flag.Bool("register-by-url", false, "If set to true, admission webhook will be registered by URL (webhookAddress:webhookPort) instead of by service name") + vpaObjectNamespace = flag.String("vpa-object-namespace", apiv1.NamespaceAll, "Namespace to search for VPA objects. Empty means all namespaces will be used.") + webhookIgnoredNamespaces = flag.String("webhook-ignore-namespaces", "", "Comma separated list of namespaces the admission webhook object will ignore.") ) func main() { @@ -136,9 +138,10 @@ func main() { TLSConfig: configTLS(certs.serverCert, certs.serverKey, *minTlsVersion, *ciphers), } url := fmt.Sprintf("%v:%v", *webhookAddress, *webhookPort) + ignoredNamespaces := strings.Split(*webhookIgnoredNamespaces, ",") go func() { if *registerWebhook { - selfRegistration(kubeClient, certs.caCert, namespace, *serviceName, url, *registerByURL, int32(*webhookTimeout)) + selfRegistration(kubeClient, certs.caCert, namespace, *serviceName, url, *registerByURL, int32(*webhookTimeout), ignoredNamespaces) } // Start status updates after the webhook is initialized. statusUpdater.Run(stopCh)