<aside> ⏰ 本文介绍如何创建一个用于容器镜像仓库白名单的 Admission Webhook。

</aside>

前面我们已经介绍了准入控制器的含义,了解可以通过有两个特殊的“动态”控制器 -ValidatingAdmissionWebhookMutatingAdmissionWebhook 来让开发者自行实现自己的准入逻辑。这两个控制器没有实现任何固定逻辑,相反,它们使我们能够在每次在集群中创建、更新或删除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 方式部署在我们的集群中。

首先新建项目: