Kubernetes 1.9 |可扩展准入机制进入 Beta 阶段
翻译:夏天
校对:唐鹏程
今天,我们来好好聊一下 Kubernetes API server 中准入机制,它可以帮助用户实现任意的准入控制决策,这一功能在 Kubernetes 1.9 中已经相当成熟。
API server 的准入机制是功能最强大的工具之一,它通过限制可以创建的对象,来保护 Kubernetes 集群,但它却是一直是与 Kubernetes 源码一起编译的。在 Kubernetes 1.9 中,Admission Webhook 升级为 beta 版,允许用户在 API server 之外使用准入机制。
准入机制是什么?
准入阶段由不同的插件组成,每个插件都能 “各司其职”,并明确知道自己要检查的对象结构。例如:PodNodeSelector(影响调度决策),PodSecurityPolicy(防止升级的容器)和 ResourceQuota(为每个 Namespace 限制资源配额)。
准入分为两个阶段:
修改 (Mutation) 阶段:允许修改对象的主体内容以及拒绝 API 请求
验证 (Validation) 阶段:允许内省查询以及拒绝 API 请求
一个准入插件可以在这两个阶段应用,但是所有的修改阶段都发生在验证阶段之前。
修改 (Mutation)阶段
Admission 的 Mutation 阶段允许在资源内容生成前进行修改。因为同一个字段在 Admission 链上可以被多次修改,因此 Admission 插件的执行顺序很重要。准入修改插件(Mutating Admission Plugin)中的一个例子就是 PodNodeSelector。
它使用 Namespace 的一个 annotation:
来查找标签选择器并将其添加到 pod.spec.nodeselector 字段。这一功能正向限制了特定 Namespace 中的 pod 能够落在哪个节点上,这与提供反向限制的 taints 正相反(也是通过 Admission 插件来实现的)。
验证 (Validating)阶段
我们可以在 Admisson 的验证阶段来检查特定 API 资源以保证其不变。验证阶段在所有的 mutators 完成之后运行,以确保资源在做完验证之后不会被再次改变。
准入验证插件(Validation Admission Plugin)的一个例子也是 PodNodeSelector 插件,它可以确保所有 pod 的 spec.nodeSelector 字段都能符合 Namespace 上节点选择器的约束。即使在 Mutating 链中运行 PodNodeSelector 之后,有其他修改插件试图更改 spec.nodeSelector 字段,验证链中的 PodNodeSelector 插件也会因验证失败而阻止 API 资源的创建。
Admission Webhook 是什么?
Admission Webhook 允许 Kubernetes 安装人员或集群管理员,不需要进行重新编译,就可以直接添加修改(Mutation)和验证(Validation)这两种插件到 kube-apiserver 和任何基于 k8s.io/apiserver 1.9 扩展的 apiserver (如 metrics, service-catalog, kube-projects 等) 准入链中。这两种 Admission Webhook 插件分别会在修改和验证链的最后执行,与编译的准入插件具有相同的功能。
Webhook Admission 插件的优势
Webhook Admission 插件允许对任何 API server 的任何资源进行修改和验证,所以应用场景非常广泛,比较常见的用例包括:
修改如 pod 这样的资源:Istio 通过修改 pod 资源,把 side-car 容器注入到 pod 中。你也可以编写一个能够强制将镜像 tag 解析成 SHA 的插件;
命名限制:在多租户系统上,保留 Namespace 已经成为一种用例 ;
复杂的 CustomResource 验证:因为整个对象是可见的,所以插件可以对字段间依赖(A 需要 B)甚至外部资源(对比 LimitRanges)进行复杂的验证;
安全响应:如果你把镜像 tag 改成了 SHA,你可以通过写一个插件来阻止对应某些 SHA 的镜像运行。
注册
这两种类型的 Webhook Admission 插件都需要在 API 中注册,所有 API servers(kube-apiserver 和所有扩展 API servers )都共享一个通用配置。在注册过程中,一个 Webhook Admission 插件描述了以下信息:
如何连接到 Webhook Admission Server;
如何验证 Webhook Admission Server(是否是我们期望的 server);
数据应该发送到 Server 的哪个 URL 路径;
它将处理哪些资源和哪些 HTTP 动词;
API server 在连接失败后应该做什么(例如如果 Webhook Admission Server 停止服务了)。
第 6 行 name:Webhook 的名称。mutating Webhooks 会根据名称进行排序。
第 7 行 clientConfig:提供关于如何连接、信任以及发送数据给 Webhook Admission Server 的信息。
第 13 行 rules:用来描述 API server 应该在什么时候调用 Admission 插件。在这个例子中,只有创建 Namespace 的时候才触发。你可以指定任何资源,例如serviceinstances.servicecatalog.k8s.io 的 create 操作也是可行的。
第 22 行 failurePolicy:如果 Webhook Admission Server 无法连接时如何处理。有两个选项分别是 “Ignore”(故障时开放) 和 “Fail”(故障时关闭)。“故障时开放”可能会导致无法预测的行为。
认证和信任
由于 Webhook Admission 插件具有强大的功能(他们可以查看 API 资源内容中任何发给他们的请求,并可以通过插件进行修改),所以在使用时需要考虑的重点是:
各个 API servers 如何验证其与 Webhook Admission Server 的连接;
Webhook Admission Server 如何准确地认证哪个 API server 正在与它连接;
该特定的 API server 是否有权进行请求。
连接可以分为以下三大类:
从 kube-apiserver 或 extension-apiservers 到运行在集群外部的 Admission Webhooks;
从 kube-apiserver 到运行在集群内部的 Admission Webhooks;
从 extension-apiservers 到运行在集群内部的 Admission Webhooks。
为了支持这三大类连接,Webhook Admission 插件可以支持从 kubeconfig 文件中读取连接各个 server 的信息。由于认证/授权和访问路径是由用户所连接的服务器所决定的,因此为了与运行在集群外部的 Admission Webhooks 进行交互,除了手动配置这个文件之外,实际上没有其他选择。
对于在集群内运行的 Admission Webhook 来说,一个巧妙构建的 Webhook Admission Server 和拓扑结构,就是能够利用 Admission 插件中内置的安全默认值,并具有可从任何 API server 运行的安全、可移植和零配置的拓扑结构。
简单安全,可移植的拓扑结构
你的 Webhook 在默认 kube-apiserver 服务 “kubernetes.default.svc” 下变得可用 https://kubernetes.default.svc/apis/admission.example.com/v1/mymutatingadmissionreviews。另一个好处是,你可以使用 kubectl 进行测试。
你的 Webhook 会自动(无需任何配置)使用 kube-apiserver 提供的集群内认证和授权。你可以使用正常的 RBAC 规则限制对 Webhook 的访问。
你的 extension API servers 和 kube-apiserver (无需任何配置)可以自动利用其集群内的凭证与 Webhook 进行通信。
因为中间会经过 kube-apiserver 这个安全的前端代理,所以 extension API servers 不会将其 service account token 泄漏给 Webhook。
https://drive.google.com/a/redhat.com/file/d/12nC9S2fWCbeX_P8nrmL6NgOSIha4HDNp
简而言之:一个安全的拓扑结构可以使用 API server 聚合 (API server aggregation) 的所有安全机制,不需要额外的配置。其他的拓扑结构也是可行的,但是需要额外的手动配置以及创建安全设置工作。尤其是像 service catalog 这种 extension API servers,上面的拓扑结构就是零配置,并且可移植到任何 Kubernetes 集群中。
编写 Webhook Admission Server
编写一个具有完整的有完备身份验证和授权的 Server 是非常困难的事情。为了让这件事变得更容易,基于 Kubernetes 1.9 的不少项目都提供了相关的库,可以让使用者用 200 行甚至更少的代码来实现一个 Webhook Admission Server。可以参考 “generic-admission-apiserver” 和 “kubernetes-namespace-reservation” 这两个项目中提供的库,以及如何构建一个安全和可移植的 Webhook Admission Server 的示例。
原文参考:http://blog.kubernetes.io/2018/01/extensible-admission-is-beta.html
留言区已开放,欢迎互动
推荐阅读:
如何用 Kubernetes 管理超过 2500 个节点的集群