kubewebhook

repository·master·Indexed Aug 4, 2026

https://github.com/slok/kubewebhook

A Go framework for simplifying the creation of Kubernetes external admission webhooks, supporting both mutating and validating types. It abstracts versioning complexities and provides built-in support for resource inference, metrics, tracing, and both static and dynamic webhook modes.

Tokens
1.9K
Snippets
3
Records
5
Agent score
21%

What's inside kubewebhook

  1. Static vs Dynamic webhooks

    master

    Kubewebhook supports two modes of operation depending on how you configure the resource type:

    Static Webhooks

    Used when a webhook is dedicated to a single resource type.

    • For mutating webhooks, configure the resource type using mutating.WebhookConfig.Obj.
    • For validating webhooks, configure the resource type using validating.WebhookConfig.Obj.
    • This is the recommended approach when working with Custom Resource Definitions (CRDs).

    Dynamic Webhooks

    Used when a single webhook needs to act on multiple types, unknown types, or generic metadata (like labels and annotations).

    • How to use: Do not set the type in the configuration (set it to nil).
    • Behavior: If a request arrives for a type not explicitly known by the library, it falls back to using a runtime.Unstructured object.
    • Use cases: Manipulating metadata (labels, annotations) across various resources like Deployments and Statefulsets simultaneously.
  2. Get started with Kubewebhook v2

    master

    To create a mutating webhook using Kubewebhook v2, import github.com/slok/kubewebhook/v2. You need to define a mutator function, create a webhook instance, and then wrap it in an HTTP handler to serve it over TLS.

    Key steps:

    1. Define a mutator using kwhmutating.MutatorFunc.
    2. Initialize the webhook with kwhmutating.NewWebhook using a kwhmutating.WebhookConfig.
    3. Generate an HTTP handler using kwhhttp.HandlerFor with kwhhttp.HandlerConfig.
    4. Serve the handler using http.ListenAndServeTLS.
    func run() error {
        logger := &kwhlog.Std{Debug: true}
    
        // Create our mutator
        mt := kwhmutating.MutatorFunc(func(_ context.Context, _ *kwhmodel.AdmissionReview, obj metav1.Object) (*kwhmutating.MutatorResult, error) {
            pod, ok := obj.(*corev1.Pod)
            if !ok {
                return &kwhmutating.MutatorResult{}, nil
            }
    
            // Mutate our object with the required annotations.
            if pod.Annotations == nil {
                pod.Annotations = make(map[string]string)
            }
            pod.Annotations["mutated"] = "true"
            pod.Annotations["mutator"] = "pod-annotate"
    
            return &kwhmutating.MutatorResult{MutatedObject: pod}, nil
        })
    
        // Create webhook.
        wh, err := kwhmutating.NewWebhook(kwhmutating.WebhookConfig{
            ID:      "pod-annotate",
            Mutator: mt,
            Logger:  logger,
        })
        if err != nil {
            return fmt.Errorf("error creating webhook: %w", err)
        }
    
        // Get HTTP handler from webhook.
        whHandler, err := kwhhttp.HandlerFor(kwhhttp.HandlerConfig{Webhook: wh, Logger: logger})
        if err != nil {
            return fmt.Errorf("error creating webhook handler: %w", err)
        }
    
        // Serve.
        logger.Infof("Listening on :8080")
        err = http.ListenAndServeTLS(":8080", cfg.certFile, cfg.keyFile, whHandler)
        if err != nil {
            return fmt.Errorf("error serving webhook: %w", err)
        }
    
        return nil
    }
  3. Deploy a validating webhook to validate Ingress hosts

    master

    This example demonstrates a validating webhook that ensures all Ingress rule hosts match a specific regular expression. If a host does not match the regex, the Ingress resource is denied admission.

    Setup Steps:

    1. Deploy certificates: Apply the validating webhook certificates.
      kubectl apply -f ./ingress-host-validator/deploy/webhook-certs.yaml
    2. Deploy the webhook: Deploy the validating webhook server.
      kubectl apply -f ./ingress-host-validator/deploy/webhook.yaml
    3. Register the webhook: Register the validating webhook with the Kubernetes API server.
      kubectl apply -f ./ingress-host-validator/deploy/webhook-registration.yaml

    Verification: Deploy a test Ingress resource and observe whether the API server accepts or denies the resource based on the host matching the regex:

    kubectl apply -f ./test-ingress.yaml
    kubectl apply -f ./ingress-host-validator/deploy/webhook-certs.yaml
    kubectl apply -f ./ingress-host-validator/deploy/webhook.yaml
    kubectl apply -f ./ingress-host-validator/deploy/webhook-registration.yaml
  4. Deploy a mutating webhook to annotate pods

    master

    This example demonstrates how to implement a mutating webhook that automatically adds annotations to pods. To set this up, follow these steps:

    1. Deploy certificates: Apply the required webhook certificates.
      kubectl apply -f ./pod-annotate/deploy/webhook-certs.yaml
    2. Deploy the webhook: Deploy the webhook controller/server.
      kubectl apply -f ./pod-annotate/deploy/webhook.yaml
    3. Register the webhook: Register the mutating webhook with the Kubernetes API server.
      kubectl apply -f ./pod-annotate/deploy/webhook-registration.yaml

    Verification: Deploy a test deployment using the provided test manifest and inspect the resulting pods to verify annotations are present:

    kubectl apply -f ./pod-annotate/deploy/test-deployment.yaml
    kubectl get pods -o yaml
    kubectl apply -f ./pod-annotate/deploy/webhook-certs.yaml
    kubectl apply -f ./pod-annotate/deploy/webhook.yaml
    kubectl apply -f ./pod-annotate/deploy/webhook-registration.yaml
  5. Kubewebhook Compatibility Matrix

    master

    Check the compatibility between Kubewebhook versions and Kubernetes versions.

    KubewebhookKubernetesAdmission reviewsDynamic webhooksOpenTelemetry tracing
    v2.71.31, 1.30, 1.29, 1.28v1beta1, v1✔✔
    v2.61.29, 1.28, 1.27, 1.26v1beta1, v1✔✔
    v2.51.25v1beta1, v1✔✔
    v2.41.24v1beta1, v1✔✔
    v2.31.23v1beta1, v1✔✔
    v2.21.22v1beta1, v1✔✔
    v2.11.21v1beta1, v1✔✖
    v2.01.20v1beta1, v1✔✖
    v0.111.19v1beta1✔✖
    v0.101.18v1beta1✔✖
    v0.91.18v1beta1✖✖
    v0.81.17v1beta1✖✖
    v0.71.16v1beta1✖✖
    v0.61.15v1beta1✖✖
    v0.51.14v1beta1✖✖
    v0.41.13v1beta1✖✖
    v0.31.12v1beta1✖✖
    v0.21.11v1beta1✖✖
    v0.21.10v1beta1✖✖