证书管理是HTTPS站点运维里最繁琐的环节,证书默认90天有效期,手动续期在服务器规模超过三台后基本不可维护。cert-manager是Kubernetes生态的事实标准证书控制器,通过CRD把证书申请、续期、注入Secret全流程声明式化,支持Let’s Encrypt、ZeroSSL及自建CA。配合Ingress的自动化签发,一个新域名从解析到HTTPS可访问可以在两分钟内完成。
cert-manager安装与ClusterIssuer配置方法
安装推荐Helm方式,便于版本管理与卸载:
helm repo add jetstack https://charts.jetstack.io
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set crds.enabled=true --version v1.15.3
安装后创建ClusterIssuer。Let’s Encrypt推荐HTTP-01与HTTP-01两种验证方式里选前者做通用签发,后者用于通配符证书:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ops@yourdomain.com
privateKeySecretRef:
name: letsencrypt-prod-account-key
solvers:
- http01:
ingress:
class: nginx
HTTP-01验证要求域名的80端口可从公网访问,cert-manager会自动创建一个临时Pod完成验证。如果集群前面有CDN或WAF,需要放行 /.well-known/acme-challenge/ 路径回源。签发通配符证书改用DNS-01,以Cloudflare DNS为例:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-dns
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ops@yourdomain.com
privateKeySecretRef:
name: letsencrypt-dns-account-key
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token
Cloudflare API Token需要Zone.DNS编辑权限,存入Secret后cert-manager通过它动态写入TXT记录验证域名所有权,验证完成自动清理记录。相比HTTP-01,DNS-01不依赖公网入口,适合内网K8s集群使用公网证书的场景。
Ingress自动签发证书的annotation触发方式
日常加域名最省事的方式是在Ingress上打annotation,cert-manager检测到后自动创建Certificate资源:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- api.yourdomain.com
secretName: api-yourdomain-tls
rules:
- host: api.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-svc
port:
number: 80
spec.tls段是触发点:指定了hosts与secretName且带cluster-issuer annotation,cert-manager就生成Certificate对象并走签发流程,证书写入名为api-yourdomain-tls的Secret,Ingress控制器热加载。这个方式缺点是证书与Ingress生命周期耦合,删除Ingress时cert-manager默认会清理证书资源。生产上更建议显式创建Certificate CR,把证书作为独立资产维护:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: api-yourdomain
spec:
secretName: api-yourdomain-tls
duration: 2160h # 90天
renewBefore: 720h # 到期前30天开始续期
dnsNames:
- api.yourdomain.com
issuerRef:
kind: ClusterIssuer
name: letsencrypt-prod
renewBefore默认是有效期的三分之二处开始续期,显式设置留出失败重试窗口。Let’s Encrypt有重复签发限速(同一证书一周内最多5次),duration不能自定义缩短,生产环境务必用生产端点。
证书签发失败排查与续期监控告警配置
签发失败的高频原因排第一位的是ACME challenge路径被拦截,第二是ClusterIssuer引用的Secret不存在。排查命令链:
# 1. 查看Certificate状态与事件
kubectl describe certificate api-yourdomain
# 看 Events 里 Ready 字段与报错信息
# 2. 追踪CertificateRequest(每1次申请一个CR)
kubectl get certificaterequests -o wide
kubectl describe certificaterequest <name>
# 3. 查看Order与Challenge状态
kubectl get orders,challenges -A
kubectl describe challenge <name>
# 报http01 challenge路径不可达时,检查Ingress/防火墙/CDN回源
监控方面,cert-manager暴露Prometheus指标,关键指标certmanager_controller_certificates_ready_status的0值持续时间就是告警条件。告警规则示例:
- alert: CertManagerCertNotReady
expr: certmanager_controller_certificates_ready_status{condition="False"} == 1
for: 1h
labels:
severity: warning
annotations:
summary: "证书 {{ $labels.namespace }}/{{ $labels.name }} 未就绪超过1小时"
配合检查证书实际到期时间的blackbox exporter做双保险,能覆盖cert-manager自身故障的情况。对于非K8s的裸机服务,可以用step-ca自建ACME服务器复用同一套流程,把内网数百张自签证书也纳入自动化续期,彻底告别人工更换证书的运维负担。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/certmanager-zheng-shu-zi-dong-hua-shi-zhan-letsencrypt-qian/