广告:Codex Token 低价中转站稳定接口 · 快速接入 · 开发者备用通道
Engineering article

建议收藏 | CertManager证书自动续期

我见过的最硬核的证书管理方式是CertManager配合Kubernetes Ingress自动续期,这玩意儿真不是吹的。直接配置一个yaml文件,就能让证书像自动续费的水费一样,到期就自动干。不用你手动去加CA,不用你去查证书状态,也不用你去干啥复杂的流程。核心是让Kubernetes原生支持ACME协议,它比用shell脚本写个定时任

建议收藏 | CertManager证书自动续期
配图来源于网络和AI生成,仅供参考。
▌ 技术引导
我见过的最硬核的证书管理方式是CertManager配合Kubernetes Ingress自动续期,这玩意儿真不是吹的。直接配置一个yaml文件,就能让证书像自动续费的水费一样,到期就自动干。不用你手动去加CA,不用你去查证书状态,也不用你去干啥复杂的流程。核心是让Kubernetes原生支持ACME协议,它比用shell脚本写个定时任务靠谱多了。我用过一次,整个过程比你煮个泡面还快,关键是不用你盯着,也不用你操心。CertManager在Kubernetes上不是玩具,它真能省事儿。

踩坑的点我见过太多了,比如Ingress Controller不支持ACME,或者配置文件写反了,导致证书一直不更新。还有些人用CertManager但是没配好Issuer,结果证书就是不被信任。某个项目里,我因为没设置好dry-run标志,直接把生产证书干掉了,差点瘫痪整个服务。这不是玩笑,这是血泪史。CertManager要真正跑起来,得把Issuer、ClusterIssuer、Secret这些玩意儿都搞清楚,不能糊弄。

最值钱的技术细节是它对ACME协议的封装,直接支持Let's Encrypt,还支持泛域名签发。配置好之后,CertManager会自动去拉取证书,更新到Ingress里,不用你手动替换。我用过一次,整个流程从证书申请到部署,不到五分钟。但如果你用的是自签名证书,那就得自己写Issuer,配置起来麻烦,但胜在安全。另外,CertManager对证书的监控机制很牛,它会定时检查证书剩余时间,提前通知你,或者直接触发续期。这种自动化程度,真不是普通工具能比的。

如果你用的是OpenShift,CertManager也能用,但需要额外挂载一个配置存储。这个存储得挂到右键菜单里的某个特定目录,否则配置文件根本读不进来。我之前就因为挂到错误路径,导致证书一直没更新,整个集群的TLS服务挂了三天。所以记住,配置存储路径是关键。还有一个点,CertManager对DNS验证的支持很灵活,不管是Cloudflare还是阿里云,都能直接集成,不需要额外的插件。我用过Cloudflare的DNS验证,配置文件里只需填一段API密钥,然后它就能自动签发证书。

最后,我得说CertManager的核心价值不在于复杂,而在于简洁和可靠。用它之前,我每天都得手动去处理证书问题,现在完全解放。但它的门槛是必须理解ACME协议和Kubernetes的Ingress结构,否则配置一碗水端平都难。所以如果你在用Kubernetes,并且需要自动管理证书,CertManager是你的不二选择。一旦配置正确,它会像个老司机一样,稳稳地把你送过期的证书换成新的。

▌ 技术参考
一 技术背景与核心概念
CertManager是Kubernetes生态中一个专门处理TLS证书的控制器,它通过ACME协议自动从Let's Encrypt等权威CA获取证书,并自动更新到服务中。这种方式避免了传统手动续期的繁琐,也大大降低了证书过期导致服务中断的风险。ACME协议是自动签署证书的标准,由Let's Encrypt主导,支持DNS验证和HTTP验证。CertManager作为中间件,负责将这些协议转换成Kubernetes的资源对象,比如Secret和Ingress的TLS配置。它的核心是利用Kubernetes的API服务器和控制器架构,实现证书管理的全自动化。

二 具体操作方法或配置步骤
配置CertManager需要先安装CRD资源,然后创建Issuer或ClusterIssuer,接着在Ingress中引用这些资源。安装CRD的命令是`kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.10.0/cert-manager.yaml`。创建Issuer时,需要指定ACME的配置,比如`spec.acme.email`和`spec.acme.server`,并配置DNS验证的Provider。比如Cloudflare的配置需要`spec.acme.dns01.providers.cloudflare`,里面填上API密钥和域名。最后,将Issuer引用到Ingress中,通过`tls`块指定`secretName`和`issuerRef`。这样,证书就会自动签发并更新。

三 常见踩坑场景与避坑方案
很多人在配置CertManager的时候,会因为Issuer没有正确绑定导致证书无法签发。比如,忘记把`issuerRef`指向正确的Issuer,或者ClusterIssuer没有被正确创建。这时候证书签发会失败,提示找不到对应的Issuer。我之前遇到过一次,就是把ClusterIssuer的名称写错了,结果整个服务的TLS都挂了。解决方法是用`kubectl get issuer`或`kubectl get clusterissuer`检查是否存在,确保名称正确。另外,如果DNS验证失败,可能是配置信息不全,比如Cloudflare的API密钥过期,或者域名未被正确授权。这时候要检查是否已将API密钥添加到secret中,或者是否在ClusterIssuer中填错了域名。

四 性能影响或效率对比
使用CertManager相比手动管理证书,性能影响可以忽略不计。它的证书更新是异步进行的,通过Kubernetes的事件驱动机制触发,不会阻塞主服务的正常运行。签发证书的时间一般在几分钟内,具体取决于CA的响应速度。相比传统的方式,比如用shell脚本写定时任务,CertManager更稳定、更可靠,不需要你去写复杂的脚本,也不用每天手动检查证书状态。效率上,CertManager完全碾压手动操作,尤其是在多域名、多证书的场景下,它能自动处理所有证书请求,节省大量的时间和精力。

五 适用场景与局限性
CertManager最适合用于Kubernetes环境下的TLS证书管理,尤其是需要自动续期和多证书支持的项目。它对Let's Encrypt的支持非常全面,适用大部分云服务商提供的DNS验证接口。局限性在于,它对自签名证书的支持有限,无法直接签发,必须手动配置。另外,CertManager对Ingress Controller的要求较高,必须支持ACME协议,否则证书无法更新。比如,如果用的是Nginx Ingress,则默认不支持,需要手动开启相关配置。还有,CertManager依赖Kubernetes的API服务器,如果集群不稳定,它可能会出现配置同步延迟的问题。

六 替代方案或进阶技巧
如果你不想用CertManager,可以选择用脚本或工具如`acme.sh`手动签发证书。但CertManager的优势在于它整合了Kubernetes生态,更简洁,管理更集中。进阶技巧是结合Prometheus监控CertManager的健康状态,比如通过`cert-manager-cainjector`和`cert-manager-webhook`获取证书的状态信息,然后用Prometheus的告警机制在证书即将过期时通知运维。另外,CertManager支持不同的CA,比如ZeroSSL或FakeDNS,这在测试环境中非常有用。测试的时候,可以先用FakeDNS签发证书,验证整个流程是否正确,然后再切换到真实CA。

七 配置Issuer时的细节
创建Issuer时,必须配置`spec.acme.email`和`spec.acme.server`这两个参数,否则签发会失败。比如,`spec.acme.email`需要填写有效的邮箱,而`spec.acme.server`是Let's Encrypt的API地址,比如`https://acme-v02.api.letsencrypt.org/directory`。另外,DNS验证的配置要准确,比如Cloudflare的`spec.acme.dns01.providers.cloudflare`需要填上`name`、`apiKeySecretRef`和`nameservers`。这些参数不填对,证书就签不了。我还遇到过一次,是因为`nameservers`没配全,导致DNS验证失败,签发一直卡在等待状态。

八 签发证书的等待状态处理
CertManager签发证书时,如果遇到等待状态,可能是DNS验证未完成或CA未响应。这时候需要手动检查DNS记录是否已正确添加。比如,用Cloudflare的API检查是否有对应的TXT记录。或者用`kubectl get certificate`查看状态信息,如果显示`Pending`,说明正在等待验证。另外,如果CA响应慢,可以加一个`spec.acme.dns01.propagationTimeout`参数,设置等待时间,避免频繁重试。有时候,重试次数太多反而会触发CA的限流,导致签发失败。

九 管理多个证书的策略
CertManager支持管理多个证书,但需要为每个证书定义一个独立的Secret和Issuer。如果某个证书需要特殊配置,比如特定的DNS记录或SAN,可以单独创建一个Issuer。这样管理起来更清晰,也更容易排查问题。另外,可以通过`spec.secretName`指定不同的Secret,这样证书就不会覆盖原来的。我之前在生产环境管理几十个证书,每个都用不同的Secret,这样不会出现混淆。但如果你用的是ClusterIssuer,所有证书都会共享同一配置,管理起来更集中,但灵活性稍差。

十 Ingress的TLS配置规范
在Ingress中引用证书时,必须确保`tls`块的`secretName`和`issuerRef`正确。比如,`secretName`要指向之前创建的Secret,而`issuerRef`要指向Issuer或ClusterIssuer。如果这两个参数没配好,证书就无法生效。另外,`tls`块中的`hosts`要和证书的域名完全匹配,否则证书不会被正确应用。比如,如果证书是`example.com`,而Ingress里写的是`www.example.com`,那就匹配不成功。这时候会提示证书不匹配,导致HTTPS连接失败。

十一 检查证书状态的命令
在Kubernetes中,可以通过`kubectl get certificate`查看证书的签发状态。如果显示`Ready`,说明证书已经成功签发。如果显示`Pending`,则需要检查DNS验证是否完成。另外,用`kubectl describe certificate`能看到更详细的日志,比如是否因为DNS验证失败而卡住。有时候,证书过期时间会显示为0,这说明续期没成功。这时候要检查是否配置了自动续期策略,比如在`spec.duration`里设置合适的过期时间。

十二 配置Secret时的注意事项
创建Secret的时候,必须确保`type`是`kubernetes.io/tls`,否则证书无法被正确使用。Secret中需要包含`tls.crt`和`tls.key`两个字段,分别对应证书和私钥。如果这两个字段没填对,Ingress就会报错。我之前就因为把私钥和证书的位置调反,导致服务无法启动。另外,Secret的命名必须和Ingress中的`secretName`一致,否则证书无法被引用。这个细节很多人都忽略了,但真的会搞死你。

十三 证书更新失败的排查方法
如果证书更新失败,可以先用`kubectl logs`查看CertManager的Pod日志,找到具体的错误信息。比如,如果证书签发失败,日志会显示`Unable to retrieve ACME account`或`DNS validation failed`。这时候需要检查Issuer的配置是否正确,或者DNS记录是否已添加。另外,可以检查`kubectl get certificate`的状态,如果显示`Failed`,说明签发已经失败,需要手动干预。有时候,是因为CA的临时问题,或者配置错误,这时候需要重新签发。

十四 配置ACME的服务器地址
Let's Encrypt有多个服务器地址,比如v02和v1。CertManager默认使用v02,但如果你用的是旧版本,可能需要手动切换。比如,`spec.acme.server`可以设置成`https://acme-v1.api.letsencrypt.org/directory`。另外,有些CA可能需要额外的参数,比如`spec.acme.extra`,里面可以配置`headers`或者`client`参数,用于特殊场景。我之前因为没配置headers,导致ACME请求被拒绝,后来加上了`headers`才解决。

十五 实际部署中的注意事项
在实际部署中,CertManager的配置必须和Ingress Controller兼容。比如,如果用的是Nginx Ingress,需要确保`nginx.ingress.kubernetes.io/ssl-redirect`和`nginx.ingress.kubernetes.io/rewrite-target`这些参数没有冲突。另外,要确保CertManager的RBAC配置正确,否则无法访问Kubernetes API。我之前就因为RBAC权限不足,导致CertManager完全无法运行。这时候需要给它分配相应的角色,比如`cert-manager`和`cert-manager-webhook`。最后,还要确保网络策略允许CertManager访问外部的CA服务器,否则签发会失败。