mirror of
https://gitea.com/mcereda/oam.git
synced 2026-02-09 05:44:23 +00:00
268 lines
9.7 KiB
Markdown
268 lines
9.7 KiB
Markdown
# Create an admission webhook
|
|
|
|
The example below will create a webhook which acts as both a `ValidatingAdmissionWebhook` and a `MutatingAdmissionWebhook`, but a real world one can act as only one of them. Or more. Your choice.
|
|
The procedure is executed in a `minikube` cluster, and will use a self signed certificate for the webhook connection.
|
|
|
|
> Be aware of the pros and cons of an `AdmissionWebhook` before deploying one:
|
|
>
|
|
> - when deploying the resources it validates it will **need to be up and running**, or those resources will be rejected
|
|
> - it will need to manage exception to avoid downtime
|
|
|
|
## Table of content <!-- omit in toc -->
|
|
|
|
1. [Concepts reminder](#concepts-reminder)
|
|
1. [Check the webhook controllers are enabled](#check-the-webhook-controllers-are-enabled)
|
|
1. [Write the webhook](#write-the-webhook)
|
|
1. [Create a certificate](#create-a-certificate)
|
|
1. [Configure the webhook](#configure-the-webhook)
|
|
1. [Troubleshooting](#troubleshooting)
|
|
1. [I cannot deploy the resources because the webhook cannot be reached](#i-cannot-deploy-the-resources-because-the-webhook-cannot-be-reached)
|
|
1. [Further readings](#further-readings)
|
|
1. [Sources](#sources)
|
|
|
|
## Concepts reminder
|
|
|
|
There are 2 special admission controllers in the list included in the Kubernetes `apiserver`:
|
|
|
|
- `ValidatingAdmissionWebhook`s, which can reject a request but cannot modify the object they are receiving in the admission request, and
|
|
- `MutatingAdmissionWebhook`s, which can modify objects by creating a patch that will be sent back in the admission response
|
|
|
|
These send admission requests to external HTTP callbacks and receive admission responses. If these two controllers are enabled, a Kubernetes administrator can create and configure an admission webhook in the cluster.
|
|
|
|
To do this:
|
|
|
|
1. [check if the admission webhook controllers are enabled](#check-the-webhook-controllers-are-enabled) in the cluster, and configure them if needed
|
|
1. [write the HTTP callback](#write-the-webhook) that will handle an admission requests; this can be a simple HTTP server that's deployed to the cluster, or even a serverless function just like in [Kelsey's validating webhook demo]
|
|
1. [configure the webhook](#configure-the-webhook) through the `ValidatingWebhookConfiguration` and/or `MutatingWebhookConfiguration` resources
|
|
|
|
## Check the webhook controllers are enabled
|
|
|
|
Check:
|
|
|
|
1. if the `MutatingAdmissionWebhook` and `ValidatingAdmissionWebhook` admission controllers are listed in the correct order in the `admission-control` flag of `kube-apiserver`:
|
|
|
|
```sh
|
|
$ kubectl get pods --namespace 'kube-system' 'kube-apiserver-minikube' -o 'yaml' \
|
|
| yq -y '.spec.containers[]
|
|
| select(.name == "kube-apiserver")
|
|
| .command' \
|
|
- \
|
|
| grep -e '--enable-admission-plugins' \
|
|
| tr ',' '\n' \
|
|
| grep 'AdmissionWebhook'
|
|
MutatingAdmissionWebhook
|
|
ValidatingAdmissionWebhook
|
|
```
|
|
|
|
1. if the admission registration API is enabled in your cluster by running the following:
|
|
|
|
```sh
|
|
$ kubectl api-versions | grep 'admissionregistration.k8s.io'
|
|
admissionregistration.k8s.io/v1
|
|
admissionregistration.k8s.io/v1beta1
|
|
```
|
|
|
|
## Write the webhook
|
|
|
|
Every language is fine as long as the webhook:
|
|
|
|
- accepts an [admission request];
|
|
- spits out an [admission response];
|
|
- uses a certificate to secure the connection, as all admission webhooks need to be on SSL; a self-signed certificate will be more than fine for testing
|
|
|
|
Example: [webhook.py]
|
|
|
|
After the webhook's creation:
|
|
|
|
1. create a containerized image of the webhook and save it to the registry
|
|
Dockerfile: [Dockerfile]
|
|
|
|
```sh
|
|
$ docker build -t webhook .
|
|
|
|
# on minikube
|
|
# will also need imagePullPolicy=Never in the container's spec
|
|
$ minikube cache add webhook
|
|
```
|
|
|
|
1. (if needed, see [below](#create-a-certificate)) to generate the self signed CA, a `CertificateSigningRequest` and the certificate, then create a `Secret` based on this certificate;
|
|
1. create a `Deployment` that will use the image created above; the service **must** be secured via SSL, so mount the secret created from the previous step as volumes in it
|
|
|
|
```yaml
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: webhook
|
|
namespace: test
|
|
labels:
|
|
app: webhook
|
|
spec:
|
|
selector:
|
|
matchLabels:
|
|
app: webhook
|
|
template:
|
|
metadata:
|
|
namespace: test
|
|
labels:
|
|
app: webhook
|
|
spec:
|
|
containers:
|
|
- name: webhook
|
|
image: webhook
|
|
imagePullPolicy: Never # needed by minikube
|
|
ports:
|
|
- containerPort: 8443
|
|
volumeMounts:
|
|
- mountPath: /cert
|
|
name: cert
|
|
volumes:
|
|
- name: cert
|
|
secret:
|
|
secretName: webhook
|
|
```
|
|
|
|
1. create a `Service` pointing to the correct ports in same namespace as the `Deployment`
|
|
|
|
```yaml
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: webhook
|
|
namespace: test
|
|
spec:
|
|
selector:
|
|
app: webhook
|
|
ports:
|
|
- protocol: TCP
|
|
port: 443
|
|
targetPort: 8443
|
|
```
|
|
|
|
### Create a certificate
|
|
|
|
For testing purposes, let's just reuse the [script][certificate script] originally written by the Istio team to generate a certificate signing request:
|
|
|
|
```sh
|
|
cd /tmp
|
|
curl --continue-at - --remote-name https://raw.githubusercontent.com/istio/istio/release-0.7/install/kubernetes/webhook-create-signed-cert.sh
|
|
bash /tmp/webhook-create-signed-cert.sh --service webhook --namespace test --secret webhook
|
|
cd -
|
|
```
|
|
|
|
## Configure the webhook
|
|
|
|
Create a `ValidatingWebhookConfiguration` to register the service for validation upon pod creation:
|
|
|
|
```yaml
|
|
apiVersion: admissionregistration.k8s.io/v1beta1
|
|
kind: ValidatingWebhookConfiguration
|
|
metadata:
|
|
name: validating-webhook
|
|
namespace: test
|
|
webhooks:
|
|
- name: webhook.example.com
|
|
failurePolicy: Fail
|
|
clientConfig:
|
|
service:
|
|
name: webhook
|
|
namespace: test
|
|
path: /validate
|
|
rules:
|
|
- apiGroups: [""]
|
|
resources:
|
|
- "pods"
|
|
apiVersions:
|
|
- "*"
|
|
operations:
|
|
- CREATE
|
|
```
|
|
|
|
At the same way, create a `MutatingWebhookConfiguration` to register the service for mutation upon pod creation:
|
|
|
|
```yaml
|
|
apiVersion: admissionregistration.k8s.io/v1beta1
|
|
kind: MutatingWebhookConfiguration
|
|
metadata:
|
|
name: mutating-webhook
|
|
namespace: test
|
|
labels:
|
|
component: mutating-controller
|
|
webhooks:
|
|
- name: webhook.example.com
|
|
failurePolicy: Fail
|
|
clientConfig:
|
|
service:
|
|
name: webhook
|
|
namespace: test
|
|
path: /mutate
|
|
rules:
|
|
- apiGroups: [""]
|
|
resources:
|
|
- "pods"
|
|
apiVersions:
|
|
- "*"
|
|
operations:
|
|
- CREATE
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### I cannot deploy the resources because the webhook cannot be reached
|
|
|
|
**Solution:** remove the AdmissionWebhook and the Service forwarding to it, then reapply its definition
|
|
|
|
## Further readings
|
|
|
|
- [Admission request]
|
|
- [Admission response]
|
|
- This example's [Dockerfile]
|
|
- This example's [webhook source][webhook.py]
|
|
- This example's [resources]
|
|
- This example's [cert script]
|
|
- [Extensible admission controllers]
|
|
|
|
## Sources
|
|
|
|
All the references in the [further readings] section, plus the following:
|
|
|
|
- [Creating your own admission controller]
|
|
- [Diving into Kubernetes mutatingAdmissionWebhook]
|
|
- [how to write validating and mutating admission controller webhooks in python for kubernetes]
|
|
- [building a kubernetes mutating admission webhook]
|
|
- [K8S admission webhooks]
|
|
- [How to Master Admission Webhooks In Kubernetes]
|
|
- [openshift's generic admission server]
|
|
- [kelsey's validating webhook demo]
|
|
- [morvencao's kube-mutating-webhook-tutorial]
|
|
- [writing a very basic kubernetes mutating admission webhook]
|
|
- Istio's [script][certificate script] to generate a certificate signing request
|
|
|
|
<!--
|
|
References
|
|
-->
|
|
|
|
<!-- Upstream -->
|
|
[admission request]: https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#request
|
|
[admission response]: https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#response
|
|
[cert script]: create-signed-cert.sh
|
|
[certificate script]: https://raw.githubusercontent.com/istio/istio/release-0.7/install/kubernetes/webhook-create-signed-cert.sh
|
|
[dockerfile]: Dockerfile
|
|
[extensible admission controllers]: https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/
|
|
[resources]: resources.yaml
|
|
[webhook.py]: webhook.py
|
|
|
|
<!-- In-article sections -->
|
|
[further readings]: #further-readings
|
|
|
|
<!-- Others -->
|
|
[building a kubernetes mutating admission webhook]: https://didil.medium.com/building-a-kubernetes-mutating-admission-webhook-7e48729523ed
|
|
[creating your own admission controller]: https://docs.giantswarm.io/guides/creating-your-own-admission-controller/
|
|
[diving into kubernetes mutatingadmissionwebhook]: https://medium.com/ibm-cloud/diving-into-kubernetes-mutatingadmissionwebhook-6ef3c5695f74
|
|
[how to master admission webhooks in kubernetes]: https://digizoo.com.au/1376/mastering-admission-webhooks-in-kubernetes-gke-part-1/
|
|
[how to write validating and mutating admission controller webhooks in python for kubernetes]: https://medium.com/analytics-vidhya/how-to-write-validating-and-mutating-admission-controller-webhooks-in-python-for-kubernetes-1e27862cb798
|
|
[k8s admission webhooks]: https://banzaicloud.com/blog/k8s-admission-webhooks/
|
|
[kelsey's validating webhook demo]: https://github.com/kelseyhightower/denyenv-validating-admission-webhook
|
|
[morvencao's kube-mutating-webhook-tutorial]: https://github.com/morvencao/kube-mutating-webhook-tutorial
|
|
[openshift's generic admission server]: https://github.com/openshift/generic-admission-server
|
|
[writing a very basic kubernetes mutating admission webhook]: https://medium.com/ovni/writing-a-very-basic-kubernetes-mutating-admission-webhook-398dbbcb63ec
|