← 中文资源

简体中文版本

用 cert-manager 在 Ingress 终止 TLS

通过 ACME Issuer 申请证书并保存到 Secret,同时把所有明文 HTTP 请求重定向到 HTTPS,无需手工上传证书。

阅读英文原文

概述

手工上传证书相当于一个没有负责人、却带过期时间的凭证。cert-manager 把证书纳入 Ingress 清单:注解指定 issuer,tls 块指定 Secret,控制器负责签发与续期。第一次配置必须使用 ACME staging 端点,因为针对生产端点反复失败会消耗速率配额,导致真正的修复被阻塞数小时。staging 签发成功后再切换到生产 issuer。

步骤

  1. 创建 staging 的 ClusterIssuer:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    email: [email protected]
    privateKeySecretRef:
      name: letsencrypt-staging
    solvers:
      - http01:
          ingress:
            ingressClassName: nginx
  1. 在 Ingress 上添加签发注解、TLS 块与强制跳转:
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-staging
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  tls:
    - hosts:
        - app.example.com
      secretName: app-example-tls
  1. 观察 Certificate 与 Challenge 状态:
kubectl get certificate,challenge -n prod -o wide
  1. 验证证书链与 HTTP 跳转:
curl -sI http://app.example.com | head -3
echo | openssl s_client -connect app.example.com:443 -servername app.example.com 2>/dev/null \
  | openssl x509 -noout -issuer -dates

验证

Certificate 应为 Ready=True,Challenge 应为 Valid。外部访问 HTTP 时应返回 301/308 跳转到 HTTPS,TLS 握手返回的证书应由受信任 CA 签发,有效期约 90 天。切换生产 issuer 后应重新执行上述检查,确认数据面已经加载新证书,而不是只看 API 中的状态。

注意事项

  • Let’s Encrypt 有速率限制,必须先用 staging 验证流程。
  • HTTP-01 无法签发通配符证书,通配符需要 DNS-01 与 DNS 提供商凭证。
  • Challenge 路径必须可从公网访问,不能被跳转或鉴权拦截。
  • 续期成功但边缘未加载时,故障只会在旧证书过期时暴露。
  • 证书 Secret 应限制访问权限,避免私钥被其他命名空间读取。