kubewebhook
Kubewebhook is a small Go framework to create external admission webhooks for Kubernetes.
With Kubewebhook you can make validating and mutating webhooks in any version, fast, easy, and focusing mainly on the domain logic of the webhook itself.
Features
- Ready for mutating and validating webhook kinds.
- Abstracts webhook versioning (compatible with
v1beta1
andv1
). - Resource inference (compatible with
CRD
s and fallbacks toUnstructured
). - Easy and testable API.
- Simple, extensible and flexible.
- Multiple webhooks on the same server.
- Webhook metrics (RED) for Prometheus with Grafana dashboard included.
- Webhook tracing with Opentelemetry support.
- Supports warnings.
Getting started
Use github.com/slok/kubewebhook/v2
to import Kubewebhook v2
.
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
You can get more examples in here
Production ready example
This repository is a production ready webhook app: https://github.com/slok/k8s-webhook-example
It shows, different webhook use cases, app structure, testing domain logic, kubewebhook use case, how to deploy...
Static and dynamic webhooks
We have 2 kinds of webhooks:
- Static: Common one, is a single resource type webhook.
- Use
mutating.WebhookConfig.Obj
to configure. - Use
validating.WebhookConfig.Obj
to configure.
- Use
- Dynamic: Used when the same webhook act on multiple types, unknown types and/or is used for generic stuff (e.g labels).
- To use this kind of webhook, don't set the type on the configuration or set to
nil
. - If a request for an unknown type is not known by the webhook libraries, it will fallback to
runtime.Unstructured
object type. - Very useful to manipulate multiple resources on the same webhook (e.g
Deployments
,Statefulsets
). - CRDs are unknown types so they will fallback to
runtime.Unstructured
`. - If using CRDs, better use
Static
webhooks. - Very useful to maniputale any
metadata
based validation or mutations (e.gLabels, annotations...
)
- To use this kind of webhook, don't set the type on the configuration or set to
Compatibility matrix
The Kubernetes' version associated with Kubewebhook's versions means that this specific version
is tested and supports the shown K8s version, however, this doesn't mean that doesn't work with other versions. Normally they work with multiple versions (e.g v1.18
and v1.19
).
Kubewebhook | Kubernetes | Admission reviews | Dynamic webhooks | OpenTelemetry tracing |
---|---|---|---|---|
v2.5 | 1.25 | v1beta1, v1 | ||
v2.4 | 1.24 | v1beta1, v1 | ||
v2.3 | 1.23 | v1beta1, v1 | ||
v2.2 | 1.22 | v1beta1, v1 | ||
v2.1 | 1.21 | v1beta1, v1 | ||
v2.1 | 1.21 | v1beta1, v1 | ||
v2.1 | 1.21 | v1beta1, v1 | ||
v2.0 | 1.20 | v1beta1, v1 | ||
v0.11 | 1.19 | v1beta1 | ||
v0.10 | 1.18 | v1beta1 | ||
v0.9 | 1.18 | v1beta1 | ||
v0.8 | 1.17 | v1beta1 | ||
v0.7 | 1.16 | v1beta1 | ||
v0.6 | 1.15 | v1beta1 | ||
v0.5 | 1.14 | v1beta1 | ||
v0.4 | 1.13 | v1beta1 | ||
v0.3 | 1.12 | v1beta1 | ||
v0.2 | 1.11 | v1beta1 | ||
v0.2 | 1.10 | v1beta1 |
Documentation
You can access here.