API Server如何集成自定义准入策略?

在 Kubernetes 中,API Server 的自定义准入策略(Admission Control) 允许你在资源创建、更新或删除时执行自定义验证和修改逻辑。以下是集成自定义准入策略的详细流程:

API Server如何集成自定义准入策略?_第1张图片

一、核心组件与流程

1. 客户端请求
  • 用户通过 kubectl、SDK 或直接调用 API 发送资源操作请求(CREATE/UPDATE/DELETE)。
2. API Server 处理阶段
  1. 认证(Authentication)

    • 验证请求身份(如 Token、证书)。
  2. 授权(Authorization)

    • 检查用户是否有操作权限(基于 RBAC、ABAC 等策略)。
  3. 准入控制链(Admission Chain)

    • 内置控制器:依次执行 NamespaceLifecycle、LimitRanger 等内置准入控制器。
    • 自定义 Webhook:按配置顺序调用验证型和修改型 Webhook。
3. 自定义准入 Webhook
  • 验证型(Validating)

    • 并行调用多个 Webhook,拒绝或允许请求,但不修改资源。
    • 典型场景:强制标签检查、权限边界控制。
  • 修改型(Mutating)

    • 串行调用 Webhook,可修改资源内容(如注入 Sidecar 容器、添加默认值)。
    • 执行顺序由webhook.priority字段控制。
4. Webhook 服务
  • 服务实现:独立部署的 HTTP 服务,接收 AdmissionReview 请求,返回 AdmissionResponse。
  • 通信协议
    • API Server 通过 HTTPS 调用 Webhook 服务。
    • 使用 TLS 证书验证双方身份(自签名或 CA 颁发)。

二、集成流程详解

1. 开发准入 Webhook 服务

使用 Go 或其他语言开发 HTTP 服务,处理准入请求:

// 示例:验证Pod是否包含特定标签
package main

import (
    "encoding/json"
    "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", "cert.pem", "key.pem", nil))
}

func validateHandler(w http.ResponseWriter, r *http.Request) {
    // 解析准入请求
    var admissionReview admissionv1.AdmissionReview
    if err := json.NewDecoder(r.Body).Decode(&admissionReview); err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    // 提取Pod对象
    pod := &corev1.Pod{}
    if err := json.Unmarshal(admissionReview.Request.Object.Raw, pod); err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    // 验证逻辑:检查是否有required-label标签
    allowed := true
    var message string
    if _, ok := pod.Labels["required-label"]; !ok {
        allowed = false
        message = "Pod must have 'required-label' label"
    }

    // 构建响应
    admissionReview.Response = &admissionv1.AdmissionResponse{
        UID:     admissionReview.Request.UID,
        Allowed: allowed,
        Result: &metav1.Status{
            Message: message,
        },
    }

    // 返回响应
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(admissionReview)
}
2. 部署 Webhook 服务到 K8s

创建 Deployment 和 Service:

# webhook-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pod-validator-webhook
spec:
  replicas: 1
  selector:
    matchLabels:
      app: pod-validator
  template:
    metadata:
      labels:
        app: pod-validator
    spec:
      containers:
      - name: webhook-server
        image: your-image:tag
        ports:
        - containerPort: 443
        volumeMounts:
        - name: cert
          mountPath: /etc/certs
          readOnly: true
      volumes:
      - name: cert
        secret:
          secretName: webhook-cert  # 证书密钥

---
apiVersion: v1
kind: Service
metadata:
  name: pod-validator-service
spec:
  ports:
  - port: 443
    targetPort: 443
  selector:
    app: pod-validator
3. 配置 TLS 证书

Webhook 服务必须使用 HTTPS,证书可通过以下方式生成:

  1. 自签名证书(测试环境):
    openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/CN=pod-validator-service.default.svc"
    
    # 创建K8s Secret
    kubectl create secret tls webhook-cert --key key.pem --cert cert.pem
    
  2. Cert-Manager 自动签发(生产环境):
    # 配置Certificate资源
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: webhook-cert
    spec:
      dnsNames:
      - pod-validator-service.default.svc
      issuerRef:
        name: ca-issuer
        kind: ClusterIssuer
      secretName: webhook-cert
    
4. 定义 ValidatingWebhookConfiguration
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: pod-validator-webhook
webhooks:
- name: validator.example.com
  rules:
  - apiGroups:   [""]
    apiVersions: ["v1"]
    operations:  ["CREATE", "UPDATE"]
    resources:   ["pods"]
    scope:       "Namespaced"
  clientConfig:
    service:
      name: pod-validator-service
      namespace: default
      path: "/validate"
    caBundle: ${CA_BUNDLE}  # Base64编码的CA证书
  admissionReviewVersions: ["v1"]
  sideEffects: None
  timeoutSeconds: 5
5. 注册 Webhook 到 API Server
  1. 将 ValidatingWebhookConfiguration 应用到集群:
    kubectl apply -f webhook-config.yaml
    
  2. API Server 自动发现并调用 Webhook 服务。

三、数据流向详解

1. 请求阶段
  1. 客户端发送资源创建请求(如 Pod)。
  2. API Server 解析请求,提取资源对象。
  3. 按顺序执行准入控制链:
    • 内置控制器处理(如验证 Namespace 是否存在)。
    • 修改型 Webhook 按优先级依次处理,可能修改资源内容。
    • 验证型 Webhook 并行处理,决定是否允许请求。
2. Webhook 交互
  1. API Server 向 Webhook 服务发送 AdmissionReview 请求,包含:

    • 请求类型(CREATE/UPDATE/DELETE)。
    • 资源对象的原始和修改后内容。
    • 用户身份信息。
  2. Webhook 服务执行自定义逻辑(如:

    • 检查 Pod 是否包含必要标签。
    • 自动注入 Istio 代理容器。
    • 验证资源配额是否超出限制。
  3. Webhook 返回 AdmissionResponse:

    • 允许 / 拒绝请求。
    • 若拒绝,附带错误信息。
    • 若修改,包含修改后的资源内容。
3. 响应阶段
  • 若所有 Webhook 允许请求,API Server 将资源持久化到 etcd。
  • 若任一 Webhook 拒绝,API Server 返回 HTTP 403 错误给客户端。

四、关键配置参数解析

  1. rules 字段
    指定 Webhook 拦截的资源类型和操作:

    rules:
    - apiGroups:   ["apps"]
      apiVersions: ["v1"]
      operations:  ["CREATE", "UPDATE"]
      resources:   ["deployments", "statefulsets"]
      scope:       "Namespaced"
    
  2. matchConditions(K8s 1.23+)
    基于资源字段的条件匹配:

    matchConditions:
    - name: "env-production"
      expression: "object.metadata.namespace == 'production'"
    
  3. failurePolicy
    处理 Webhook 失败的策略:

    failurePolicy: Fail  # 失败时拒绝请求(默认)
    # 或
    failurePolicy: Ignore  # 失败时允许请求
    

四、验证与测试

  1. 部署测试 Pod
    apiVersion: v1
    kind: Pod
    metadata:
      name: test-pod
    spec:
      containers:
      - name: nginx
        image: nginx
    
  2. 尝试创建 Pod,预期失败(缺少required-label):
    kubectl apply -f test-pod.yaml
    # 输出错误:Pod must have 'required-label' label
    
  3. 添加标签后重试:
    metadata:
      name: test-pod
      labels:
        required-label: "true"
    

五、安全与性能考虑

  1. 网络隔离

    • 将 Webhook 服务部署在专用命名空间,限制访问权限。
    • 使用 NetworkPolicy 控制 Webhook 服务的入站和出站流量。
  2. 性能优化

    • 设置合理的timeoutSeconds(建议 5-10 秒)。
    • 对高并发场景,考虑水平扩展 Webhook 服务。
  3. 监控与日志

    • 收集 Webhook 服务的请求响应日志。
    • 设置 Prometheus 指标监控 Webhook 服务的可用性和响应时间。

六、总结

集成自定义准入策略的核心步骤:

  1. 开发 Webhook 服务:实现准入逻辑,处理 AdmissionReview 请求。
  2. 部署服务:创建 Deployment 和 Service,并配置 TLS 证书。
  3. 注册 Webhook:通过 ValidatingWebhookConfiguration 或 MutatingWebhookConfiguration 将服务注册到 API Server。
  4. 验证与优化:测试策略效果,调整配置确保安全性和性能。

通过自定义准入策略,你可以实现环境特定的安全检查、资源标准化、成本控制等高级功能,增强 Kubernetes 集群的安全性和可管理性。

你可能感兴趣的:(#,Kubernetes系列,k8s)