🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ### **背景简介** 前面我们学习了K8S的认证与授权机制,当客户端向APIserver发起API请示的时候,需要被认证与授权,这两个步骤通过,该请示才能正常返回。那为什么还要准入控制机制呢? 使用过服务网格Istio的同学都知道,当我们创建一个Pod时,K8S最终会往这个Pod中注入一个SideCar容器(也就是说,这个Pod的yaml文件被修改了,增加了一个Container)。那么问题来了,这个SideCar容器是如何被注入的呢(或者说,这个Pod的yaml文件是如何被修改的呢)? ### **什么是准入控制器** 首先,我们先看看 Kubernetes 官方文档中关于`准入控制器`的定义 > An admission controller is a piece of code that intercepts requests to the Kubernetes API server prior to persistence of the object, but after the request is authenticated and authorized. \[…\] Admission controllers may be “validating”, “mutating”, or both. Mutating controllers may modify the objects they admit; validating controllers may not. \[…\] If any of the controllers in either phase reject the request, the entire request is rejected immediately and an error is returned to the end-user. 大概意思就是说`准入控制器`是在对象持久化之前用于对 Kubernetes API Server 的请求进行拦截的代码段,在请求经过身份验证和授权之后放行通过。准入控制器可能正在`validating`、`mutating`或者都在执行,Mutating 控制器可以修改他们的处理的资源对象,Validating 控制器不会,如果任何一个阶段中的任何控制器拒绝了请求,则会立即拒绝整个请求,并将错误返回给最终的用户。 流程如下: ![](https://img.kancloud.cn/2f/c1/2fc108d002c6d68dca927500198a0d0c_1492x655.png) 当client发送一个创建Pod的请求给Apiserver,Apiserver检查自己的web-hook链是否有注册admission-controller,如果有则把这个请求转发给它。然后admission-controller会对Pod的Yaml进行处理(验证或修改),然后返回结果给Apiserver,Apiserver根据返回结果,判断是否需要将这个Pod对象持久化,最后Apiserver再返回结果给client。 ### **如何开启准入控制器** kube-apiserver提供了两个启动参数: ``` --enable-admission-plugins NamespaceLifecycle,LimitRanger,... --disable-admission-plugins xxx,xxx,... ``` 第一参数用来指定开启哪些控制器,第二个参数用来指定关闭哪些控制器。这个链接[https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#what-does-each-admission-controller-do](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#what-does-each-admission-controller-do)可以看到有哪些准入控制器。 ### **静态控制器与动态控制器** 静态控制器的代码内置在K8S当中的,比如ServiceAccount、LimitRanger等,它们的行为是定义好的。所以如果我们要定义自己的控制器行为,就得用到动态控制器。 在 Kubernetes apiserver 中包含两个特殊的准入控制器:`MutatingAdmissionWebhook`和`ValidatingAdmissionWebhook`。这两个控制器将发送准入请求到外部的 HTTP(HTTPS) 回调服务并接收一个准入响应。 总的来说,步骤如下: * 检查集群中是否启用了 admission webhook 控制器,并根据需要进行配置。 * 编写处理准入请求的 HTTP 回调,回调可以是一个部署在集群中的简单 HTTP 服务 * 通过`MutatingWebhookConfiguration`和`ValidatingWebhookConfiguration`资源配置 admission webhook 这两种类型的 admission webhook 之间的区别是非常明显的:validating webhooks 可以拒绝请求,但是它们却不能修改在准入请求中获取的对象,而 mutating webhooks 可以在返回准入响应之前通过创建补丁来修改对象,如果 webhook 拒绝了一个请求,则会向最终用户返回错误。 现在非常火热的的[Service Mesh](https://www.qikqiak.com/post/what-is-service-mesh/)应用`istio`就是通过 mutating webhooks 来自动将`Envoy`这个 sidecar 容器注入到 Pod 中去的:[https://istio.io/docs/setup/kubernetes/sidecar-injection/](https://istio.io/docs/setup/kubernetes/sidecar-injection/) ### **FAQ** ### **参考** * https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/ * https://kubernetes.io/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/ * https://www.qikqiak.com/post/k8s-admission-webhook/