OpenShift 4 build your First Admission Controller

About this Tutorial

Being a PAAS admin one of the thing that kept me must interested is the ability to create automation for my customers depending on there needs without me having to do all the heavy lifting for each request.

Ever sense Admission Controller came along it was clear to me that this is the way I want to go in case I want to enforce policies (validate) or add complex requirements while my customers need to do next to none (mutate).

I am basing this tutorial on my git repository which you can find here

NOTE

You need to be Cluster Admin in order to create the admission controller.

How does it works ?

The way that it works is once the Admission controller is setup and an API request is being sent to the Kubernetes API the Cluster check if it’s conditions are matched and sends a JSON request to the web server (which we will build).
To complete the process he cluster expects a JSON response with the changes or with a validation replay depending on the admission type.

More information about admission controller can be found at Kubernetes Official Site

There are 2 types of admission controller

  1. Mutating
  2. Validation

Mutating

Mutating admission webhooks are invoked first, and can modify objects sent to the API server to enforce custom defaults. After all object modifications are complete, and after the incoming object is validated by the API server.

Validation

validating admission webhooks are invoked and can reject requests to enforce custom policies.

Where to start ?

The communication between the API server and the webhook (our web server) is force by using SSL.

In order to create the SSL/TLS certificate we will use OpenSSL to generate the CA , the Key and then Sign the certificate (More information about OpenSSL can be found in my Tutorial about “Working with OpenSSL and DNS alternative names” )

To Begin let’s first create an answer file with the name of the service we are going to use :

First let’s clone the repository :

Now let’s Navigate to utils , and you will see 2 files in the directory

Start by creating the namespace and running the generate_crt.sh with the service and the namespace for the webhook pod (for our example we will call it “kubernetes-acpodnaming”

And Run :

The output should look like :

You Noticed that by the end of the run an out put of the CA in Base 64 was givern , we saved the output to a file called “ca_base64.txt” so it will be available for us later on

And we can even generate a variable that will hold the ca base64 :

Once the script is completed you will notice there are a lot of new files in your directory :

Now we will switch to our new Namespace :

And now let’s create a secret from our new certificate :

Now that the secret is created we can go on and build our pod.
For our example I will use registry.example.local as my registry .
Run the following command :

As you can tell by the name it is a pretty KUKU web hook , the only thing that it does is to check if your pod has the name containing the word kuku and only then it will allow us to deploy it.

Or run the build.sh in the project’s top directory:

Once the build is complete you can push the container to your local registry and we can continue to our Deployment

Optional

OpenShift Internal Registry

if you want to work with your OpenShift internal registry you can push it with buildah but you will need to directed the image internally on the deployment

For Example …

Login to OpenShift internal registry :

Now build :

And Push it to the registry :

(Optional Section Ends)

Continue …

Now for the deployment all we need to do is to update the image section under the deployment directory

NOTE !!!

For the internal registry you need to direct to pull internally :

And deploy it :

Once the Image is running we can go ahead and deploy the service :

Now let’s look at the Validating Webhook YAML file to see what is going to happened

As you can see, this admission controller only effects namespace with the annotation of “admission.example.local/podnaming: True” or the admission controller will disregard the namespace

Continue on in the “rules” section we see that this AC (Admission controller) only been called when a pod in been created under the scope of a namespace.

And lastly the configuration tells the Kubernetes API to talk to our acpodnaming service which is located in the “kube-acpodnaming” namespace and needs to be addressed with the path of “/validate” on port 8080 …

The last part is the interesting one … here we are going to replace this content with our CA_BASE64 content we generated in the beginning.

The reason we update our admission controller with the CA that was generated is to enable a clean SSL/TLS connection (PASS the TLS verification step).

After we ran the update on the file we can go ahead and deploy it :

And apply the file :

Congratulations , you have just configured your admission controller , now it is time to test it …

First create a new name space :

And Add annotation to it (if you created it from the tests directory you do not need to patch) :

And Now we can test our AC.

Open A new terminal and run the events with a “wait” flag :

Now deploy the “not working” pod :

Look at the description of the pod and the events on the name space to see what’s going on and what is the feedback we are getting from the AC :

as you can see our admission controller denied our request…

Now delete it :

And deploy the working pod :

Now let’s look at our events :

GREAT !!!!!!

As you can see , all the pods are working and running :

A real life scenario that can help us get a better use case of admission controller such as :

  1. making sure labels exists
  2. forcing the image pull policy on the pods
  3. validation mutation
  4. running external tasks and validating (creating a new git repository when a new name space is been created for example)

we can use this tools to enforce any kind of policy we want. A Tutorial about the code (GO LANG) will be out shortly.

That is it !!!
Have fun …

Open Source contributer for the past 15 years