cert-manager · TLS 证书自动签发
cert-manager 是这套集群的证书生命周期管理器:它监听 Certificate / Ingress 资源,向 ACME CA(Let's Encrypt)申请、续期 TLS 证书,并把签发结果写回 Secret 供 Traefik ingress 终结 TLS。集群里所有对外 HTTPS 域名的证书都由它管,签发器单独配置在 letsencrypt-prod ClusterIssuer 上。
applications/infrastructure/cert-manager/),由 ArgoCD root-app 同步;ServiceMonitor 单独放在 applications/security/cert-manager/。完整 CRD 在 cert-manager-v1.20.2-full-manifest.yaml 里随版本一起进仓。部署形态
cert-manager 拆成三个独立 Deployment,全部跑在 cert-manager namespace,核心镜像统一为 v1.20.2(部分 Service / label 仍带 Helm chart 版本号 v1.16.3,是渲染遗留的展示字段,与运行镜像无关)。
- Name
- cert-manager(controller)
- Description
Deployment,1 副本,镜像quay.io/jetstack/cert-manager-controller:v1.20.2。核心控制器,处理 Certificate / Order / Challenge,签发 ACME 解题用的 acmesolver 镜像也是v1.20.2。--max-concurrent-challenges=60,nodeSelectorworkload: infra。端口 9402(metrics)/ 9403(healthz)。
- Name
- cert-manager-webhook
- Description
Deployment,2 副本,镜像quay.io/jetstack/cert-manager-webhook:v1.20.2。准入校验 webhook,监听 9443(https)/ 6080(healthcheck)/ 9402(metrics)。带软反亲和(podAntiAffinitypreferred,topologyKeykubernetes.io/hostname)让两副本分散到不同节点。
- Name
- cert-manager-cainjector
- Description
Deployment,1 副本,镜像quay.io/jetstack/cert-manager-cainjector:v1.20.2。把 CA bundle 注入到 webhook / APIService 等需要的对象。nodeSelectorworkload: infra,leader election 在kube-system。
三个组件都以非 root 运行(runAsNonRoot、readOnlyRootFilesystem、drop ALL caps、seccomp RuntimeDefault),无持久化存储 —— 证书状态存在 Secret 与 CRD 里,不挂 PVC。namespace 配了 LimitRange(容器默认 50m/64Mi 起,上限 1 CPU / 1Gi)与 ResourceQuota(最多 10 pod,limits 2 CPU / 2Gi)兜底。
配置与依赖
cert-manager 本身无 ConfigMap,运行参数全部走容器 args。它依赖几个由 ExternalSecret 从 Vault(ClusterSecretStore vault-backend,KV v2)拉取的 Secret,刷新间隔统一 1h:
- Name
- cloudflare-api-token
- Description
remoteRef.key: cert-manager/cloudflare(propertyapi-token)。DNS-01 解题时用它在 Cloudflare 创建 TXT 记录,token 必须覆盖到要签发的所有 zone(含relaya.pro)。
- Name
- letsencrypt-prod / letsencrypt-staging
- Description
dataFrom整段 extract,key 分别为cert-manager/letsencrypt-prod与cert-manager/letsencrypt-staging。存 ACME 账户私钥。
- Name
- cert-manager-webhook-ca
- Description
dataFromextract,keycert-manager/cert-manager-webhook-ca,带注解cert-manager.io/allow-direct-injection: "true",供 cainjector 把 CA 注入 webhook 配置。
cert-manager 还要访问 kube-apiserver(NetworkPolicy allow-kube-api-egress 放行 egress),webhook 也需要 API server 反向调用(见下)。
ACME 签发器
唯一的签发器是 letsencrypt-prod(ClusterIssuer),走生产 ACME endpoint https://acme-v02.api.letsencrypt.org/directory,账户邮箱 admin@yldm.tech,私钥存在 Secret letsencrypt-prod。它配了两类 solver:
| solver | 用途 | 说明 |
|---|---|---|
| HTTP-01 | 默认 | ingress.class: traefik。集群唯一的 IngressClass 是 traefik,若用 nginx-class solver ingress 会无人接管、HTTP-01 静默失败。 |
| DNS-01 | 指定 dnsZones | Cloudflare provider,凭 cloudflare-api-token,作用域 yldm.tech / yldm.ai / dunaifen.games / relaya.pro。 |
DNS-01 是签发通配符证书(如 *.relaya.pro)的唯一途径 —— HTTP-01 做不了通配符。preferredChain: "" 留空以避免频繁切链触发续订速率限制。
访问与监控
三个组件都只暴露 ClusterIP Service,无对外 Ingress:
cert-manager(controller):ClusterIP,端口 9402(tcp-prometheus-servicemonitor)。cert-manager-webhook:ClusterIP,443 → targetPort 9443(https),9402(metrics)。- ServiceMonitor
cert-manager(在applications/security/cert-manager/)按 labelapp.kubernetes.io/instance: cert-manager选中,30s 抓/metrics。NetworkPolicyallow-prometheus-scraping放行来自prometheusnamespace 对 9402 的 Ingress。
可用性兜底:
PodDisruptionBudgetcert-manager-webhook:minAvailable: 1,配 2 副本,节点 drain 时保证至少一个 webhook 在线。- NetworkPolicy
allow-cert-manager-webhook:放行所有来源(含 API server)对 webhook 9443 的 Ingress —— webhook 是准入校验链路,API server 必须能回调它。 - 三个组件各有一个
VerticalPodAutoscaler(updateMode: Recreate,区间 50m/64Mi ~ 500m/512Mi)自动调整 requests/limits。未配 HPA(控制器类组件按副本而非负载横向扩展)。
注意事项
webhook 是整条证书签发 / 校验链路的关键单点:webhook 全挂会阻断集群所有证书的签发与校验。所以它特意从 worker3 解绑(原 nodeSelector workload: infra)、升到 2 副本并加软反亲和分散到不同节点,以扛住单节点(如 worker3)宕机。
另外,MetalLB 的 validating webhook 用的自签证书也依赖 cert-manager(issuers-selfsigned + certificates-webhook)—— 这是 MetalLB manifest 偏离上游、带 --webhook-mode=enabled 的原因之一。改动 cert-manager 时留意这类下游依赖。
返回 infrastructure 总览