Skip to content

Commit 6485838

Browse files
committed
feature: mutating webhook post ready
Signed-off-by: Batuhan Apaydın <[email protected]>
1 parent 42dd2d5 commit 6485838

2 files changed

+287
-0
lines changed

_posts/2020-10-27-kubernetes-webhooks-made-easy-with-openfaas.md

+6
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,12 @@ $ cd deployment
146146
$ kubectl apply -f rbac.yaml,service.yaml,deployment.yaml
147147
```
148148

149+
* Label the default namespace to enable the webhook
150+
151+
```sh
152+
$ kubectl label namespaces default admission-webhook-example=enabled
153+
```
154+
149155
### 5. Build and Deploy OpenFaaS Function (Optional)
150156

151157
* Pull the [golang-middleware](https://github.com/openfaas-incubator/golang-http-template) template from [OpenFaaS Official Template Store](https://github.com/openfaas/store)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
---
2+
title: "Kubernetes Webhooks made easy with OpenFaaS - Part 2"
3+
description: "In this post you'll learn how to write Kubernetes Admission webhooks using OpenFaaS functions - Part 2"
4+
date: 2020-11-2
5+
image: /images/2020-10-27-k8s-validatingwebhook-openfaas/puzzle.jpg
6+
categories:
7+
- arkade
8+
- kubectl
9+
- faas-cli
10+
- admissionwebhooks
11+
- mutatingadmissionwebhooks
12+
- k8s extensibility
13+
author_staff_member: developer-guy
14+
dark_background: true
15+
---
16+
17+
In this post you'll learn how to write Kubernetes Admission webhooks using OpenFaaS functions - Part 2
18+
19+
<p align="center">
20+
<img height="128" src="/images/openfaas/kubernetes.png">
21+
</p>
22+
23+
## Introduction to Kubernetes Mutating Admission webhooks
24+
In the previous [part](https://www.openfaas.com/blog/kubernetes-webhooks-made-easy-with-openfaas/), we talked about what Kubernetes Admission Webhooks are and how can we use Validating Admission Webhook.
25+
26+
Today we are gonna talk about Mutating Admission Webhook and demonstrate how can we use it as OpenFaaS Function.
27+
28+
The main difference between the two types of admission webhook are pretty self-explanatory: validating webhooks can reject a request, but they cannot modify the object they are receiving in the admission request, while mutating webhooks can modify objects by creating a patch that will be sent back in the admission response and can reject a request too. If a webhook rejects a request, an error is returned to the end-user.
29+
30+
Also, the other difference between two types are validating webhooks are called in parallel and mutating webhooks are called in-sequence by the api-server.
31+
32+
## The Scenario
33+
This time we will inject a file to the container filesystem using [configMap volume](https://kubernetes.io/docs/concepts/storage/volumes/#configmap) automatically by the Mutating Admission Webhook.
34+
35+
In order to do that, we need to create a file that will inject by the Mutating Admission Webhook to the container's filesystem like below:
36+
37+
```sh
38+
$ cat functions/fileinjector/hello-openfaas.txt
39+
_ _ _ _ ___ ___ ___
40+
| || |___| | |___ / _ \ _ __ ___ _ _ | __|_ _ __ _/ __|
41+
| __ / -_) | / _ \ | (_) | '_ \/ -_) ' \| _/ _` / _` \__ \
42+
|_||_\___|_|_\___/ \___/| .__/\___|_||_|_|\__,_\__,_|___/
43+
|_|
44+
```
45+
46+
There is one important thing we need to say about Mutating Admission webhook is that:
47+
48+
> In a mutating admission controller webhook, mutations are performed via JSON patches. While the JSON patch standard includes a lot of intricacies that go well beyond the scope of this discussion, the Go data structure in our example as well as its usage should give the user a good initial overview of how JSON patches work:
49+
50+
```golang
51+
type patchOperation struct {
52+
Op string `json:"op"`
53+
Path string `json:"path"`
54+
Value interface{} `json:"value,omitempty"`
55+
}
56+
```
57+
58+
For setting the field .spec.securityContext.runAsNonRoot of a pod to true, we construct the following patchOperation object:
59+
60+
```golang
61+
patches = append(patches, patchOperation{
62+
Op: "add",
63+
Path: "/spec/securityContext/runAsNonRoot",
64+
Value: true,
65+
})
66+
```
67+
68+
Reminder, we will use the same workflow defined in previous post like below:
69+
70+
* Kubernetes API -> Webhook (w/TLS) -> OpenFaaS Gateway (w/HTTP) -> OpenFaaS Function
71+
72+
![Workflow](/images/2020-10-27-k8s-validatingwebhook-openfaas/admission-controller-phases.png)
73+
> Credit: [https://kubernetes.io/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/](https://kubernetes.io/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/)
74+
75+
### Prerequisites
76+
##### Arkade
77+
78+
* [arkade](https://get-arkade.dev) is The OpenFaaS community built tool for Kubernetes developers, with arkade you can easily install all necessary cli tools to your host and deploy apps to the cluster.
79+
80+
```sh
81+
$ curl -sLS https://dl.get-arkade.dev | sudo sh
82+
```
83+
84+
##### KinD (Kubernetes in Docker)
85+
86+
* Kubernetes is our recommendation for teams running at scale, but in this demo we will be using [KinD](https://kind.sigs.k8s.io/docs/user/quick-start/) for the sake of simplicity.
87+
88+
```sh
89+
$ arkade get kind
90+
```
91+
92+
##### kubectl
93+
94+
* You can control your cluster using [kubectl](https://github.com/kubernetes/kubectl) CLI.
95+
96+
```sh
97+
$ arkade get kubectl
98+
```
99+
100+
##### faas-cli
101+
102+
* [faas-cli](https://github.com/openfaas/faas-cli) is an official CLI for OpenFaaS , with "faas-cli" you can build and deploy functions easily.
103+
104+
```sh
105+
$ arkade get faas-cli
106+
```
107+
108+
### Setup
109+
110+
### 1. Setup a Kubernetes Cluster with KinD
111+
112+
You can start a Kubernetes cluster with KinD if you don't have one already
113+
114+
```bash
115+
$ arkade get kind
116+
$ kind create cluster
117+
```
118+
119+
### 2. Deploy OpenFaaS to our local Kubernetes Cluster with arkade:
120+
121+
* Install a OpenFaaS
122+
123+
```sh
124+
$ arkade install openfaas
125+
```
126+
127+
Read the output from the installation and run the commands given to you.
128+
129+
You can access them again at any time with `arkade info openfaas`
130+
131+
### 3. Clone the project
132+
133+
* Clone the sample from GitHub
134+
135+
```sh
136+
$ git clone https://github.com/developer-guy/admission-webhook-example-with-openfaas
137+
$ cd admission-webhook-example-with-openfaas
138+
$ git checkout feature/mutating
139+
```
140+
141+
* Let's explore the structure of the project.
142+
143+
```
144+
deployment/ --> includes necessary manifests and scripts for the deployment of the project
145+
functions/ --> includes templates and the requiredlabel function itself
146+
Dockerfile --> includes instructions to build an image of the project
147+
build --> automated way to build and push an image of the project
148+
```
149+
150+
### 4. Deploy MutatingAdmissionWebhook
151+
152+
* We will generate the TLS certificates required for the ValidatingAdmissionWebhook using the following: [Kubernetes TLS Certificates Management](https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/)
153+
154+
```sh
155+
$ cd deployment
156+
$ sh webhook-create-signed-cert.sh
157+
```
158+
159+
* Get the Certificate Authority (CA) from the local cluster
160+
161+
```sh
162+
$ export CA_BUNDLE=$(kubectl config view --minify --flatten -o json | jq -r '.clusters[] | select(.name == "'$(kubectl config current-context)'") | .cluster."certificate-authority-data"')
163+
$ sed -e "s|\${CA_BUNDLE}|${CA_BUNDLE}|g" mutatingwebhook.yaml | kubectl apply -f -
164+
$ cd ..
165+
```
166+
167+
* Build the project
168+
169+
```sh
170+
$ export DOCKER_USER="docker-hub-username"
171+
$ ./build
172+
```
173+
174+
Now edit `deployment.yaml` and set 'DOCKER_USER' to the above.
175+
176+
* Deploy it project
177+
178+
```sh
179+
$ cd deployment
180+
$ kubectl apply -f rbac.yaml,service.yaml,deployment.yaml
181+
# Label the default namespace to enable the webhook
182+
$ kubectl label namespaces default admission-webhook-example=enabled
183+
```
184+
185+
* This time we are using "fileinjector" as a FUNCTION_NAME environment variable in the deployment.yaml file
186+
187+
```yaml
188+
env:
189+
- name: FUNCTION_NAME
190+
value: fileinjector
191+
```
192+
193+
### 5. Build and Deploy OpenFaaS Function (Optional)
194+
195+
* Pull the [golang-middleware](https://github.com/openfaas-incubator/golang-http-template) template from [OpenFaaS Official Template Store](https://github.com/openfaas/store)
196+
197+
```sh
198+
$ faas-cli template store list # check available templates in store
199+
$ faas-cli template store describe golang-middleware # describe the specific template
200+
$ faas-cli template store pull golang-middleware
201+
```
202+
203+
* Create the function
204+
205+
```sh
206+
$ export OPENFAAS_PREFIX=$DOCKER_USER
207+
$ faas-cli new fileinjector --lang go-middleware
208+
$ cd fileinjector
209+
$ go mod init fileinjector
210+
$ # fill the handler.go with the corresponding code: [functions/fileinjector/handler.go](https://github.com/developer-guy/admission-webhook-example-with-openfaas/blob/feature/mutating/functions/fileinjector/handler.go)
211+
$ go get
212+
```
213+
214+
* Deploy the function
215+
216+
```sh
217+
$ cd functions
218+
$ faas-cli up -f fileinjector.yml --build-arg GO111MODULE=on # (build-push-deploy) make sure you are using your docker hub username. i.e: devopps
219+
```
220+
221+
* Verify the functions that are working in `openfaas-fn` namespace
222+
223+
```sh
224+
$ kubectl get pods --namespace openfaas-fn
225+
```
226+
227+
### 6. Testing the whole workflow
228+
* The purpose of this PoC is that to add a simple volume which is type configMap and volumeMount which is mounted to that volume to the pod automatically by our Mutating Admission Webhook.
229+
230+
* First, we need to create a ConfigMap to be able to mount a file to the Pod:
231+
232+
```sh
233+
$ cat functions/fileinjector/hello-openfaas.txt
234+
235+
_ _ _ _ ___ ___ ___
236+
| || |___| | |___ / _ \ _ __ ___ _ _ | __|_ _ __ _/ __|
237+
| __ / -_) | / _ \ | (_) | '_ \/ -_) ' \| _/ _` / _` \__ \
238+
|_||_\___|_|_\___/ \___/| .__/\___|_||_|_|\__,_\__,_|___/
239+
|_|
240+
```
241+
242+
```
243+
$ kubectl create hello-configmap --from-file=functions/fileinjector/hello-openfaas.txt
244+
```
245+
246+
* Now , you can apply the Pod manifest, once you done, you will notice that Pod includes a volume + volumeMount additional to the manifest you wrote in the beginning
247+
248+
```sh
249+
$ kubectl apply -f busybox.yaml
250+
```
251+
252+
* Check the logs of the Pod, you will see "Hello OpenFaaS" text as the output of the container.
253+
254+
```sh
255+
$ kubectl logs -f busybox
256+
257+
_ _ _ _ ___ ___ ___
258+
| || |___| | |___ / _ \ _ __ ___ _ _ | __|_ _ __ _/ __|
259+
| __ / -_) | / _ \ | (_) | '_ \/ -_) ' \| _/ _` / _` \__ \
260+
|_||_\___|_|_\___/ \___/| .__/\___|_||_|_|\__,_\__,_|___/
261+
|_|
262+
```
263+
264+
### Join the community
265+
266+
Have you got questions, comments, or suggestions? Join the community on [Slack](https://slack.openfaas.io).
267+
268+
Would you like help to set up your OpenFaaS installation, or someone to call when things don't quite go to plan? [Our Premium Subscription plan](https://www.openfaas.com/support/) gives you a say in the project roadmap, a support contact, and access to Enterprise-grade authentication with OIDC.
269+
270+
### Acknowledgements
271+
272+
* Special Thanks to [Alex Ellis](https://twitter.com/alexellisuk) for all guidance and for merging changes into OpenFaaS to better support this workflow.
273+
* Special Thanks to [Furkan Türkal](https://twitter.com/furkanturkaI) for all the support.
274+
275+
### References
276+
* [https://banzaicloud.com/blog/k8s-admission-webhooks](https://banzaicloud.com/blog/k8s-admission-webhooks)
277+
* [https://kubernetes.io/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/](https://kubernetes.io/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/)
278+
* [https://medium.com/ibm-cloud/diving-into-kubernetes-mutatingadmissionwebhook-6ef3c5695f74](https://medium.com/ibm-cloud/diving-into-kubernetes-mutatingadmissionwebhook-6ef3c5695f74)
279+
* [https://blog.alexellis.io/get-started-with-openfaas-and-kind/](https://blog.alexellis.io/get-started-with-openfaas-and-kind/)
280+
* [https://github.com/morvencao/kube-mutating-webhook-tutorial](https://github.com/morvencao/kube-mutating-webhook-tutorial)
281+
* [https://github.com/developer-guy/admission-webhook-example-with-openfaas](https://github.com/developer-guy/admission-webhook-example-with-openfaas)

0 commit comments

Comments
 (0)