admission webhook 本质上就是一个 HTTP 回调服务,在 k8s apiserver 开启了 MutatingAdmissionWebhook
或 ValidatingAdmissionWebhook
的情况下,apiserver 收到请求后会调用对应的回调,在回调验证通过后请求才会持久化到 etcd。
现在非常火热的的 Service Mesh 应用 istio 就是通过 mutating webhooks 来自动将 Envoy 这个 sidecar 容器注入到 Pod 中去的:https://istio.io/docs/setup/kubernetes/sidecar-injection/。
kube-apiserver 属于 static pod,因此之间修改 /etc/kubernetes/manifests/kube-apiserver.yaml
配置就行了:
apiVersion: v1
kind: Pod
metadata:
labels:
component: kube-apiserver
tier: control-plane
name: kube-apiserver-ydzs-master
namespace: kube-system
......
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=10.151.30.11
- --allow-privileged=true
- --authorization-mode=Node,RBAC
- --client-ca-file=/etc/kubernetes/pki/ca.crt
- --enable-admission-plugins=NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook
......
定义 adminssion webhook 资源时,可以指定请求的 Path,监听的资源类型和范围,可以通过这种方式只编写单个 webhook 服务,定义多个 webhook 资源,在不同的 Path 上处理不同类型的请求:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
...
webhooks:
- name: my-webhook.example.com
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["apps"]
apiVersions: ["v1", "v1beta1"]
resources: ["deployments", "replicasets"]
scope: "Namespaced"
clientConfig:
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle containing the CA that signed the webhook's serving certificate>...tLS0K"
service:
namespace: my-service-namespace
name: my-service-name
path: /my-path
port: 1234
mutating 类型的 webhook 响应应该使用 JSON Patch 来表示要修改的内容:
{
"apiVersion": "admission.k8s.io/v1",
"kind": "AdmissionReview",
"response": {
"uid": "<value from request.uid>",
"allowed": true,
"patchType": "JSONPatch",
"patch": "W3sib3AiOiAiYWRkIiwgInBhdGgiOiAiL3NwZWMvcmVwbGljYXMiLCAidmFsdWUiOiAzfV0="
}
}
通常 webhook 会使用 HTTPS 来通信,因此需要生成 CA 证书,可以使用 certificates.k8s.io
API 来签发受 k8s 信任的 x509 证书,当然也可以直接在定义 webhook 时指定 CA 证书。
签署可参考脚本:https://github.com/newrelic/k8s-webhook-cert-manager/blob/master/generate_certificate.sh