Kubernetes运维:Admission Controllers
文章目录
介绍 Kubernetes Admission Controllers
Admission Controllers
在介绍 Kubernetes 的 Admission Controllers 迁移,我们通过回顾一下 kube-apiserver 处理 request 的过程。
上图中每个 API Request 在被保存到 etcd 前,kube-apiserver 对它们进行了以下处理:
- API HTTP Handler
- Authentication/Authorization
- Mutating Admission
- Object Schema Validation
- Validating Admission
kube-apiserver 和其他 http server 一样在真正处理请求时,需要先运行一些代码中预先定义的 filter 函数,即上面图片中的 API HTTP Handler 过程。kube-apiserver 注册的 filter 在逻辑在 staging/src/k8s.io/apiserver/pkg/server/config.go 文件的 DefaultBuildHandlerChain 函数中实现。filter 函数主要定义在 k8s.io/apiserver/pkg/server/filters 包。
从 DefaultBuildHandlerChain 的代码中可以看出,该函数注册了 WithAuthorization 和 WithAuthentication 函数,这两个函数会分别通过 Authorizer 接口和 AuthenticateRequest 接口分别进行鉴权和认证。
请求通过处理链后 kube-apiserver 真正处理逻辑就开始了,"/",“version”,“apis”,“/healthz” 等特殊 URL 的请求将被 router 到特定的函数进行处理,而针对资源类(如 pod 等)请求将进入后续的 Mutating Admission、Object Schema Validation、Validating Admission 阶段进行处理,最后保存到 etcd 中。
上述流程中,完成 Mutating Admission 和 Validating Admission 阶段的代码逻辑在 Kubernetes 中称为 Admission Controllers ,按照其功能可以大致分为两类:
- Mutating Admission:修改请求的对象
- Validating Admission:验证请求的对象
Admission Controllers 可能属于 Mutating Admission 或者 Validating Admission 中的一种又或者同时属于这两种类型。
kube-apiserver 处理 request 的请求并非完全如上图一样,step by step 按照顺序执行。该图来自 kubernetes blogs 仅描述了 kube-apiserver 工作的大体流程。
目前 Kubernetes 中定义了大量 Admission Controllers,代码在 kubernetes 项目的 plugin/pkg/admission 目录下。
用户可以通过参数 –enable-admission-plugins 和 –disable-admission-plugins 开启或者禁用特定的 Admission Controllers。 通过执行以下命令可以快速查看,默认开启的 Admission Controllers:
|
|
官方文档花了很大篇幅介绍每个 Admission Controllers 的作用,有兴趣的读者可以直接阅读相关章节(what does each admission controller do)。
Dynamic Admission Control
Kubernetes 提供了两个特殊准入控制器 ValidatingAdmissionWebhook 和 MutatingAdmissionWebhook。它们提供了一种基于 HTTP 回调的机制,使用户可以在 kube-apiserver 处理流程中实现对资源的修改和校验。通常我们将 ValidatingAdmissionWebhook 和 MutatingAdmissionWebhook 提供的能力称为“动态准入”。
ValidatingAdmissionWebhook 和 MutatingAdmissionWebhook 的代码逻辑定义在 staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook 包中,用户启用它们之前需要确保 kube-apiserver 开启了相关插件,并且启用了 admissionregistration.k8s.io/v1 API。
WebHook Server
Dynamic Admission Control 基于 web hook 工作,用户需要实现一个 Admission Webhook Server。Server 用于处理由 kube-apiserver 发送的 AdmissionReview 请求,并将处理结果发回 kube-apiserver。
Kubernetes 官方给出了以下两个 WebHook Server 的 demo:
依赖 kubernetes-sigs/controller-runtime 包提供的接口,我们可以非常快速的开发 Webhook Server。用于只需要将实现 kubernetes-sigs/controller-runtime 中定义的 Handler 接口并将它注册到对应的 url 中即可。
|
|
通常情况下,我们将 Webhook Server 部署在 kubernetes 集群中并且创建对应的 Service ,kube-apiserver 通过 ClusterIP 访问他们,但需要注意的是我们需要在一定程度上保证 Webhook Server 的高可用。
证书配置
kube-apiserver 和 Webhook Server 基于 HTTPS 通讯,因此双方需要配置相关证书。
当 Webhook Server 基于 [kubernetes-sigs/controller-runtime] 开发时,我们可以指定一个 serving-certs 目录,目录中包含证书文件 tls.crt 和 tls.key。
需要注意的是:服务端证书文件中的 SAN 配置需要和 kube-apiserver 访问 Webhook Server 使用的地址匹配,通常在 kubernetes 集群中部署 Webhook Server 并通过 Service 访问时,需要将ClusterIP 或者 Service Name 添加到证书的 SAN 中。
需要注意,当 kube-apiserver 使用 systemctl 部署在服务器上时,无法解析 Service Name
配置好 Webhook 的服务端证书后,需要通过 –admission-control-config-file 在 kube-apiserver 配置客户端证书,该配置指定了 ValidatingAdmissionWebhook 和 MutatingAdmissionWebhook 访问服务端时使用的客户端证书,内容如下:
|
|
上述配置中,kubeConfigFile 指向证书文件,它的格式和 kubeconfig 的文件格式一致,可以基于证书、token 等多种方式实现认证:
|
|
webhooks 配置
ValidatingAdmissionWebhook 和 MutatingAdmissionWebhook 之所以被称为“动态准入控制”的原因是:用户可以在不重启 kube-apisever 的前提下(前提是你已经配置好了 HTTPS 的客户端证书),使自定义的 webhook 生效。这主要通过在 kubernetes 中配置 ValidatingWebhookConfiguration 或者 MutatingWebhookConfiguration 实现,不同配置决定了 webhook 起作用的位置不同,即 Validating 和 Mutating 的差别。
|
|
上述定义了一个为 Pod 注入 toleration 的 MutatingWebhook,其中最关键是:webhooks.clientConfig,它决定了 kube-apiserver 如何连接 Webhook Server 。用户可以通过 service 或 url 的方式定义 Webhook Server 的服务器地址、端口、CA 证书、以及 URL。
MutatingWebhookConfiguration 还决定了 kube-apiserver 调用 webhook 的事件类型,用户可以通过多种方式设置 kube-apiserver 什么情况下会调用 webhook:
- rules:这是最常用的方式,基于资源的 GVK 操作(CREATE、DELETE、UPDATE) 筛选事件。
- objectSelector:基于资源的 Labels 筛选事件。
- namespaceSelector:基于资源所处的 Namespace 进行筛选。
需要注意,由于升级引发资源的版本变化,如 Deployment 的版本从 extensions/v1beta1 变为 apps/v1 时,默认情况下用户只需要在 rules 中指定 apps/v1 版本即可,具体可以查看官方文档关于 Matching requests: matchPolicy 的描述。
配置 manifest 的字段说明可以参考以下地址:
其他内容
Side effects
kubernetes 在 1.13 版本提供了服务端 Dry-run 功能,当用户使用 kubectl apply 时可以添加 –dry-run=server 参数,当 kube-apiserver 处理这类请求时同样会访问 webhook 并执行完正常请求除持久化到 etcd 以外的所有流程。
对于一些调用 kubenretes client 修改其中资源的 Webhook 来说, dry-run=server 请求对 kubernetes 集群会产生某些副作用。
为了杜绝这些副作用,kubernetes 在 MutatingWebhookConfiguration 和 ValidatingWebhookConfiguration 中提供了 sideEffects 配置,该配置支持以下参数:
- None:明确声明该 Webhook 对集群不存在副作用
- NoneOnDryRun:该 Webhook 对集群存在副作用,当 Server 端能够从 AdmissionReview 的参数中判断请求是否是 dry-run 类型,并作出相应的逻辑处理。
- Some:该 Webhook 对集群存在副作用,此时 dry-run 类型的请求不会被发送到 Webhook Server,kube-apiserver 会直接拒绝请求。
- Unknown:作用同 Some ,默认值。
参考:https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#side-effects
幂等性
根据官方文档的描述,通过 reinvocationPolicy 配置我们可以触发 Webhook 的重新调用,以避免内置 Admission 覆盖 MutatingWebhook 的修改。 这种情况下,要注意的重要因素有:
- 不能保证重新调用 Webhook 的次数恰好是一。
- 如果重新调用 Webhook 导致对象的进一步修改,则不能保证再次调用 Webhook(进步修改意思是:Webhook Server 接受/返回的对象结构不一致)。
- Webhook 可能会重新排序,以最大程度地减少额外调用的次数。
为了满足上述要求,MutatingWebhook 的代码应该总能保证其“幂等性”。
参考:https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/extensible-admission-controllers/#reinvocation-policy
监控
参考:https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#monitoring-admission-webhooks
最佳实践
参考:https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#best-practices-and-warnings
参考
文章作者 yoaz
上次更新 2022-09-12
许可协议 MIT