Kubernetes Admission Controllers:Kubernetes 世界的“安检员”与“魔法师”
各位观众,各位朋友,欢迎来到今天的 Kubernetes 深度剖析讲座!今天我们要聊聊 Kubernetes 世界里一群神秘而重要的角色:Admission Controllers。
想象一下,Kubernetes 集群是一个热闹非凡的城市,各种应用服务就像熙熙攘攘的人群,争先恐后地想进入这个城市。没有秩序,这个城市就会变成一团乱麻,甚至崩溃。而 Admission Controllers,就好像是这座城市的“安检员”和“魔法师”,他们负责对所有进入集群的请求进行检查、验证,甚至修改,确保这个城市安全、稳定、高效地运转。
简单来说,Admission Controllers 就是 Kubernetes 的准入控制机制,它拦截对 Kubernetes API Server 的请求,并在对象持久化之前对请求进行验证(validation)或修改(mutation)。
为什么我们需要 Admission Controllers?
你可能会问,Kubernetes 本身不是已经有认证和授权了吗?为什么还需要 Admission Controllers 这么一道“额外”的工序?
嗯,这个问题问得好!认证和授权就像是检查你的身份证和门票,验证你是否有资格进入这个城市。而 Admission Controllers 则更进一步,他们会检查你携带的物品是否安全、是否符合城市的规定,甚至可以根据规定修改你的服装,让你更适合这个城市的环境。
具体来说,我们需要 Admission Controllers 来实现以下目标:
- 安全加固: 阻止恶意镜像的部署,限制特权容器的使用,防止资源滥用等。
- 策略执行: 强制执行组织内的命名规范、资源限制、安全策略等。
- 资源优化: 自动注入 sidecar 容器,设置默认资源请求,优化资源利用率。
- 自定义逻辑: 根据业务需求,实现自定义的验证和修改逻辑,满足特殊场景的需求。
总而言之,Admission Controllers 提供了一种灵活、强大的方式来扩展 Kubernetes 的功能,并使其更符合我们的实际需求。
Admission Controllers 的工作原理:一场精妙的拦截与变形
现在,让我们深入了解一下 Admission Controllers 的工作原理。你可以把 Admission Controllers 想象成一个管道,所有对 Kubernetes API Server 的请求都要经过这个管道。
这个管道分为两个阶段:
- Mutating Admission Webhooks (变形阶段): 这个阶段就像是“魔法师”在施展魔法,它可以修改请求的对象。例如,自动注入 sidecar 容器,设置默认的资源请求等。这个阶段可以有多个 Mutating Admission Webhooks,它们按照配置的顺序依次执行。
- Validating Admission Webhooks (验证阶段): 这个阶段就像是“安检员”在进行严格的检查,它会验证请求的对象是否符合预定义的规则。例如,检查镜像是否来自可信的仓库,检查资源限制是否超标等。这个阶段也可以有多个 Validating Admission Webhooks,它们按照配置的顺序依次执行。
整个流程可以用下图来概括:
graph LR
A[API Server] --> B{Authentication/Authorization};
B --> C{Mutating Admission Webhooks};
C --> D{Validating Admission Webhooks};
D --> E{Object Persistence};
E --> F[Response to Client];
C -- Mutated Object --> D;
D -- Validation Success --> E;
D -- Validation Failed --> G[Rejection];
G --> F;
- API Server: 接收客户端的请求。
- Authentication/Authorization: 认证和授权用户身份,判断其是否有权限进行操作。
- Mutating Admission Webhooks: 修改请求的对象。
- Validating Admission Webhooks: 验证请求的对象。
- Object Persistence: 将对象持久化到 etcd 中。
- Response to Client: 向客户端返回响应。
- Rejection: 拒绝请求。
如果任何一个 Admission Webhook 拒绝了请求,整个流程就会中断,API Server 会向客户端返回错误信息。
Admission Controllers 的类型:内置 vs. 自定义
Kubernetes 提供了两种类型的 Admission Controllers:
- 内置 Admission Controllers: 这些是 Kubernetes 自带的,默认情况下会启用一些常用的 Admission Controllers,例如
NamespaceLifecycle
、LimitRanger
、ServiceAccount
等。 你可以通过查看 API Server 的启动参数来确认哪些是默认开启的。 - Dynamic Admission Webhooks: 这是我们可以自定义的,通过 HTTP 回调到我们自己的服务,实现更灵活的验证和修改逻辑。
内置的 Admission Controllers 提供了基础的功能,但往往无法满足我们所有的需求。这时,我们就需要使用 Dynamic Admission Webhooks 来扩展 Kubernetes 的功能。
实践:手把手教你打造一个自定义 Admission Webhook
接下来,让我们通过一个简单的例子,来演示如何创建一个自定义的 Admission Webhook。
假设我们有一个需求:我们需要强制所有 Pod 都必须包含一个特定的 Label,例如 owner=team-a
。
我们可以通过以下步骤来实现:
-
编写 Webhook 服务: 我们需要编写一个 HTTP 服务,接收 AdmissionReview 请求,并返回 AdmissionReview 响应。这个服务需要实现以下逻辑:
- 解析 AdmissionReview 请求,获取 Pod 对象。
- 检查 Pod 对象是否包含
owner=team-a
Label。 - 如果包含,则返回允许的 AdmissionReview 响应。
- 如果不包含,则返回拒绝的 AdmissionReview 响应,并给出错误信息。
我们可以使用任何编程语言来实现这个 Webhook 服务,例如 Go、Python、Java 等。这里我们以 Go 语言为例,提供一个简单的示例代码:
package main import ( "encoding/json" "fmt" "io/ioutil" "log" "net/http" admissionv1 "k8s.io/api/admission/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func main() { http.HandleFunc("/validate", validateHandler) log.Fatal(http.ListenAndServeTLS(":443", "/etc/webhook/certs/tls.crt", "/etc/webhook/certs/tls.key", nil)) } func validateHandler(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { log.Printf("Error reading request body: %v", err) http.Error(w, "Error reading request body", http.StatusBadRequest) return } var admissionReview admissionv1.AdmissionReview if err := json.Unmarshal(body, &admissionReview); err != nil { log.Printf("Error unmarshaling admission review: %v", err) http.Error(w, "Error unmarshaling admission review", http.StatusBadRequest) return } pod := corev1.Pod{} if err := json.Unmarshal(admissionReview.Request.Object.Raw, &pod); err != nil { log.Printf("Error unmarshaling pod: %v", err) http.Error(w, "Error unmarshaling pod", http.StatusBadRequest) return } allowed := true message := "" if _, ok := pod.ObjectMeta.Labels["owner"]; !ok { allowed = false message = "Pod must have the 'owner' label." } response := admissionv1.AdmissionReview{ Response: &admissionv1.AdmissionResponse{ UID: admissionReview.Request.UID, Allowed: allowed, Result: &metav1.Status{ Message: message, }, }, } respBytes, err := json.Marshal(response) if err != nil { log.Printf("Error marshaling admission review response: %v", err) http.Error(w, "Error marshaling admission review response", http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") fmt.Fprint(w, string(respBytes)) }
-
部署 Webhook 服务: 我们需要将 Webhook 服务部署到 Kubernetes 集群中。可以使用 Deployment 和 Service 来管理 Webhook 服务。需要注意的是,Webhook 服务必须使用 HTTPS 协议,并且需要配置 TLS 证书。
这里提供一个简单的 Deployment 和 Service 的 YAML 文件:
# deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: admission-webhook labels: app: admission-webhook spec: replicas: 1 selector: matchLabels: app: admission-webhook template: metadata: labels: app: admission-webhook spec: containers: - name: admission-webhook image: your-image:latest # 替换成你的镜像地址 ports: - containerPort: 443 volumeMounts: - name: webhook-certs mountPath: /etc/webhook/certs readOnly: true volumes: - name: webhook-certs secret: secretName: webhook-certs # 替换成你的 Secret 名称 --- # service.yaml apiVersion: v1 kind: Service metadata: name: admission-webhook labels: app: admission-webhook spec: ports: - port: 443 protocol: TCP targetPort: 443 selector: app: admission-webhook
-
创建 TLS 证书: 我们需要为 Webhook 服务创建 TLS 证书,并将其存储在 Kubernetes Secret 中。可以使用
openssl
等工具来生成证书。openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/CN=admission-webhook.default.svc" # 替换成你的 Service 名称 kubectl create secret tls webhook-certs --key key.pem --cert cert.pem
-
注册 Admission Webhook: 我们需要创建一个 MutatingWebhookConfiguration 或 ValidatingWebhookConfiguration 对象,将 Webhook 服务注册到 Kubernetes 集群中。
这里提供一个 ValidatingWebhookConfiguration 的 YAML 文件:
apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: pod-owner-label-validator webhooks: - name: pod-owner-label.example.com clientConfig: service: name: admission-webhook # 替换成你的 Service 名称 namespace: default # 替换成你的 Service 所在的 Namespace path: /validate caBundle: $(base64 -w 0 cert.pem) # 替换成你的 CA 证书 rules: - apiGroups: [""] apiVersions: ["v1"] operations: ["CREATE", "UPDATE"] resources: ["pods"] sideEffects: None admissionReviewVersions: ["v1", "v1beta1"]
需要注意的是,
clientConfig
中的caBundle
字段需要填写 CA 证书的内容。你可以使用base64
命令将证书文件转换成 Base64 编码的字符串。 -
测试 Webhook: 我们可以创建一个不包含
owner
Label 的 Pod,并尝试将其部署到 Kubernetes 集群中。如果一切配置正确,API Server 应该会拒绝这个 Pod 的创建请求,并返回错误信息。apiVersion: v1 kind: Pod metadata: name: test-pod spec: containers: - name: test-container image: nginx
执行
kubectl apply -f pod.yaml
后,你会看到类似以下的错误信息:Error from server: admission webhook "pod-owner-label.example.com" denied the request: Pod must have the 'owner' label.
Admission Controllers 的注意事项
在使用 Admission Controllers 时,需要注意以下几点:
- 性能影响: Admission Controllers 会增加 API Server 的处理时间,因此需要谨慎使用,避免过度复杂的逻辑。
- 故障处理: 如果 Admission Webhook 服务出现故障,可能会导致 API Server 无法正常工作。因此,需要确保 Webhook 服务的稳定性和可用性。
- 顺序依赖: Mutating Admission Webhooks 的执行顺序非常重要,需要仔细考虑,避免出现冲突或错误。
- 权限管理: 需要对 Admission Webhook 服务进行适当的权限管理,防止被恶意利用。
总结:Admission Controllers,Kubernetes 的守护者与改造者
Admission Controllers 是 Kubernetes 中一个非常强大和灵活的工具,它可以帮助我们实现各种各样的安全策略、资源优化、自定义逻辑等。它就像 Kubernetes 世界的“安检员”和“魔法师”,守护着集群的安全和稳定,并根据我们的需求改造着集群的功能。
虽然 Admission Controllers 的配置和使用可能比较复杂,但只要我们掌握了其基本原理和使用方法,就可以充分利用它来提升 Kubernetes 集群的价值。
希望今天的讲座对大家有所帮助!谢谢大家! 👏