WEBKT

Kubernetes Ingress HTTPS自动化:Cert-Manager与Let's Encrypt实践指南

80 0 0 0

你好,SRE同行!

我理解你刚接手一个Kubernetes集群,发现大量服务Ingress缺乏HTTPS配置,老板又要求所有对外服务必须走HTTPS,这确实是个常见的挑战。手工管理证书不仅效率低下,而且极易出错,特别是证书的存储、分发和自动续期。

别担心,在Kubernetes生态中,我们有非常成熟的工具来自动化这一过程。今天,我将带你通过一个实用的方法,利用 Cert-Manager 结合 Let's Encrypt 实现Kubernetes Ingress HTTPS证书的自动化管理,彻底解决你的困扰。

为什么选择 Cert-Manager 和 Let's Encrypt?

  • Cert-Manager:Kubernetes原生证书管理工具,能够自动化地从各种CA(如Let's Encrypt、Vault等)获取、续订和管理TLS证书。它将证书以Secret的形式存储在Kubernetes集群中,供Ingress Controller或其他应用使用。
  • Let's Encrypt:一个免费、开放、自动化的证书颁发机构(CA),提供被所有主流浏览器信任的TLS证书。它的ACME协议非常适合自动化集成。

前提条件

  1. 一个运行中的Kubernetes集群。
  2. 已安装并配置好Ingress Controller,例如Nginx Ingress Controller或Traefik。确保你的Ingress Controller能够正确处理流量并路由到后端服务。
  3. 一个或多个可解析到Ingress Controller外部IP/域名的域名(例如:your-service.example.com)。

实践步骤:自动化部署与管理HTTPS证书

步骤 1:安装 Cert-Manager

Cert-Manager 的安装非常简单,推荐使用 Helm。

# 1. 添加 cert-manager Helm 仓库
helm repo add jetstack https://charts.jetstack.io
helm repo update

# 2. 安装 cert-manager CRDs(Custom Resource Definitions)
# 注意:v1.7.0+ 版本需要手动安装CRDs,或者使用 helm install --set installCRDs=true
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.crds.yaml

# 3. 安装 cert-manager 到 cert-manager 命名空间
# 请根据你的集群版本选择合适的 cert-manager 版本
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.13.2 # 替换为你想要安装的版本

安装完成后,你可以通过以下命令检查 cert-manager Pods 是否正常运行:

kubectl get pods -n cert-manager
# 应该看到 cert-manager, cert-manager-webhook, cert-manager-cainjector 三个 Pod 处于 Running 状态

步骤 2:配置 ClusterIssuer 或 Issuer

IssuerClusterIssuer 是 Cert-Manager 用来表示证书颁发机构的资源。Issuer 作用于特定命名空间,而 ClusterIssuer 作用于整个集群。对于需要跨多个命名空间共享证书的场景,ClusterIssuer 是更好的选择。

这里我们使用 Let's Encrypt 的 HTTP-01 挑战类型,因为它最常用且易于配置,只要你的 Ingress Controller 能正常访问外部网络。

2.1 创建 Let's Encrypt Staging ClusterIssuer(用于测试)

建议先使用 Let's Encrypt Staging 环境进行测试,以免触及生产环境的速率限制。

# cert-manager-staging-clusterissuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    # 邮箱用于接收证书相关的通知,非常重要
    email: your-email@example.com
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      # 用于存储 ACME 账户密钥的 Secret
      name: letsencrypt-staging-private-key
    solvers:
    - http01:
        ingress:
          class: nginx # 替换为你的 Ingress Controller 名称,例如:nginx, traefik, gce

保存为 cert-manager-staging-clusterissuer.yaml 并应用:

kubectl apply -f cert-manager-staging-clusterissuer.yaml

2.2 创建 Let's Encrypt Production ClusterIssuer(用于生产)

当测试通过后,你可以创建生产环境的 ClusterIssuer

# cert-manager-production-clusterissuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    email: your-email@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-prod-private-key
    solvers:
    - http01:
        ingress:
          class: nginx # 替换为你的 Ingress Controller 名称

保存为 cert-manager-production-clusterissuer.yaml 并应用:

kubectl apply -f cert-manager-production-clusterissuer.yaml

检查 ClusterIssuer 状态:

kubectl get clusterissuer letsencrypt-staging -o yaml
# 确保 Status.Conditions 中 Type: Ready 的状态为 True

步骤 3:更新 Ingress 资源以请求 HTTPS 证书

现在,你可以修改现有的 Ingress 资源,或创建新的 Ingress,让 Cert-Manager 为其自动签发证书。

# my-service-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-service-ingress
  annotations:
    # 指定使用哪个 ClusterIssuer 来签发证书
    cert-manager.io/cluster-issuer: letsencrypt-staging # 测试阶段用 staging,生产阶段改为 letsencrypt-prod
    # 强制将 HTTP 请求重定向到 HTTPS (Nginx Ingress Controller 特有)
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  ingressClassName: nginx # 确保指定了你的 Ingress Class
  tls:
  - hosts:
    - your-service.example.com # 你的域名
    secretName: your-service-tls # Cert-Manager 会将证书存储到这个 Secret
  rules:
  - host: your-service.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-backend-service # 你的后端服务名称
            port:
              number: 80 # 你的后端服务监听的端口

关键点解释:

  • cert-manager.io/cluster-issuer: letsencrypt-staging:这个 annotation 告诉 Cert-Manager 哪个 ClusterIssuer 负责为这个 Ingress 签发证书。
  • tls 部分:
    • hosts:指定需要 HTTPS 保护的域名。
    • secretName:Cert-Manager 会把签发到的证书(包括私钥和公钥)以 kubernetes.io/tls 类型的 Secret 存储在这个名称下。Ingress Controller 会自动加载这个 Secret 来启用 HTTPS。

保存为 my-service-ingress.yaml 并应用:

kubectl apply -f my-service-ingress.yaml

步骤 4:验证证书签发状态

应用 Ingress 后,Cert-Manager 会自动为你创建 CertificateOrder 资源来管理证书签发流程。

# 查看 Certificate 资源
kubectl get certificate

# 查看 Order 资源(会显示证书签发过程中的挑战状态)
kubectl get order

# 查看 Challenge 资源(会显示 ACME 挑战的具体信息)
kubectl get challenge

Certificate 资源的状态显示 ReadyTrue 时,表示证书已成功签发并存储在 your-service-tls 这个 Secret 中。

kubectl get secret your-service-tls -o yaml
# 你会看到 base64 编码的 tls.crt 和 tls.key

步骤 5:访问服务验证 HTTPS

现在,通过浏览器访问 https://your-service.example.com,你应该能看到浏览器地址栏显示安全连接(小绿锁),并且证书信息应该是由 Let's Encrypt 签发的。

证书存储、分发与自动续期

  • 证书存储:Cert-Manager 成功获取证书后,会将其存储在一个 Kubernetes Secret 中(例如上面的 your-service-tls)。这个 Secret 类型为 kubernetes.io/tls,包含 tls.crttls.key 两个数据字段。
  • 证书分发:当 Ingress Controller 检测到 Ingress 资源中指定了 tls 部分以及对应的 secretName 后,它会自动从这个 Secret 中读取证书数据,并将其配置到其代理服务器(如Nginx或Envoy)中,从而启用 HTTPS。这个过程对你来说是透明的。
  • 自动续期:这是 Cert-Manager 最强大的功能之一。默认情况下,Cert-Manager 会在证书到期前约30天自动尝试续订。它会重新执行 ACME 挑战流程,获取新的证书,并更新对应的 Secret。由于 Ingress Controller 通常会监听这些 Secret 的变化,所以证书更新后,服务通常不需要手动干预就能无缝切换到新证书,实现了真正的自动化。

最佳实践与注意事项

  1. 先用 Staging,后用 Production:始终先在 letsencrypt-staging 环境测试你的配置,确保一切正常后再切换到 letsencrypt-prod。生产环境的 Let's Encrypt 有严格的速率限制,频繁失败可能导致暂时无法签发证书。
  2. DNS-01 挑战:如果你的 Ingress Controller 无法直接暴露 HTTP-01 挑战所需的 .well-known/acme-challenge 路径,或者你需要签发泛域名证书(例如 *.example.com),你就需要使用 DNS-01 挑战。这通常需要 Cert-Manager 能够与你的DNS服务提供商(如阿里云DNS、腾讯云DNS、AWS Route 53等)集成,通过API修改DNS记录来验证域名所有权。
  3. 监控证书状态:虽然 Cert-Manager 会自动续期,但作为 SRE,监控其健康状况仍是必要的。你可以设置告警,例如当 Certificate 资源的 Ready 状态长时间不是 True,或者其 notAfter 字段显示证书即将过期时。
  4. Secret 安全:存储证书的 Secret 是敏感信息,确保对这些 Secret 设置适当的 RBAC 权限,限制只有必要的服务账户才能访问。
  5. Ingress Controller 配置:确认你的 Ingress Controller 支持 networking.k8s.io/v1 版本的 Ingress 资源,并正确配置了 ingressClassName

通过上述步骤,你不仅能满足老板对HTTPS的要求,还能建立一套健壮、自动化的证书管理流程,大大提升运维效率和系统安全性。祝你顺利!

K8S运维老兵 KubernetesHTTPS

评论点评