kubewebhook

repository·master·Indexed 20 days ago

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