Skip to content

cloudkite-io/custom-mutating-webhook

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A configurable Kubernetes mutating admission webhook, written using Python's FastAPI.

Docker image

The Docker image for this service is publicly accessible at:

TAG='20260707-1'
gcr.io/cloudkite-public/custom-mutating-webhook:20260707-1

How it works

The FastAPI service handles admission requests through the /mutate path. Upon receiving a request, it performs various checks, such as the namespace of the resource. Subsequently, it generates an admission response containing the patch to be applied to the resource. The charts directory holds the necessary Helm templates for deploying the mutating admission webhook within a Kubernetes cluster.

Prerequisites

Run the generate-cert.sh script. The script will create a self signed SSL certificate and save the base64 encoded certificate and key to the chart/secrets.yaml file.

Environment variables

VARIABLE NAME DESCRIPTION REQUIRED? DEFAULT VALUE
PATCH_DICT This is a JSON which contains key-value pairs, where the keys represent the patch path, and the values represent the patch values. The patch path acts as a field selector, indicating the resource path to the field you wish to patch, starting from the root. The specific path varies depending on the resource type. For example, the path to labels in a pod is /metadata/labels. The patch value is the new value you intend to apply using the mutating webhook. See example in ./charts/values.yaml. Yes None
PATCH_OPERATION The patch operation to be used. See the docs No "add"
MATCH_NAMESPACES A comma separated string of namespaces in which resources should be patched. If not set, it defaults to all namespaces. No None
IMAGE_PULL_SECRET The name of a kubernetes.io/dockerconfigjson secret to inject into the pod's imagePullSecrets. It is only injected when at least one container, init container, or ephemeral container uses an image from a matched registry (see MATCH_REGISTRIES). The secret is appended without clobbering existing pull secrets and is skipped if already present. The referenced secret must exist in each matched namespace. No None
MATCH_REGISTRIES A comma separated list of registry hosts whose images should receive the injected IMAGE_PULL_SECRET (e.g. docker.io,ghcr.io). Trailing slashes are optional. The special value * matches every image regardless of registry. When Docker Hub (docker.io, index.docker.io, or registry-1.docker.io) is in the list, images with no registry host such as nginx are also matched, since they implicitly pull from Docker Hub. Only used when IMAGE_PULL_SECRET is set. No "docker.io,index.docker.io,registry-1.docker.io"
METRICS_PORT The port on which Prometheus metrics are served (plaintext, separate from the TLS webhook port). Exposes counters for admission requests, patch operations, and imagePullSecret injections, plus a request-latency histogram. No 8080

Use cases

1. Injecting imagePullSecrets to avoid Docker Hub rate limits

Set IMAGE_PULL_SECRET to a kubernetes.io/dockerconfigjson secret holding authenticated Docker Hub credentials. Any pod pulling a Docker Hub image (e.g. nginx:1.29, bitnamilegacy/nginx:1.2.4) automatically gets the secret injected, so pulls use your authenticated (higher) rate limit instead of the anonymous one.

IMAGE_PULL_SECRET: "dockerhub-pull-secret"
# MATCH_REGISTRIES defaults to Docker Hub, so no further config is needed.

2. Injecting pull secrets for private/other registries

Point MATCH_REGISTRIES at any registries you want covered. Store multi-registry credentials in a single dockerconfigjson secret and inject it everywhere it's needed.

IMAGE_PULL_SECRET: "registry-creds"
MATCH_REGISTRIES: "ghcr.io,quay.io"        # inject only for these registries
# or MATCH_REGISTRIES: "*" to inject for every image regardless of registry.

3. Adding a default liveness/readiness probe to workloads

Use PATCH_DICT to attach a standard probe to matched pods, enforcing a health-check convention across teams without editing every manifest.

PATCH_DICT: |
  {
    "/spec/containers/0/livenessProbe": {
      "exec": { "command": ["sh", "-c", "if timeout 4 cat /proc/1/fd/1 | grep .; then exit 0; else exit 1; fi"] },
      "initialDelaySeconds": 10, "periodSeconds": 10, "timeoutSeconds": 5, "failureThreshold": 3
    }
  }

4. Enforcing labels or annotations on resources

Add organizational metadata (cost-center labels, ownership annotations, sidecar-injection flags) to every matched resource.

PATCH_DICT: |
  {
    "/metadata/labels/managed-by": "platform-team",
    "/metadata/annotations/example.com~1injected": "true"
  }

5. Scoping mutations to specific namespaces

Combine MATCH_NAMESPACES with any of the above to limit changes to a subset of namespaces (e.g. only staging and dev), leaving production untouched.

MATCH_NAMESPACES: "staging,dev"

6. Observability of the webhook itself

Scrape the Prometheus metrics on METRICS_PORT to alert on admission errors, track patch volume, and monitor how often pull secrets are injected — useful for verifying rollout and catching regressions.

References.

  1. https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/
  2. https://github.com/kubernetes/api/blob/master/admissionregistration/v1/types.go

About

A configurable Kubernetes mutating admission webhook, written using Python's FastAPI.

Resources

License

Stars

0 stars

Watchers

2 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors