Skip to content

HTTPS 与 cert-manager 证书自动化

手工维护证书(openssl 生成、kubectl create secret tls)不适合多域名长期运维。cert-manager 通过与 Let's Encrypt 集成,实现证书的自动申请、自动续期、自动注入 Secret

工作原理

Ingress(带注解) → cert-manager → Let's Encrypt 校验域名 → 签发证书 → K8s Secret → Traefik 加载

证书默认 90 天有效,cert-manager 会在到期前 30 天自动续期,全程无需人工干预。

安装 cert-manager

使用官方静态清单安装:

bash
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.21.1/cert-manager.yaml

# 等待就绪
kubectl -n cert-manager rollout status deploy/cert-manager --timeout=120s
kubectl -n cert-manager get pods

国内服务器注意

cert-manager 镜像来自 quay.io,国内拉取较慢(首次约 30~40 秒)。首次签发时 solver 镜像也是从 quay.io 拉取,可能出现短暂 503,属正常现象。

创建 ClusterIssuer

ClusterIssuer 是集群级别的证书签发方配置:

yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: your-email@example.com          # 到期提醒邮箱
    privateKeySecretRef:
      name: letsencrypt-prod-key
    solvers:
      - http01:
          ingress:
            ingressClassName: traefik

校验方式选型

方式原理适用
HTTP-01访问 http://域名/.well-known/acme-challenge/<token>公网可访问 80 端口
DNS-01写入 TXT 记录 _acme-challenge.域名泛域名、80 端口不可达

本环境使用 HTTP-01(域名已解析到公网 IP,80 由 Traefik 提供)。

给 Ingress 配置 TLS

只需在 Ingress 上加两处:

yaml
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod   # ① 触发签发
spec:
  tls:
    - hosts:
        - docs.ljdou.cn
      secretName: docs-ljdou-cn-tls                     # ② 证书存放的 Secret

cert-manager 会创建 docs-ljdou-cn-tls Secret(类型 kubernetes.io/tls),Traefik 自动加载。

状态查看

bash
# 查看证书状态(READY=True 即签发成功)
kubectl get certificate -A

# 查看签发订单与挑战过程
kubectl get order,challenge -A

# 查看证书详情
kubectl describe certificate docs-ljdou-cn-tls -n default

常见问题

1. 国内服务器 HTTP-01 失败

报错特征:

During secondary validation: ...: Timeout during connect (likely firewall problem)

原因:Let's Encrypt 会从多个网络视角校验(多视角校验),部分海外校验点到国内服务器的 80 端口连通性不稳定。

应对:

  • 优先改用 DNS-01(无入站连接要求,最稳)
  • 或重试(cert-manager 会自动退避重试)
  • 首次失败常因 solver 镜像未拉取完成,重试即可

2. 证书一直 False

bash
kubectl describe challenge <name> -n <ns>   # 查看具体失败原因
kubectl logs -n cert-manager deploy/cert-manager --tail=50

3. 多个域名合并一张证书

同一 Ingress 的 tls.hosts 写多个域名即可(SAN 证书):

yaml
tls:
  - hosts:
      - ljdou.cn
      - www.ljdou.cn
    secretName: ljdou-cn-tls

基于 VitePress 构建