In this blog we are going to talk about admission controllers, how they interact with Kubernetes and what they can do for us. Well, I want to start by just sort of diagramming out what a request looks like when it comes into Kubernetes.
- There are basically three parts.
First obviously the person or potential automation that is making the API call that goes to the API server and eventually to the database. That’s the basic flow of all API requests.
Now inside the API server itself, there is code that does RBAC for authorization and also does authentication. So, that allows you to say, hey, this user can or can’t do certain things within the cluster. But there’s a lot of stuff that you might want to do that involves either modifying or validating an API object that looks within the API object itself in order to make decisions or even make modifications.
And that’s where admission controllers come in.
What is admission controller:
An admission controller is a very powerful feature that intercepts the requests to API server after it has be authenticated and authorized. It then validates and modifies the request before persisting it to etcd.
There are two basic classes of admission controllers.
- Validating admission controllers: It looks at the contents of an API object and make sure that it’s a valid API object. We’ll talk a little bit about some use cases for that
- Mutating admission controllers: It looks at the API object and actually changes it. It may add or remove things from the API object and modifies it in the way in.
Why do we need admission Controller:
The admission controller acts as a guard to our cluster. They are there to enforce different kind of policies to our resource requests like:
- Allow pulling images only from specific registries known to the enterprise, while denying unknown image registries.
- Reject deployments that do not meet security standards. For example, containers using the privileged flag. The request can also be mutated by overriding the privileged flag to false.
- Ensuring reasonable labels and annotations are added to the pods.
- Automatically adding resource limits or validating resource limits.
And many more..
It allows us to catch all non-compliance early in the stage, and helps preventing them.
Setup Admission Controller
Kubernetes comes with 30 of these Admission controllers already there in API server. By default some of these controllers are enabled while others can be enabled by cluster administrator when starting the API server.
How to check which controllers are enabled by default ?
$kubectl describe -n kube-system pods kube-apiserver-minikube | grep enable-admission-plugins --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota
I am currently using a minikube setup.For any other setup, you just need to describe the API server and look for “enable-admission-plugins” flag.
To enable a controller:
- Admission controllers can only be enabled by Cluster Administrator when starting the API server.
- The Kubernetes API server flag “enable-admission-plugins” takes a comma-delimited list of admission control plugins to invoke.
- The way of doing this can differ depending on the way the cluster is setup. For example, we may have to modify the systemd unit file if the API server is deployed as a systemd service, we may modify the manifest file for the API server if Kubernetes is deployed in a self-hosted way.
- In minikubes, this can be achieved by adding an extra-config flag when starting minikube.
minikube start --extra-config=apiserver.enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook
What does some of these Admission controllers do?
- NamespaceLifecycle: It enforces that a Namespace that is undergoing termination cannot have new objects created in it, and ensures that requests in a non-existent Namespace are rejected. It also prevents deletion of three system reserved namespaces default, kube-system, kube-public.
- LimitRanger: This plug-in will observe the incoming request and ensure that it does not violate any of the constraints enumerated in the LimitRange object in a Namespace.
- DefaultStorageClass: This plug-in observes creation of PersistentVolumeClaim objects that do not request any specific storage class and automatically adds a default storage class to them.
From the list of all the admission controllers present, two of them are very special. They are:
- MutatingAdmissionWebhook: This admission controller calls any mutating webhooks which match the request. Matching webhooks are called in serial; each one may modify the object if it desires.
- ValidatingAdmissionWebhook: This admission controller calls any validating webhooks which match the request. Matching webhooks are called in parallel; if any of them rejects the request, the request fails
Benefit of Webhooks
Kubernetes cluster administrators can use webhooks to create additional mutating and validating admission plugins to the admission chain of apiserver without recompiling them.This provides developers with the freedom and flexibility to customize admission logic on multiple actions such CREATE, UPDATE, and DELETE on any resource. The number of applications that can be used are vast. Some common use cases include:
- Customising default values (eg. resources limits)
- More sophisticated Validation than in admission controllers delivered with Kubernetes
- Preventing users from creating/modifying/deleting particular resources that should be immutable (eg. RBAC policies can grant access to all pods in namespace and defining exception on that level is not possible)
- Modifying deployments to inject sidecar containers like log collectors, monitoring and auditing applications, and additional traffic controllers like Istio.
Setting Up Admission Webhook:
- First, we need to create an admission webhook server, that handles admissionReview requests from the API server and returns admissionReview response object back to the API server.
- Next, we need to create a MutattingWebhookConfigration or ValidatingWebhookConfigration to register our webhook server to the api server. The WebhookConfigration looks something like this.
kind: ValidatingWebhookConfiguration apiVersion: admissionregistration.k8s.io/v1beta1 metadata: name: < Webhook configuration name > webhooks: - name: < Webhook Name > rules: - operations: ["CREATE", "UPDATE"] apiGroups: ["*"] apiVersions: ["*"] resources: ["*"] clientConfig: caBundle: < Base64 encoded ca bundle> service: namespace: < namespace where webhook server is deployed> name: <Name of the service for the server>
How does the complete picture looks like?
Admission controller is one of the many powerful features of Kubernetes. They can help us enforce our organizational policies for the cluster. Most of the basic features of Kubernetes are also implemented using Admission controllers. The mutating webhooks are allowing us to expand the API server. This opens door to implement many cool features in our cluster.