在 Kubernetes 集群里对外暴露 HTTPS 服务时,证书的信任问题不只是“装上就行”。客户端浏览器会去查这张证书有没有被吊销,证书本身有没有被公开审计记录在案,这些动作分别涉及 OCSP 和证书透明度两个机制。如果配置不当,轻则握手延迟增加几百毫秒,重则浏览器直接弹出警告。这篇文章就来拆解这两个概念在 Kubernetes 环境下的落地方式。

证书透明度到底是什么,Kubernetes 管理员需要关心什么
证书透明度(Certificate Transparency,简称 CT)是 Google 主推的一套公开审计框架,要求 CA 在签发证书时必须把证书提交到公开的、可验证的 CT 日志中。任何人都可以查询这些日志,确认某张证书是否被合法签发、是否存在恶意签发的情况。Chrome 从 2018 年起强制要求所有可信证书必须包含 SCT(Signed Certificate Timestamp),也就是 CA 写入证书中的“已提交日志”签名回执。
对 Kubernetes 管理员来说,CT 日志的价值主要体现在审计侧。比如你的团队持有 example 组织的域名,可以定期通过 crt.sh 或者 Google 的 Certificate Transparency Log 搜索接口查询是否有陌生的证书被签发出来。如果有人冒充你的域名向 CA 申请了证书,这是发现域名劫持和内部人员违规签发的重要手段。
需要注意的一点常见误区:CT 不是证书校验的开关,浏览器对 SCT 的要求是强制的,你没法“关闭”证书透明度。如果你用自签证书或者私有 CA(比如企业内部 Vault PKI),这些证书本身就不在公开 CT 日志里,浏览器自然也不会信任它们。在集群内部服务间通信(mTLS)场景下,通常用私有 CA 配合 SPIFFE 身份体系,这时 CT 完全不适用;只有面向公网的入口证书才需要考虑 CT 合规。
OCSP 的性能瓶颈与 stapling 的解决思路
OCSP(Online Certificate Status Protocol)是 CA 提供的证书状态查询接口。传统模式下,客户端在 TLS 握手时会实时向 CA 的 OCSP 服务端点发起请求,查询这张证书是否被吊销。这个模式有三个明显的问题:第一,每次握手都多一个网络往返,增加延迟;第二,CA 的 OCSP 服务一旦宕机,客户端要么放行(不安全)要么拒绝(影响可用性);第三,客户端的查询行为本身会向 CA 泄露用户访问了哪些网站,构成隐私问题。
OCSP stapling(中文常译作“装订”)的思路是让服务端代替客户端去查询。Kubernetes 集群中的 Ingress 控制器(比如 Nginx Ingress)作为反向代理,定期向 CA 拉取 OCSP 响应,把它“装订”在 TLS 握手过程中直接发给客户端。这样客户端不再需要自己发起查询,延迟降为零,隐私问题也一并解决。由于 OCSP 响应是 CA 签名的,服务端无法伪造,安全性没有损失。
下面是一个 Nginx Ingress 的注解配置,开启 OCSP stapling 并配合 HTTP/2 使用:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-certificate: "default/web-tls"
# 开启 OCSP stapling(Nginx Ingress 默认已开启,可显式声明)
nginx.ingress.kubernetes.io/enable-ocsp-stapling: "true"
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/enable-http2: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- app.ipipp.com
secretName: web-tls
rules:
- host: app.ipipp.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-svc
port:
number: 80
这段配置的关键点在于 secretName 指向的 Secret 必须包含完整的证书链。很多人配 stapling 失败,就是因为证书文件里只放了叶子证书,没有拼上中间证书。Nginx 在拿不到完整链的情况下找不到 OCSP 地址,stapling 会静默失效。可以用 openssl 命令验证效果:
# 查看 OCSP 响应是否被装订,返回 OCSP response: 无则说明失败 openssl s_client -connect app.ipipp.com:443 -status -servername app.ipipp.com < /dev/null 2>&1 | grep -A 3 "OCSP" # 手动向 CA 查询证书状态,确认 AIA 地址可达 openssl ocsp -issuer chain.pem -cert leaf.pem -text -url http://ocsp.example-ca.com
结合 cert-manager 实现证书签发与自动续期
生产环境中很少有人手动维护证书,cert-manager 是 Kubernetes 生态的事实标准。它通过 CRD 的方式声明证书需求,支持 Let's Encrypt、ZeroSSL 等公开 CA,也支持 Vault 和私有 CA。Let's Encrypt 签发的证书自带 SCT,天然满足证书透明度要求,同时提供 OCSP 服务端点,可以配合 stapling 使用。
一个典型的 Issuer 和 Certificate 配置如下:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ops@ipipp.com
privateKeySecretRef:
name: letsencrypt-prod-account-key
solvers:
- http01:
ingress:
class: nginx
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: web-cert
spec:
secretName: web-tls
duration: 2160h # 90 天
renewBefore: 720h # 提前 30 天续期
dnsNames:
- app.ipipp.com
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
这里有几个实践细节值得注意。renewBefore 建议设置为有效期的一半左右,给续期失败留出重试窗口;Let's Encrypt 的 OCSP 响应有效期通常是 3 到 7 天,Nginx 会自动在过期前重新拉取,不需要人工干预;另外 Let's Encrypt 已经宣布逐步淘汰 OCSP 转向更轻量的 CRL 和短周期证书方案,新项目也可以考虑把证书有效期缩短到几天,用高频自动续期替代吊销检查,这是目前业界的一个演进方向。
常见问题排查与最佳实践
配置完成后如果 stapling 没生效,按以下顺序排查。第一,确认证书链完整,kubectl get secret web-tls -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -text 检查是否包含中间证书;第二,检查出集群的网络策略是否放行了 CA 的 OCSP 端点,有些安全加固过的集群默认拒绝 Pod 主动外联,需要为 Ingress 控制器的 Pod 添加出站白名单;第三,查看 Ingress 控制器日志中有没有 ssl_stapling ignored 之类的告警。
关于证书透明度的运维侧实践,建议把 CT 日志监控纳入例行工作。可以用开源工具定期抓取 crt.sh 的 JSON 接口,把新签发的证书与资产清单做比对,发现陌生签发立即告警。对于规模较大的组织,还可以在 DNS 层面部署 CAA 记录,明确限定只有指定 CA 可以为你的域名签发证书,从源头上缩小攻击面:
ipipp.com. IN CAA 0 issue "letsencrypt.org" ipipp.com. IN CAA 0 iodef "mailto:security@ipipp.com"
总结一下:证书透明度是 CA 生态的强制审计机制,运维侧的价值在于主动监控日志发现异常签发;OCSP stapling 则是纯性能与隐私优化,核心前提是证书链完整、网络可达。两者配合 cert-manager 的自动化续期,基本可以做到证书体系免维护。如果还在用手动复制证书文件到 Secret 的方式,尽早迁移到自动化方案,能省掉大量半夜处理证书过期告警的时间。
Kubernetes证书管理OCSP stapling证书透明度修改时间:2026-09-13 13:12:48