Admission Controllers
准入控制器是一段代码,会在请求通过认证和授权之后、对象被持久化之前拦截到达 kube-apiserver 的请求。
准入控制器可以执行 Validating 和 Mutating 操作。准入控制器限制创建、删除、修改对象的请求,也可以阻止自定义 verbs,如通过 api 代理服务器连接到 Pod 的请求。准入控制器不能阻止 get、watch 或 list 对象的请求。
有 2 个特殊的准入控制器:MutatingAdmissionController 和 ValidatingAdmissionController,分别执行变更和验证准入控制 Webhook。
准入控制阶段
- 运行 MutatingAdmissionControl
- 运行 ValidatingAdmissionControl
某些 AdmissionController 即是 MutatingAdmissionController,又是 ValidatingAdmissionController。
如果某个请求在 2 个阶段的其中一个被拒绝,则整个请求立即被拒绝,并返回错误。
准入控制器有其他副作用,将相关资源作为请求处理的一部分进行变更。如增加资源配额。任何一个准入控制器都无法确定其他准入控制器的需求,只有当请求符合所有的准入控制器的要求,才会被 kube-apiserver 正确处理。
启用准入控制器
kube-apiserver --enable-admission-plugins=NamespaceLifeCycle,LimitRanger ...
关闭准入控制器
kube-apiserver --disable-admission-plugins=PodNodeSelector,AlwaysDeny ...
默认启用的准入控制器
- CertificateApproval
- CertificateSigning
- CertificateSubjectRestriction
- DefaultIngressClass
- DefaultTolerationSeconds
- LimitRanger
- MutatingAdmissionWebhook
- NamespaceLifeCycle
- PersistentVolumeClaimResize
- PodSecurity
- Priority
- ResourceQuota
- ServiceAccount
- StorageObjectInUseProtection
- TaintNodesByCondition
- ValidatingAdmissionPolicy
- ValidatingAdmissionWebhook
每个准入控制器的作用
- LimitRanger: 监测传入的请求,确保不会违反 Namespace 中 LimitRange 对象所设置的任何约束;还可以用于将默认资源配额应用到没有设定资源配额的 Pod
- NamespaceLifeCycle:会禁止在一个正在被删除的 Namespace 中创建新对象,并确保针对不存在的 Namespace 的请求被拒绝;会禁止删除系统中的保留命名空间:default,kube-system,kube-public
动态准入控制器
除了编译到 kube-apiserver 中的准入控制器,还支持在运行时动态使用的准入控制器。
准入 Webhook
是一种用于接受准入请求并对其进行处理的 HTTP 回调机制。可以定义 2 种类型的准入 Webhook:ValidatingAdmissionWebhook,MutatingAdmissionWebhook。其中 Mutating 性质的 Webhook 被先调用,然后执行 Validating 的 Webhook。
用户可以实现自己的准入 Webhook 动态加入到 kube-apiserver 的准入控制中。自定义准入 webhook
监控准入 Webhook
- 哪个变更性质的 Webhook 改变了 API 请求中的对象
- 变更性质的 Webhook 对对象做了那些修改
- 哪些 Webhook 经常拒绝 API 请求,什么原因拒绝等等
指标信息示例
# HELP apiserver_admission_webhook_rejection_count [ALPHA] Admission webhook rejection count, identified by name and broken out for each admission type (validating or admit) and operation. Additional labels specify an error type (calling_webhook_error or apiserver_internal_error if an error occurred; no_error otherwise) and optionally a non-zero rejection code if the webhook rejects the request with an HTTP status code (honored by the apiserver when the code is greater or equal to 400). Codes greater than 600 are truncated to 600, to keep the metrics cardinality bounded.
# TYPE apiserver_admission_webhook_rejection_count counter
apiserver_admission_webhook_rejection_count{error_type="calling_webhook_error",name="always-timeout-webhook.example.com",operation="CREATE",rejection_code="0",type="validating"} 1
apiserver_admission_webhook_rejection_count{error_type="calling_webhook_error",name="invalid-admission-response-webhook.example.com",operation="CREATE",rejection_code="0",type="validating"} 1
apiserver_admission_webhook_rejection_count{error_type="no_error",name="deny-unwanted-configmap-data.example.com",operation="CREATE",rejection_code="400",type="validating"} 13
自定义准入 Webhook 最佳实践与警告
- 幂等性:变更性质的准入 webhook 多次执行都会与初次执行产生相同的结果。
- 拦截对象的所有版本:
.webhook[].matchPolicy = Equivalent
匹配请求:matchPolicy - 可用性
- 确保看到对象的最终状态
- 避免自定义的 Webhook 出现死锁
- 应尽可能避免副作用
- 避免对 kube-system 命名空间进行操作