Kubernetes admission webhook 自签名证书认证
k8s 在 apiserver 中提供 准入控制 扩展,用于在资源创建、更新、删除操作时进行拦截和处理。
自定义的准入控制器通过提供一个 webhook 服务,再创建对应的资源对象注册到 apiserver 中,这就是 Dynamic Admission Control 动态准入控制。比如你作为某个 k8s 的平台管理员,希望使用方在创建 pod 的时候必须带上特定的业务标签,就可以通过自定义准入控制器来实现。
为了保证 webhook 服务的安全性,API Server 与 Webhook 之间需要使用 TLS 证书进行认证。
证书架构
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
认证流程
用"银行验证 ATM 机身份"来类比:
- API Server = 银行总部,需要验证对方身份
- Webhook = ATM 机,需要证明自己是合法的
- CA = 认证机构,负责颁发"身份证"(证书)
- caBundle = 银行总部持有的认证机构列表,注意是多个,主要是为了应对证书轮换。
当用户执行 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
核心验证点:
- CA 可信:服务证书必须由
caBundle中的 CA 签发 - DNS 匹配:证书的 SAN 必须包含 Webhook Service 的 DNS 名称
- 未过期:证书在有效期内