准入控制器是在对象持久化之前用于对 Kubernetes API Server 的请求进行拦截的代码段,在请求经过身份验证和授权之后放行通过。准入控制器可能正在 validating、mutating 或者都在执行,Mutating 控制器可以修改他们处理的资源对象,Validating 控制器不会,如果任何一个阶段中的任何控制器拒绝了请求,则会立即拒绝整个请求,并将错误返回给最终的用户。
时序图如下所示:
如果我们想为 CRD 实现 admission webhook,我们唯一要做的就是实现 Defaulter
和 (或) Validator
接口。
Kubebuilder 会我们处理剩余的工作:
创建 webhook 服务器
确保服务器已添加到管理器中
为 webhook 创建处理程序
使用服务器中的路径注册每个处理程序
这里我们直接在 手摸手教你使用 kubebuilder 开发 operator [1] 中实战的 app-operator 项目上来扩展功能。
这里我们扩展两个功能:
1、假设用户的 CR 中没有设置总 QPS,我们可以通过 webhook 来设置一个默认值,比如 1300;
2、为了保护系统,给单个 Pod 的 QPS 设置上限,比如 1000,如果用户的 CR 中 singlePodsQPS 的值超过 1000,webhook 进行拦截,创建资源对象失败。
和 controller 类似,webhook 既可以在 kubernetes 环境中运行,也可以在 kubernetes 环境外运行,如果 webhook 在 kuberneetes 环境之外运行,需要将证书放在所在的环境中,默认路径:
/tmp/k8s-webhook-server/serving-certs/tls.{crt,key}
这里选择是将 webhook 部署在 kubernetes 环境中,使用 cert-manager [2]
来管理证书。
直接使用下面命令安装 cert-manager 组件即可:
$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml
命令执行成功后,会自动创建 cert-manager 命名空间,以及 rbac、pod、service 等资源:
- $ kubectl get all -n cert-manager
- NAME READY STATUS RESTARTS AGE
- pod/cert-manager-6544c44c6b-gf6nk 1/1 Running 0 20h
- pod/cert-manager-cainjector-5687864d5f-22dzw 1/1 Running 0 20h
- pod/cert-manager-webhook-785bb86798-nh2gc 1/1 Running 0 20h
-
- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
- service/cert-manager ClusterIP 10.109.226.106 <none> 9402/TCP 20h
- service/cert-manager-webhook ClusterIP 10.106.116.190 <none> 443/TCP 20h
-
- NAME READY UP-TO-DATE AVAILABLE AGE
- deployment.apps/cert-manager 1/1 1 1 20h
- deployment.apps/cert-manager-cainjector 1/1 1 1 20h
- deployment.apps/cert-manager-webhook 1/1 1 1 20h
-
- NAME DESIRED CURRENT READY AGE
- replicaset.apps/cert-manager-6544c44c6b 1 1 1 20h
- replicaset.apps/cert-manager-cainjector-5687