Webhooks
Your controllers can serve admission webhooks (validating, mutating) and CRD conversion webhooks. Your control plane calls them like a Kubernetes cluster would, through a Service with a certificate it already trusts.
Turning it on
Section titled “Turning it on”In the controller’s settings, set Webhook port to the port your controller serves webhooks
on. controller-runtime uses 9443. In a Tenant, that’s:
controllers:- name: guestbook image: ghcr.io/you/guestbook-operator:v1.0.0 webhook: {port: 9443} # webhook: {} means 9443 tooThe controller then gets:
Service ctrl-<controller>-webhook, port 443 |
In your control plane’s namespace. Your control plane forwards it to the webhook port. |
/tmp/k8s-webhook-server/serving-certs/tls.crt, tls.key |
A serving certificate for that Service, where controller-runtime looks by default. It’s renewed before it expires, and the controller restarts with the new one. |
Pointing webhooks at it
Section titled “Pointing webhooks at it”Use a service reference with your control plane’s namespace (the one in WATCH_NAMESPACE), and
leave caBundle empty: your control plane already trusts the certificate. You don’t need
cert-manager.
apiVersion: admissionregistration.k8s.io/v1kind: ValidatingWebhookConfigurationmetadata: name: guestbookwebhooks:- name: vguestbook.webapp.example.com clientConfig: service: namespace: acme # your control plane's namespace name: ctrl-guestbook-webhook # ctrl-<controller>-webhook path: /validate-webapp-example-com-v1-guestbook rules: - apiGroups: [webapp.example.com] apiVersions: [v1] operations: [CREATE, UPDATE] resources: [guestbooks] admissionReviewVersions: [v1] sideEffects: NoneConversion webhooks work the same way, in the CRD:
spec: conversion: strategy: Webhook webhook: conversionReviewVersions: [v1] clientConfig: service: {namespace: acme, name: ctrl-guestbook-webhook, path: /convert}Services in other namespaces don’t resolve, and url webhooks aren’t given the certificate.
With kubebuilder
Section titled “With kubebuilder”A kubebuilder project’s webhooks work unchanged in the code. In config/:
- Drop cert-manager (the
certmanagerdirectory and thecert-manager.io/inject-ca-fromannotations) and thewebhook-service: ctrlplane provides both. - In the generated webhook configurations and CRD patches, set the service name to
ctrl-<controller>-webhookand the namespace to your control plane’s. - Don’t set
ENABLE_WEBHOOKS=false.
Apply the webhook configurations and CRDs with your control plane’s kubeconfig.
Limits
Section titled “Limits”- Webhooks may only match your own API groups, not built-in ones:
"",*and groups ending ink8s.io(which includesx-k8s.io) orkubernetes.ioare refused. So they can’t intercept namespaces, RBAC or Secrets. - With
failurePolicy: Fail(the default), requests your webhook matches fail while your controller isn’t running, for example while a new version can’t start.