RBAC and Network policies are two fundamental security elements of Kubernetes that you probably already know about if you work with it. These mechanisms are helpful for enforcing fundamental guidelines regarding what operations different users or services within your cluster are permitted to carry out.
However, there are situations when you require more policy features or granularity than RBAC or network policies can provide. Alternatively, you might want to run additional checks to verify a resource before allowing it to join your cluster.
Admission Controllers (ACs) allow you to add additional options to the work of Kubernetes to change or validate objects when making requests to the Kubernetes API.
🖼️ Pic source: Giant Swarm
The image shows the various parts that make up the API component. The request initiates communication between the API and the admission controller. The authorization module determines whether the request issuer is permitted to carry out the operation after the request has been authenticated. The admittance magic kicks in once the request have been duly approved.
If the controller rejects the request, then the entire request to the API server is rejected and an error is returned to the end user.
To activate controllers discussed, you must specify the names of the controllers in the form of a list when creating or updating a cluster. After that,
kube-apiserver will be started or restarted with the
--enable-admission-plugins option and access controllers set.
Passing a controller that is not available for the current version of Kubernetes will return an appropriate error.
Admission controllers that are built into and made available by Kubernetes itself are known as static admission controllers. Not every one of them is turned on by default. The cloud companies also grab some of them or restrict some of them for their own usage. You can enable and utilize them if you are the owner of your Kubernetes deployment. Some examples:
LimitRanger makes sure that any of the restrictions listed in the
LimitRange object in a namespace are not broken by incoming requests. Use this admission controller to impose those restrictions if you are utilizing
LimitRange objects in your Kubernetes setup. Applying default resource requests to pods without any specifications is also possible with this AC.
AlwaysPullImages changes the image pull policy for every new Pod. This is useful, for example, in multi-tenant clusters to ensure that only those with the credentials to fetch private images can access them. Without this admission controller, after an image has been pulled to a node, any pod from any user can use it just by knowing the image's name without any authorization checks. This feature must be enabled in the cluster.
NamespaceLifecycle 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.
And there are dynamic ones. See details below.
There are two types of dynamic admission controllers in Kubernetes. They work slightly differently. Saying shortly, one just validates the requests, and the other modifies it if it isn’t up to spec.
⚙️ The first type is the validating admission controller
ValidatingAdmissionWebhook, which proxies the requests to the subscribed webhooks. The Kubernetes API registers the webhooks based on the resource type and the request method. Every webhook runs some logic to validate the incoming resource, and it replies with a verdict to the API.
In case the validation webhook rejects the request, the Kubernetes API returns a failed HTTP response to the user. Otherwise, it continues with the next admission.
⚙️ The second type is a mutating admission controller
MutatingAdmissionWebhook, which alters the resource that the user has submitted so that default values can be set, or the schema can be verified. The API can have mutation webhooks attached by cluster administrators so that they can execute them similarly to validation.
Any resource type, including those that are pre-built like pods, jobs, or services, may be the primary resource type for a controller. The issue is that most built-in resources, if not all of them, already come with associated built-in controllers. In order to prevent having many controllers update the status of a shared object, custom controllers are frequently built for special resources.
If resources are merely Kubernetes API endpoints, writing a controller for a resource is just a fancy way to bind a request handler to an API endpoint!
Conditional resource modification can be implemented using a so-called webhook, which is essentially an API endpoint.
It is possible to configure dynamically what resources are subject to what admission webhooks via
Both are available in
admissionregistration.k8s.io/v1 API version.
$ kubectl api-versions | grep admiss admissionregistration.k8s.io/v1 admissionregistration.k8s.io/v1beta1
To use before changing cluster objects, the Kubernetes API server flag
--enable-admission-plugins accepts a comma-delimited list of AC plugins. For instance, the following command line activates the
NamespaceLifecycle admission control plugins:
⚠️ Note: You may need to apply the parameters in different ways depending on how your Kubernetes cluster is installed and how the API server is launched. For instance, if Kubernetes is deployed using self-hosted Kubernetes, you may need to alter the manifest file for the API server and/or the
systemd Unit file if the API server is installed as a
⚠️ Note: API kind
admissionregistration.k8s.io/v1beta1 became deprecated in 1.22+
In this case, everything is already set up for you.
To learn more about using dynamic admission controllers with Amazon EKS, see the Amazon EKS documentation.
Azure AKS Policy, Microsoft's implementation of OPA Gatekeeper, is another interesting thing. Involving AC webhooks, if there are problems in the admission control pipeline, it can block numerous requests to the API server.
The VMware Tanzu team followed a similar path in their Tanzu Kubernetes Grid (TKG).
Of course, OPA Gatekeeper itself is a separate and extensive topic, so more on that another time.
In the ninth article of the series, the author will talk about how smart people were able to translate the theory described above into a useful solution.
Be careful and stay tuned!
Many thanks to Leonid Sandler, Douglas Makey @douglasmakey Mendez Molero, Luca 🐦 @LucaDiMaio11 Di Maio, Kristijan Mitevski and W.T. Chang!