Kubernetes API Server 中有一个功能,能让用户(对工作负载)进行决策,这一功能在 1.9 中已经走入成熟期。
Admission 是 Kubernetes 中最强大的工具之一,可以通过限制创建对象的方式来增强 Kubernetes 集群的安全性,这部分一直是编译在代码之中的。在 1.9 中,我们将 Admission 的 Webhook 升级成 Beta,让用户可以在 API Server 之外对 Admission 施加影响。
Admission 是什么?
Admission(注1),是在认证之后,资源持久化之前 的一个处理 API Server 请求的步骤。Admission 能获取到和认证过程一致的信息(用户、URL 等),以及绝大多数 API 请求的完整报文。
Admission 阶段由不同插件组成,每个 Admission 都会对一个侧面进行观察和操作。例如:影响调度决策的PodNodeSelector、阻止恶意容器的PodSecurityPolicy以及实现 Namespace 资源分配的ResourceQuota。
Admission 内部分为两个阶段:
Admission 插件可以在这两个阶段起作用,但是变更总是在验证之前。
Mutation
Admission 的变更功能可以在资源生成之前进行修改。在 Admission 链条上可以多次修改同一个字段,因此插件不是无序的。
PodNodeSelector就是一个例子,他使用 Namespace 的一个注解namespace.annotations[“scheduler.alpha.kubernetes.io/node-selector”],在其中查找标签选择器,并将其加入pod.spec.nodeselector字段。这一功能限制某个 Namespace 的 Pod,只能运行在指定节点上,同 Taint 的功能正好相反(也是 Admission 插件)。
验证
Admission 的验证阶段用来对特定 API 资源进行验证。这一阶段会在所有变更执行结束之后,API 资源不再发生变化的情况下进行。
PodNodeSelector插件同样演示了这一活动,他确保 Pod 的spec.nodeSelector字段符合该 Namespace 的限制。如果变更链上有其他 Admission 尝试在PodNodeSelector之后修改了资源的spec.nodeSelector,就会在验证阶段因为不符合限制而被拒绝创建。
Admission Webhook 是什么?
Admission webhook 允许 Kubernetes 安装者或集群管理员无需重新编译就可以加入 Admission 插件,像其他基于 k8s.io/apiserver 1.9 的扩展 API Server(例如 metrics(注 2), service-catalog(注 3) 、以及 kube-projects(注 4))一样。两种 Admission Webhook 都在各自的链条尾端运行,和编译的 Admission 插件具有同样的能力和限制。
有什么好处?
Webhook Admission 插件允许对任何 API Server 的任何资源进行变更和验证,所以可能有多种形态的应用,比较普通的用例包括:
注册
Webhook Admission 插件需要注册,所有的 API Server(Kube API server 以及所有扩展 API Server)都共享一个配置。在注册过程中插件需要提供如下信息:
apiVersion: admissionregistration.k8s.io/v1beta1 kind: ValidatingWebhookConfiguration metadata: name: namespacereservations.admission.online.openshift.io webhooks: - name: namespacereservations.admission.online.openshift.io clientConfig: service: namespace: default name: kubernetes path: /apis/admission.online.openshift.io/v1alpha1/namespacereservations caBundle: KUBE_CA_HERE rules: - operations: - CREATE apiGroups: - "" apiVersions: - "*" resources: - namespaces failurePolicy: Fail
name:Webhook 的名称。变更类的 Hook 会使用名称进行排序。 clientConfig:如何连接,证书信任,以及如何向 Webhook Admission 服务器发送数据。 rules:API Server 应该在什么时机调用 Webhook。这里只有创建 Namespace 的时候才触发。这里可以指定任何资源,例如serviceinstances.servicecatalog.k8s.io的create操作也是可以定义的。 failurePolicy:如果 Webhook Admission 服务器无法连接,如何处置?有两个选项分别是 ”Ignore“(失败就通过) 和 ”Fail“(失败就拒绝)。失败则通过的设置,可能会导致无法预测的行为。
认证和信任
因为 Webhoo Admission 插件能够获取任何发送过来的请求资源的内容,并且能进行变更,所以很有必要回答下面的问题:
- API Server 如何检验 Webhook Admission Server。
- Webhook Server 如何精确认证接入进来的 API Server。
- 接入的 API Server 是否被授权发送请求。
连接主要分为三种:
要支持这些类别,Webhook Admission 插件可以用一个 kubeconfig 文件来得知如何连接到独立的服务器。为了和外部的 Admission Webook 进行通信,因为认证、授权都是外部服务器处理的,因此只能手工指定,别无他法。
自有服务来说,一个明智的插件会提供缺省的安全设施,提供简单、安全、可移植、零配置,并可以在各个 API Server 运行的能力。
简单、安全、可移植、零配置
如果把 Webhook Admission 服务器构建成扩展 API Server 的模式,就有可能把它聚合为一个普通的 API 服务器,会收到如下益处:
- 你的 Webhook 会和其他 API 一样,以类似 kube-apiserver kubernetes.default.svc (例如 https://kubernetes.default.svc/apis/admission.example.com/v1/mymutatingadmissionreviews)服务的面目出现。可以使用kubectl进行测试。
- 无需任何配置,你的 Webhook 自动具有了集群内置的认证和授权能力,可以使用 RBAC 规则进行访问控制。
- API Server 和 Webhook 之间可以直接使用内置认证进行通信。
- 因为通过 Kube API Server 代理通信,因此扩展 API Server 不会泄露 Service Account Token。
简单说来,这一安全拓扑可以使用 API Server 的所有安全机制,并且无需额外配置。
其他用法也是可以的,不过就需要附加的手工配置,以及大量的额外工作来完成同等目标。
如何开发 Webhook admission 服务器?
编写一个具有认证和鉴权能力的完整的服务是个令人生畏的任务。为简化这一工作,有些基于 Kubernetes 1.9 的项目提供了库支持,能把代码量缩减到两百行甚至更少。可以参考 generic-admission-apiserver(注 5)以及 kubernetes-namespace-reservation(注 6)作为创建自己的安全、可移植的 Webhook Server 的示例。
在 1.9 中有了 Admission Webhook,让 Kubernetes 更加贴近用户需求,我们希望 Red Hat 和 Google 的这一工作能让支持更多的工作负载,为整体生态贡献更多(例如 Istio),现在是时候试一试了!
如果有兴趣做出贡献或者反馈,请加入 SIG API machinery(注 7)
注:
https://github.com/kubernetes/community/tree/master/sig-api-machinery