Skip to content

Commit e773bb3

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

2 files changed

+297
-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,291 @@
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 injected 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+
```sh
130+
# Forward the gateway to your machine
131+
kubectl rollout status -n openfaas deploy/gateway
132+
kubectl port-forward -n openfaas svc/gateway 8080:8080 &
133+
134+
# If basic auth is enabled, you can now log into your gateway:
135+
PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)
136+
echo -n $PASSWORD | faas-cli login --username admin --password-stdin
137+
```
138+
139+
You can access them again at any time with `arkade info openfaas`
140+
141+
### 3. Clone the project
142+
143+
* Clone the sample from GitHub
144+
145+
```sh
146+
$ git clone https://github.com/developer-guy/admission-webhook-example-with-openfaas
147+
$ cd admission-webhook-example-with-openfaas
148+
$ git checkout feature/mutating
149+
```
150+
151+
* Let's explore the structure of the project.
152+
153+
```
154+
deployment/ --> includes necessary manifests and scripts for the deployment of the project
155+
functions/ --> includes templates and the requiredlabel function itself
156+
Dockerfile --> includes instructions to build an image of the project
157+
build --> automated way to build and push an image of the project
158+
```
159+
160+
### 4. Deploy MutatingAdmissionWebhook
161+
162+
* 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/)
163+
164+
```sh
165+
$ cd deployment
166+
$ sh webhook-create-signed-cert.sh
167+
```
168+
169+
* Get the Certificate Authority (CA) from the local cluster
170+
171+
```sh
172+
$ export CA_BUNDLE=$(kubectl config view --minify --flatten -o json | jq -r '.clusters[] | select(.name == "'$(kubectl config current-context)'") | .cluster."certificate-authority-data"')
173+
$ sed -e "s|\${CA_BUNDLE}|${CA_BUNDLE}|g" mutatingwebhook.yaml | kubectl apply -f -
174+
$ cd ..
175+
```
176+
177+
* Build the project
178+
179+
```sh
180+
$ export DOCKER_USER="docker-hub-username"
181+
$ ./build
182+
```
183+
184+
Now edit `deployment.yaml` and set 'DOCKER_USER' to the above.
185+
186+
* Deploy it project
187+
188+
```sh
189+
$ cd deployment
190+
$ kubectl apply -f rbac.yaml,service.yaml,deployment.yaml
191+
# Label the default namespace to enable the webhook
192+
$ kubectl label namespaces default admission-webhook-example=enabled
193+
```
194+
195+
* This time we are using "fileinjector" as a FUNCTION_NAME environment variable in the deployment.yaml file
196+
197+
```yaml
198+
env:
199+
- name: FUNCTION_NAME
200+
value: fileinjector
201+
```
202+
203+
### 5. Build and Deploy OpenFaaS Function (Optional)
204+
205+
* Pull the [golang-middleware](https://github.com/openfaas-incubator/golang-http-template) template from [OpenFaaS Official Template Store](https://github.com/openfaas/store)
206+
207+
```sh
208+
$ faas-cli template store list # check available templates in store
209+
$ faas-cli template store describe golang-middleware # describe the specific template
210+
$ faas-cli template store pull golang-middleware
211+
```
212+
213+
* Create the function
214+
215+
```sh
216+
$ export OPENFAAS_PREFIX=$DOCKER_USER
217+
$ faas-cli new fileinjector --lang go-middleware
218+
$ cd fileinjector
219+
$ go mod init fileinjector
220+
$ # 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)
221+
$ go get
222+
```
223+
224+
* Deploy the function
225+
226+
```sh
227+
$ cd functions
228+
$ 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
229+
```
230+
231+
* Verify the functions that are working in `openfaas-fn` namespace
232+
233+
```sh
234+
$ kubectl get pods --namespace openfaas-fn
235+
```
236+
237+
### 6. Testing the whole workflow
238+
* 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.
239+
240+
* First, we need to create a ConfigMap to be able to mount a file to the Pod:
241+
242+
```sh
243+
$ cat functions/fileinjector/hello-openfaas.txt
244+
245+
_ _ _ _ ___ ___ ___
246+
| || |___| | |___ / _ \ _ __ ___ _ _ | __|_ _ __ _/ __|
247+
| __ / -_) | / _ \ | (_) | '_ \/ -_) ' \| _/ _` / _` \__ \
248+
|_||_\___|_|_\___/ \___/| .__/\___|_||_|_|\__,_\__,_|___/
249+
|_|
250+
```
251+
252+
```
253+
$ kubectl create hello-configmap --from-file=functions/fileinjector/hello-openfaas.txt
254+
```
255+
256+
* 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
257+
258+
```sh
259+
$ kubectl apply -f busybox.yaml
260+
```
261+
262+
* Check the logs of the Pod, you will see "Hello OpenFaaS" text as the output of the container.
263+
264+
```sh
265+
$ kubectl logs -f busybox
266+
267+
_ _ _ _ ___ ___ ___
268+
| || |___| | |___ / _ \ _ __ ___ _ _ | __|_ _ __ _/ __|
269+
| __ / -_) | / _ \ | (_) | '_ \/ -_) ' \| _/ _` / _` \__ \
270+
|_||_\___|_|_\___/ \___/| .__/\___|_||_|_|\__,_\__,_|___/
271+
|_|
272+
```
273+
274+
### Join the community
275+
276+
Have you got questions, comments, or suggestions? Join the community on [Slack](https://slack.openfaas.io).
277+
278+
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.
279+
280+
### Acknowledgements
281+
282+
* Special Thanks to [Alex Ellis](https://twitter.com/alexellisuk) for all guidance and for merging changes into OpenFaaS to better support this workflow.
283+
* Special Thanks to [Furkan Türkal](https://twitter.com/furkanturkaI) for all the support.
284+
285+
### References
286+
* [https://banzaicloud.com/blog/k8s-admission-webhooks](https://banzaicloud.com/blog/k8s-admission-webhooks)
287+
* [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/)
288+
* [https://medium.com/ibm-cloud/diving-into-kubernetes-mutatingadmissionwebhook-6ef3c5695f74](https://medium.com/ibm-cloud/diving-into-kubernetes-mutatingadmissionwebhook-6ef3c5695f74)
289+
* [https://blog.alexellis.io/get-started-with-openfaas-and-kind/](https://blog.alexellis.io/get-started-with-openfaas-and-kind/)
290+
* [https://github.com/morvencao/kube-mutating-webhook-tutorial](https://github.com/morvencao/kube-mutating-webhook-tutorial)
291+
* [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)