4、自动化轮换工具:Cert-Manager与ACME协议实战

说到证书自动化,Cert-Manager 和 ACME 协议是绕不开的两个名字。我最早接触 Cert-Manager 是在一次 K8s 集群的证书大换血中——当时手动轮换了 200 多个证书,差点没把我累趴下。后来我就在想,能不能让机器自己搞定这些事?

嗯,答案就是 Cert-Manager + ACME。说白了,这套组合拳能让你的证书从申请、下发到轮换,全程无人值守。你想想看,这多省心。

4.1 ACME 协议:自动化的基石

ACME(Automatic Certificate Management Environment)是 IETF 的标准协议(RFC 8555)。它的核心思想很简单:让 CA 和客户端通过自动化的挑战应答来验证域名所有权,然后签发证书。

我个人习惯把 ACME 的工作流程拆成三步:

  1. 注册:客户端向 CA 注册账号,获取账户密钥对
  2. 授权:客户端证明自己对域名的控制权(通过 HTTP、DNS 或 TLS 挑战)
  3. 签发:CA 验证通过后,签发证书并返回给客户端

我在项目中遇到过一个问题:很多人以为 ACME 只能用于 Let's Encrypt。其实不是,现在主流的 CA 基本都支持 ACME 了,比如 ZeroSSL、Google Trust Services、甚至企业自建的 PKI 也能跑 ACME。

ACME 挑战类型对比

挑战类型 验证方式 适用场景 优缺点
HTTP-01 在 Web 服务器上放置特定文件 公网可达的 Web 服务 简单,但需要 80 端口开放
DNS-01 在 DNS 记录中添加 TXT 记录 通配符证书、内网服务 无需公网 IP,但需要 DNS API 权限
TLS-ALPN-01 在 TLS 握手时验证 仅 TLS 端口的服务 无需 80 端口,但支持有限

4.2 Cert-Manager:K8s 里的证书管家

Cert-Manager 是 Kubernetes 生态里最流行的证书管理工具。它把证书的生命周期抽象成了 CRD(Custom Resource Definition),你只需要声明想要的证书,剩下的交给它。

它的核心组件包括:

  • Issuer / ClusterIssuer:定义证书颁发者(比如 Let's Encrypt、自建 CA)
  • Certificate:声明证书的域名、有效期、密钥算法等
  • Order / Challenge:ACME 订单和挑战的内部资源
  • Secret:证书和私钥最终存储在 K8s Secret 中

我记得第一次部署 Cert-Manager 时,踩了一个坑:Issuer 和 ClusterIssuer 的区别没搞清楚。Issuer 是命名空间级别的,ClusterIssuer 是集群级别的。如果你想让所有命名空间共用同一个 ACME 账号,就得用 ClusterIssuer。

我的建议:生产环境优先用 ClusterIssuer,配合 RBAC 控制访问权限。这样证书策略统一,管理也方便。

4.3 实战:用 Cert-Manager + ACME 自动轮换证书

下面我带你走一遍完整的配置流程。假设我们要为 example.com 和 *.example.com 申请通配符证书,使用 DNS-01 挑战。

4.3.1 安装 Cert-Manager

# 使用 Helm 安装
helm repo add jetstack https://charts.jetstack.io
helm repo update

helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set installCRDs=true

安装完成后,检查 Pod 是否正常运行:

kubectl get pods -n cert-manager
# 应该看到 cert-manager、cert-manager-cainjector、cert-manager-webhook 三个 Pod

4.3.2 配置 DNS 提供商

DNS-01 挑战需要 Cert-Manager 能操作你的 DNS 记录。以阿里云为例,需要创建一个 Secret 存储 API 密钥:

apiVersion: v1
kind: Secret
metadata:
  name: alidns-secret
  namespace: cert-manager
type: Opaque
stringData:
  access-key: "你的AccessKey"
  secret-key: "你的AccessKeySecret"

4.3.3 创建 ClusterIssuer

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: admin@example.com
    privateKeySecretRef:
      name: letsencrypt-account-key
    solvers:
    - dns01:
        alidns:
          accessKeySecretRef:
            name: alidns-secret
            key: access-key
          secretKeySecretRef:
            name: alidns-secret
            key: secret-key

注意:ACME 服务器地址分生产环境和 staging 环境。staging 环境没有速率限制,适合测试。我曾经在生产环境调试时,因为频繁请求触发了 Let's Encrypt 的速率限制,导致证书签发失败。建议先用 staging 验证配置。

4.3.4 声明证书

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: example-tls
  namespace: default
spec:
  secretName: example-tls-secret
  duration: 2160h  # 90天
  renewBefore: 720h  # 提前30天续期
  commonName: example.com
  dnsNames:
  - example.com
  - "*.example.com"
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer

这里有个关键参数:renewBefore。Cert-Manager 会在证书到期前这个时间点自动触发续期。我一般设置成证书有效期的三分之一,这样有足够的时间处理异常。

4.3.5 验证证书

kubectl get certificate
kubectl describe certificate example-tls
kubectl get secret example-tls-secret -o yaml

如果一切正常,你会看到证书状态变成 Ready,Secret 里包含了 tls.crt 和 tls.key。

4.4 自动化轮换的完整流程

下面这张图展示了 Cert-Manager 与 ACME 协议协同工作的完整流程:

Cert-Manager + ACME 自动化证书轮换流程 用户/运维 Certificate CR Cert-Manager Controller 创建/更新 监听 ACME Order ACME Challenge DNS Provider 添加 TXT 记录 CA / ACME Server 验证 TXT 记录 签发证书 K8s Secret 存储证书 Ingress / 应用 引用 说明: 1. 用户创建 Certificate CR → 2. Controller 创建 ACME Order → 3. 执行 DNS-01 挑战 → 4. CA 验证并签发证书 → 5. 证书存入 Secret → 6. 应用自动加载新证书

4.5 避坑指南

实战中我踩过不少坑,挑几个典型的说说:

  • 速率限制:Let's Encrypt 生产环境每周每个域名只能签发 50 个证书。测试时一定要用 staging 环境。
  • DNS 传播延迟:DNS-01 挑战需要等待 DNS 记录生效。如果 DNS 提供商响应慢,可以设置 dns01CheckInterval 参数增加等待时间。
  • 证书吊销联动:Cert-Manager 本身不处理证书吊销。如果需要吊销证书,得手动调用 CA 的 API 或使用 cert-manager-approver 等工具。
  • 密钥安全:私钥存储在 K8s Secret 中,默认是 base64 编码。建议启用 Secret 加密(如 KMS 或 SOPS)保护私钥。

我的经验:我曾经因为 DNS 提供商 API 密钥过期,导致证书续期失败,服务中断了 2 小时。后来我加了一个监控:每天检查证书剩余有效期,小于 15 天就告警。这样即使自动续期失败,也有时间手动处理。

4.6 总结

Cert-Manager + ACME 这套方案,说白了就是把证书管理的脏活累活都交给机器。你只需要声明想要的证书,剩下的申请、验证、签发、续期、存储,全部自动化完成。

我个人觉得,这套方案最大的价值不是省事,而是消除了人为失误。想想看,手动轮换证书时,漏掉一个域名、写错一个 SAN、忘记更新 Secret——这些坑我都踩过。自动化之后,这些风险基本归零。

嗯,如果你还在手动管理证书,真的可以试试 Cert-Manager。从 staging 环境开始,跑通一个域名,再逐步推广到全集群。你会发现,证书管理原来可以这么轻松。