How to use mutating webhook for the operator with operator-sdk

After reading the instructions on how to create the conversion webhook and the validating webhook, there is no way for the mutating webhook to escape. The custom resource is the source of truth to configure the operand for the Kubernetes operator. Once we have got the content of the CR ready, it does not necessarily need to change. I have done some researches on the use cases of the mutating webhook. The common one is to fill in the fields with the default values, if they are empty. I have not found any other proper use case. Feel free to share it with me, if you find some.

We can set the default values to the CR fields, by implementing the Defaulter interface, the controller-runtime framework provides.

Question for audience: If an operator has enabled all the types of webhooks: conversion webhook, validating webhook and mutating webhook(defaulting webhook), what is the correct order to run all of them, when there is an incoming CR request?

I will give the answer at the end of this article.

Make sure you have done the following steps:

  • Prerequisites
  • Prepare your workstation
  • Create the operator. Follow all the step below this section. You can either choose to finish the creation and configuration of webhook, because that’s also necessary for the defaulting webhook, or skip the command to create the conversion webhook.

Next, let’s walk through how to create the defaulting webhook.

Open the terminal, and go to the home directory of memcached-operator.

There are two versions for the APIs. We will create the validating webhook for the version v1beta1.

Run the following command to create the defaulting webhook:

The flag

in the end will force to create the defaulting webhook, even if there is any.

What has been scaffolded after this command? Go to the file memcached_webhook.go under api/v1beta1, and you can see the following section is added:

Change the annotation admissionReviewVersions={v1,v1beta1} into admissionReviewVersions={v1alpha1,v1beta1}, since we have create the CRDs with v1alpha1 and v1beta1.

In this function Default(), specify the CR fields with the default value if they are empty.

For example, we would like to set the number of replicas into 2, if it is empty.

Implement the function like this:

Update the generated code and regenerate the CRD manifests:

Enable the webhook and certificate manager in manifests:

Go through a few kustomization.yaml files under config/crd, config/default, and config/webhook, and do a few uncomment and comment actions.

For config/crd/kustomization.yaml, uncomment the following lines:

For config/default/kustomization.yaml, uncomment the following lines:

and all the line below vars:

Build the image for v1beta1:

We use the tag v0.0.2 for v1beta1 CRD. Replace <name> with your name registered with

Deploy the operator with v1beta1 resource:

Change the CR sample at config/samples/cache_v1beta1_memcached.yaml into the following contents:

The field replicaSize is left empty. The defaulting webhook will set it into 2 automatically.

Check the log with the command:

Answer to the question: The order of running the webhooks is conversion webhook first, mutating(defaulting webhook) second, and validating webhook last.

Follow Vincent, you won’t derail!



A Chinese software engineer, used to study in Belgium and currently working in US, as Knative & Tekton Operator Lead and Istio Operator Contributor.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Vincent Hou

A Chinese software engineer, used to study in Belgium and currently working in US, as Knative & Tekton Operator Lead and Istio Operator Contributor.