cert-manager可自动申请并续期let's encrypt证书,但需满足三个前提:正确安装cert-manager(crd须先于controller部署)、clusterissuer配置无误(http01需ingress响应验证路径,dns01需dns api权限)、ingress资源严格声明tls且域名可被acme验证。

能自动申请并续期 Let's Encrypt 证书,前提是 cert-manager 已正确安装、ClusterIssuer 配置无误、Ingress(或 Gateway)资源声明了 TLS 且域名可被 ACME 验证——三者缺一不可。漏掉任意一环,Certificate 状态就会卡在 Pending 或报 Failed。
cert-manager 安装必须分两步:CRDs 先于 controller
很多人用 Helm 或 YAML 一键部署却失败,根源在于 CRD 资源没提前注册。Kubernetes 不识别 Certificate、ClusterIssuer 这些自定义类型,controller 就会静默退出。
- 先手动应用 CRDs:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.0/cert-manager.crds.yaml(注意版本要和后续 controller 匹配) - 再部署 controller,推荐 Helm:
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --version v1.17.0 - 验证是否就绪:
kubectl -n cert-manager get pod—— 所有 Pod 必须是Running,且READY为1/1 - 别跳过这步:
kubectl get crd | grep cert-manager应该输出至少 6 行,含certificates.cert-manager.io等
ClusterIssuer 的 solver 类型决定你能不能过验证
http01 和 dns01 不是随便选的。选错会导致 ACME 挑战永远失败,日志里反复出现 Waiting for HTTP-01 challenge propagation 或 No matching hosted zone found。
-
http01要求:你的 Ingress 控制器(如 nginx-ingress)必须能响应/.well-known/acme-challenge/xxx请求,且该路径不能被重写、拦截或限流 -
dns01要求:你得有 DNS 提供商 API 权限(如阿里云alidns-webhook、AWS Route53),并在ClusterIssuer中正确引用 secret(如accessKeyIDSecretRef) - 测试阶段务必用 Let's Encrypt staging 地址:
https://acme-staging-v02.api.letsencrypt.org/directory,避免触发生产环境速率限制 -
privateKeySecretRef.name是 cert-manager 自动生成私钥的 Secret 名,不用提前创建;但 DNS webhook 场景下,你得自己建好带密钥的 secret
Ingress 注解和 tls 字段必须严格匹配 issuer 和域名
常见错误是注解写错名字、secretName 冲突、或 hosts 域名没对齐——哪怕多一个空格或少一个 www.,证书都不会签发。
- 注解必须是
cert-manager.io/cluster-issuer: "letsencrypt-prod"(注意引号和大小写,cluster-issuer不是issuer) -
spec.tls[].hosts和spec.rules[].host必须完全一致,且都指向你已解析到集群的公网域名 -
secretName是证书最终存入的 Secret 名,它由 cert-manager 创建,不能和已有 Secret 同名(否则会拒绝更新) - 如果你用的是 Kubernetes 1.22+,确保 Ingress API 版本是
networking.k8s.io/v1,旧版extensions/v1beta1已废弃
排查证书卡住时,优先看 Certificate 和 Challenge 资源状态
别只盯着 Ingress 或 Secret——真正决定证书成败的是 Certificate 和它触发的 Challenge 对象。
- 查证书状态:
kubectl get certificate -A,状态不是Ready就说明流程中断 - 看详情:
kubectl describe certificate <name> -n <ns></ns></name>,Events 里通常有明确提示,比如Failed to verify challenge - 进一步查挑战:
kubectl get challenges -A,挑出状态为Pending或Invalid的,再describe它,里面会显示 ACME 错误码(如urn:ietf:params:acme:error:dns) - 如果用了
dns01,检查对应 DNS 提供商控制台,确认 cert-manager 是否成功添加了 TXT 记录(记录名类似_acme-challenge.example.com)
最易被忽略的一点:Let’s Encrypt 要求域名在公网可解析且权威 DNS 服务器能返回正确的 TXT 或 HTTP 响应——本地 hosts 修改、内网 DNS、或 CDN 缓存未刷新,都会让验证失败。调试时,直接用 dig 或 curl -v http://example.com/.well-known/acme-challenge/test 验证通路,比反复改 YAML 更快。











