<aside> ⏰ 本文介绍如何创建一个用于容器镜像仓库白名单的 Admission Webhook。
</aside>
前面我们已经介绍了准入控制器的含义,了解可以通过有两个特殊的“动态”控制器 -ValidatingAdmissionWebhook
和 MutatingAdmissionWebhook
来让开发者自行实现自己的准入逻辑。这两个控制器没有实现任何固定逻辑,相反,它们使我们能够在每次在集群中创建、更新或删除Kubernetes 资源时通过 webhooks 灵活地实现和执行自定义逻辑。
接下来我们将构建一个准入控制器示例,只允许使用来自白名单镜像仓库的资源创建 Pod,拒绝使用不受信任的镜像仓库中进行拉取镜像。
比如我们这里之允许使用来自 docker.io 或者 gcr.io 镜像仓库的镜像创建 Pod,其他不受信任的镜像创建的 Pod 将会被拒绝。
要实现这个需求,我们就需要构建一个 ValidatingAdmissionWebhook
,并将其注册到 APIServer。在编写这个 Webhook 之前我们就需要先链接通过注册的 Webhook 从 APIServer 接收到的请求的结构,以及我们对 APIServer 的响应结构。
APIServer 实际上使用的是一个 AdmissionReview
类型的对象来向我们自定义的 Webhook 发送请求和接收响应。
对于每个请求,在 AdmissionReview 结构体内部都有一个 AdmissionRequest 类型的属性,该属性中封装了发送到 APIServer 的原始请求数据,我们主要关心的就是该对象内部包含的正在创建/更新或删除的 Kubernetes 对象(比如 Pod、Deployment 等) JSON payload 数据。下面是用于验证准入控制器的 AdmissionReview 请求对象示例:
{
"apiVersion": "admission.k8s.io/v1",
"kind": "AdmissionReview",
"request": {
# Random uid uniquely identifying this admission call
"uid": <random uid>,
...
"object": {"apiVersion":"v1","kind":"Pod",...},
...
}
}
对于验证准入控制器,我们的应用程序必须接收一个 AdmissionReview
对象,对其进行处理来决定是否允许/不允许该请求,并通过在 AdmissionReview
结构中填充一个类型为 AdmissionResponse
的 response 属性来返回我们的验证结果。在 response 中,我们使用一个名为 allowed 的布尔类型来表示是否允许/不允许,我们还可以选择包含一个 HTTP 状态码和一条 message 消息,将其传递回客户端。下面是用于验证准入控制器的 AdmissionReview
响应对象示例:
{
"apiVersion": "admission.k8s.io/v1",
"kind": "AdmissionReview",
"response": {
"uid": "<value from request.uid>",
"allowed": true/false,
"status": {
"code": <optional http status code, ex: 200/403>,
"message": "optional message"
}
}
}
如果我们要构建一个 Mutating 准入控制器,我们将使用一个 JSONPatch
类型的对象作为 AdmissionReview
响应的 response 属性的一部分发送回变更的结果,原始请求将使用此JSON Patch 进行修改。下面是用于 Mutating 准入控制器的 AdmissionReview
响应对象示例:
{
"apiVersion": "admission.k8s.io/v1",
"kind": "AdmissionReview",
"response": {
"uid": "<value from request.uid>",
"allowed": true/false,
"status": {
"code": <optional http status code, ex: 200/403>,
"message": "optional message"
},
"patchType": "JSONPatch",
"patch": <base64 encoded JSON patch>
}
}
关于 AdmissionReview 的完整结构定义可以查看文档:https://github.com/kubernetes/api/blob/master/admission/v1/types.go。
这里我们要实现的是一个简单的带 TLS 认证的 HTTP 服务,用 Deployment 方式部署在我们的集群中。
首先新建项目: