简介
Kubernetes 的 apiserver 一开始就有 AdmissionController 的设计,这个设计和各类 Web 框架中的 Filter 很像,就是一个插件化的责任链,责任链中的每个插件针对 apiserver 收到的请求做一些操作或校验。分类
- ValidatingWebhookConfiguration,校验 api 对象的
- MutatingWebhookConfiguration,操作 api 对象的
apiserver 就能保证在校验(Validating)之前先做完所有的修改(Mutating)
配置apiserver 发起webhook
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"
rules 控制apiserver 何时 因为何种资源 发出请求:上例中 匹配针对 apps/v1
和 apps/v1beta1
组中 deployments 和 replicasets 资源的 CREATE 或 UPDATE 请求
clientConfig 描述如何调用webhook
- url 方式
```yaml
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
…
webhooks:
- name: my-webhook.example.com clientConfig: url: “https://my-webhook.example.com:9443/my-webhook-path” ```
- service 方式
```yaml
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
…
webhooks:
- name: my-webhook.example.com 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 ```
请求响应参数
type AdmissionReview struct {
metav1.TypeMeta `json:",inline"`
// Request describes the attributes for the admission request.
// +optional
Request *AdmissionRequest `json:"request,omitempty" protobuf:"bytes,1,opt,name=request"`
// Response describes the attributes for the admission response.
// +optional
Response *AdmissionResponse `json:"response,omitempty" protobuf:"bytes,2,opt,name=response"`
}
- 向 Webhook 发送 POST 请求时,请设置 Content-Type: application/json 并对 admission.k8s.io API 组中的 AdmissionReview 对象进行序列化,将所得到的 JSON 作为请求的主体。
-
Webhook 使用 HTTP 200 状态码、Content-Type: application/json 和一个包含 AdmissionReview 对象的 JSON 序列化格式来发送响应。该 AdmissionReview 对象与发送的版本相同,且其中包含的 response 字段已被有效填充。response 至少必须包含以下字段:
- uid,从发送到 webhook 的 request.uid 中复制而来
- allowed,设置为 true 或 false
Webhook 禁止请求的最简单响应示例:
{
"apiVersion": "admission.k8s.io/v1",
"kind": "AdmissionReview",
"response": {
"uid": "<value from request.uid>",
"allowed": false
}
}
当允许请求时,mutating admission webhook 也可以选择修改传入的对象。 这是通过在响应中使用 patch 和 patchType 字段来完成的。 当前唯一支持的 patchType 是 JSONPatch。 对于 patchType: JSONPatch,patch 字段包含一个以 base64 编码的 JSON patch 操作数组。例如,设置 spec.replicas
的单个补丁操作将是 [{"op": "add", "path": "/spec/replicas", "value": 3}]
。
{
"apiVersion": "admission.k8s.io/v1",
"kind": "AdmissionReview",
"response": {
"uid": "<value from request.uid>",
"allowed": true,
"patchType": "JSONPatch",
"patch": "W3sib3AiOiAiYWRkIiwgInBhdGgiOiAiL3NwZWMvcmVwbGljYXMiLCAidmFsdWUiOiAzfV0="
}
}
ValidatingWebhookConfiguration 妙用
Kubernetes 中如何保证优雅地停止 Pod利用 ValidatingAdmissionWebhook,在重要的 Pod 收到删除请求时,先在 webhook server 上请求集群进行下线前的清理和准备工作,并直接返回拒绝。这时候重点来了,Control Loop 为了达到目标状态(比如说升级到新版本),会不断地进行 reconcile,尝试删除 Pod,而我们的 webhook 则会不断拒绝,除非集群已经完成了所有的清理和准备工作。