欢迎光临
我们一直在努力

通过准入控制器 MutatingWebhook 实现 Pod 配置的自动注入与合规性检查

Kubernetes 的准入控制器(Admission Controllers)是控制集群变更的关键组件。其中,MutatingAdmissionWebhook 允许我们在资源对象被持久化到 etcd 之前对其进行修改(突变)。这使得我们可以实现强大的自动化功能,例如自动注入 Sidecar 容器、设置默认标签或环境变量,从而确保所有 Pod 都符合组织定义的合规性。

本文将聚焦如何使用 MutatingWebhook 实现 Pod 配置的自动注入,并提供核心的 JSON Patch 逻辑。

1. MutatingWebhook 工作原理

当用户提交一个 Pod 定义时,API Server 会经历以下步骤:

  1. 认证/授权
  2. 执行 Mutating Webhooks: Webhook Server 接收一个 AdmissionReview 请求,该请求包含待创建的 Pod 定义。Webhook Server 返回一个包含 patch(使用 JSON Patch 格式)的 AdmissionReview 响应。
  3. 应用修改: API Server 应用 JSON Patch。
  4. 执行 Validating Webhooks (合规性检查)。
  5. 持久化到 etcd

2. 核心步骤:定义 JSON Patch 注入逻辑

我们的 Webhook Server 必须能够解析传入的 Pod 定义,判断是否需要注入,然后生成 JSON Patch。

假设我们要实现以下目标:对于带有标签 injector.example.com/sidecar: “true” 的 Pod,自动注入一个名为 monitoring-agent 的 Sidecar 容器。

Python/Flask 伪代码示例(处理逻辑)

import json
import base64

def generate_patch(admission_request):
    # 提取待创建的 Pod 定义
    pod = admission_request['request']['object']

    # 检查是否需要注入
    labels = pod.get('metadata', {}).get('labels', {})
    if labels.get('injector.example.com/sidecar') != 'true':
        return [] # 不注入,返回空 Patch

    # 定义要注入的 Sidecar 容器
    sidecar_container = {
        "name": "monitoring-agent",
        "image": "prom/node-exporter:latest",
        "resources": {
            "limits": {"cpu": "100m", "memory": "128Mi"}
        },
        "ports": [{"containerPort": 9100}]
    }

    # 生成 JSON Patch 数组
    # 使用 'add' 操作,路径 '/spec/containers/-' 表示将其附加到容器列表末尾
    patch = [
        {
            "op": "add", 
            "path": "/spec/containers/-", 
            "value": sidecar_container
        },
        {
             "op": "add", 
             "path": "/metadata/annotations", 
             "value": {"injector.example.com/status": "injected"}
        }
    ]

    return patch

def handle_webhook_request(data):
    # ... (处理 AdmissionReview 请求并调用 generate_patch)
    patch = generate_patch(data)

    # 将 Patch 编码为 Base64
    patch_bytes = json.dumps(patch).encode('utf-8')
    encoded_patch = base64.b64encode(patch_bytes).decode('utf-8')

    # 构建 AdmissionReview 响应
    response = {
        "apiVersion": "admission.k8s.io/v1",
        "kind": "AdmissionReview",
        "response": {
            "uid": data['request']['uid'],
            "allowed": True,
            "patchType": "JSONPatch",
            "patch": encoded_patch
        }
    }
    return response

3. Kubernetes 配置定义

Webhook 服务器通常部署为一个 Service 和 Deployment,并且必须使用 TLS 证书(K8s API Server 必须信任该证书)。

3.1 定义 MutatingWebhookConfiguration

此配置告诉 Kubernetes API Server 何时将请求发送给我们的 Webhook 服务。

apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  name: sidecar-injector-webhook-config
webhooks:
  - name: injector.example.com
    clientConfig:
      service:
        name: sidecar-injector-service # Webhook Server 对应的 Service 名称
        namespace: default
        path: "/mutate"
      caBundle: | # 必须是 Webhook Server 证书颁发机构的 PEM 编码 CA 证书
        # 示例:base64 编码的 CA 证书内容
        LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCg==
    rules:
      - operations: [ "CREATE" ]
        apiGroups: [ "" ]
        apiVersions: [ "v1" ]
        resources: [ "pods" ]
    failurePolicy: Ignore # 如果 Webhook 失败,是忽略还是拒绝资源创建
    sideEffects: None # 确保 Webhook 不会影响其他资源的副作用
    admissionReviewVersions: ["v1"]
    scope: Namespaced

3.2 部署测试 Pod

一旦 Webhook Server 运行且配置生效,任何带有特定标签的 Pod 创建请求都会被拦截并修改。

apiVersion: v1
kind: Pod
metadata:
  name: my-app-with-sidecar
  labels:
    app: my-app
    injector.example.com/sidecar: "true" # 触发注入
spec:
  containers:
  - name: main-app
    image: nginx:latest
    ports:
    - containerPort: 80

当这个 Pod 被创建时,如果查看其定义 (kubectl get pod my-app-with-sidecar -o yaml),你会发现 monitoring-agent 容器已经被自动添加到 spec.containers 列表中。

【本站文章皆为原创,未经允许不得转载】:汤不热吧 » 通过准入控制器 MutatingWebhook 实现 Pod 配置的自动注入与合规性检查
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址