jimyag's Blog

Kubernetes admission webhook 自签名证书认证

k8s 在 apiserver 中提供 准入控制 扩展,用于在资源创建、更新、删除操作时进行拦截和处理。

自定义的准入控制器通过提供一个 webhook 服务,再创建对应的资源对象注册到 apiserver 中,这就是 Dynamic Admission Control 动态准入控制。比如你作为某个 k8s 的平台管理员,希望使用方在创建 pod 的时候必须带上特定的业务标签,就可以通过自定义准入控制器来实现。

API Server 通过 TLS 连接 webhook,并用 caBundle 校验 webhook 服务端证书。

证书架构

  graph TB
    subgraph "Certificate Authority (CA)"
        CAKey[CA 私钥]
        CACert[CA 证书]
    end

    subgraph "Serving Certificate"
        ServingKey[服务私钥]
        ServingCert[服务证书]
    end

    CAKey -->|签发| ServingCert
    CACert -->|配置到 caBundle| APIServer[API Server]
    ServingKey --> WebhookServer[Webhook Server]
    ServingCert --> WebhookServer

    APIServer -->|TLS 请求| WebhookServer
    APIServer -->|用 caBundle 验证| ServingCert

认证流程

webhook 提供服务证书和私钥;WebhookConfiguration 中的 caBundle 提供信任的 CA 证书。轮换 CA 时可以同时配置新旧 CA 证书,让新旧服务证书在过渡期都能通过校验。

当用户执行 kubectl create pod 触发 Webhook 调用时:

  sequenceDiagram
    participant API as API Server
    participant Webhook as Webhook Server

    API->>Webhook: 1. 发起 TLS 连接
    Webhook->>API: 2. 返回服务证书
    Note over API: 3. 用 caBundle 验证证书:<br/>- CA 是否可信?<br/>- DNS 名称是否匹配?<br/>- 证书是否过期?
    alt 验证通过
        API->>Webhook: 4. 发送 AdmissionReview
        Webhook->>API: 5. 返回 AdmissionResponse
    else 验证失败
        API--xWebhook: 拒绝连接
    end

核心验证点:

  1. CA 可信:服务证书必须由 caBundle 中的 CA 签发
  2. DNS 匹配:证书的 SAN 必须包含 Webhook Service 的 DNS 名称
  3. 未过期:证书在有效期内

#Kubernetes