Kubernetes环境cert-manager部署与应用

发布于2023-02-11,最后编辑于2024-10-25,全文约1852字,阅读时间约4分钟。

Kubernetes cert-manager Certificate Cloudflare X.509 Let's Encrypt ACME DNS-01 Ingress TLS

更新记录
  • 2023-04-14

    • cert-manager版本由v1.11.0更新至v1.11.1
  • 2023-06-02

    • cert-manager版本由v1.11.1更新至v1.12.1
  • 2023-06-24

    • cert-manager版本由v1.12.1更新至v1.12.2
  • 2023-08-08

    • cert-manager版本由v1.12.2更新至v1.12.3
  • 2023-10-19

    • cert-manager版本由v1.12.3更新至v1.13.1
  • 2023-11-20

    • cert-manager版本由v1.13.1更新至v1.13.2
  • 2024-01-01

    • cert-manager版本由v1.13.2更新至v1.13.3
  • 2024-02-10

    • cert-manager版本由v1.13.3更新至v1.14.2
  • 2024-09-30

    • cert-manager版本由v1.14.2更新至v1.15.3

概述

本文用于整理基于Kubernetes环境的cert-manager部署与应用,实现证书管理和Ingress启用TLS配置。

随着各相关组件版本的更新,笔者将在验证通过后对本文进行补充和更新,请参考更新记录

本次演练环境为Kubernetes集群环境,环境配置可参考笔者另一篇笔记《Kubernetes集群部署笔记》。

本次演练使用Traefik作为Ingress Controller实现,环境配置可参考笔者另一篇笔记《Kubernetes环境Traefik部署与应用》。

本次演练使用Cloudflare提供的DNS解析服务,并假定读者已经注册了Cloudflare并正确配置了网站。有关Cloudflare的配置和使用,请参考Cloudflare帮助中心或相关文档。

组件版本

配置过程

安装cert-manager

  • 参考官方文档,使用kubectl安装cert-manager,所有参数使用默认值,这将会把cert-manager安装至cert-manager命名空间。

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

配置Issuer和ClusterIssuer

  • 配置API Token

    本次演练使用Cloudflare提供的DNS解析服务,实现通过DNS-01质询方式申请证书,可根据需要替换为其他支持的DNS-01验证程序,或通过Webhook方式扩展cert-manager对其他DNS解析服务的支持。

    首先,登录Cloudflare控制面板,打开API Tokens页面,按照cert-manager文档中的说明,创建一个API Token,记录该API Token的值用于后续操作。

    1- Permissions
    2  - Zone - DNS - Edit
    3  - Zone - Zone - Read
    4- Zone Resources:
    5  - Include - All Zones
    
  • 创建IssuerClusterIssuer

    cert-manager提供两种用于签发证书的对象:IssuerClusterIssuer,简单地说,Issuer是命名空间级别的资源,无法用于处理跨命名空间的证书签发请求;ClusterIssuer是集群级别的资源,可以用于处理跨命名空间的证书签发请求。

    创建一个Issuer对象。

     1cat <<EOF | kubectl apply -f - > /dev/null
     2apiVersion: v1
     3kind: Secret
     4metadata:
     5  name: cloudflare-api-token-secret
     6  namespace: apps-choral
     7type: Opaque
     8stringData:
     9  api-token: '<REDACTED>' # 这里的值为[配置API Token]一节中创建的API Token值
    10
    11---
    12apiVersion: cert-manager.io/v1
    13kind: Issuer
    14metadata:
    15  name: cloudflare-acme-issuer
    16  namespace: apps-choral
    17spec:
    18  acme:
    19    email: '<REDACTED>'
    20    # 配置证书目录,演练环境使用Staging环境
    21    # server: https://acme-v02.api.letsencrypt.org/directory
    22    server: https://acme-staging-v02.api.letsencrypt.org/directory
    23    privateKeySecretRef:
    24      name: acme-issuer-account-key
    25    solvers:
    26    - dns01:
    27        cloudflare:
    28          apiTokenSecretRef:
    29            name: cloudflare-api-token-secret # 引用当前文档中创建的Secret名称
    30            key: api-token
    31EOF
    

    创建一个ClusterIssuer对象。

     1cat <<EOF | kubectl apply -f - > /dev/null
     2apiVersion: v1
     3kind: Secret
     4metadata:
     5  name: cloudflare-api-token-secret
     6  namespace: cert-manager # 这里配置为安装cert-manager资源的命名空间
     7type: Opaque
     8stringData:
     9  api-token: '<REDACTED>' # 这里的值为[配置API Token]一节中创建的API Token值
    10
    11---
    12apiVersion: cert-manager.io/v1
    13kind: ClusterIssuer
    14metadata:
    15  name: cloudflare-acme-cluster-issuer
    16spec:
    17  acme:
    18    email: '<REDACTED>'
    19    # 配置证书目录,演练环境使用Staging环境
    20    # server: https://acme-v02.api.letsencrypt.org/directory
    21    server: https://acme-staging-v02.api.letsencrypt.org/directory
    22    privateKeySecretRef:
    23      name: acme-issuer-account-key
    24    solvers:
    25    - dns01:
    26        cloudflare:
    27          apiTokenSecretRef:
    28            name: cloudflare-api-token-secret # 引用当前文档中创建的Secret名称
    29            key: api-token
    30EOF
    

配置Ingress TLS

可以通过手动创建或基于注解自动创建Certificate资源,cert-manager会自动管理签发证书并保存至指定的Secret对象中,并自动管理续期

  • 手动创建Certificate资源

    首选,创建一个Certificate对象,这会触发spec.issuerRef字段指定的IssuerClusterIssuer签发TLS证书,并保存至spec.secretName字段指定的Secret对象中。

     1cat <<EOF | kubectl apply -f - > /dev/null
     2apiVersion: cert-manager.io/v1
     3kind: Certificate
     4metadata:
     5  name: cert-local-choral-io
     6  namespace: apps-choral
     7spec:
     8  dnsNames:
     9  - 'local.choral.io'
    10  - '*.local.choral.io'
    11  issuerRef:
    12    kind: ClusterIssuer
    13    name: cloudflare-acme-cluster-issuer
    14  secretName: cert-local-choral-io
    15EOF
    

    证书签发成功后,配置Ingress使用指定的Secret实现TLS。

     1cat <<EOF | kubectl apply -f - > /dev/null
     2apiVersion: networking.k8s.io/v1
     3kind: Ingress
     4metadata:
     5  name: whoami
     6  namespace: apps-choral
     7  annotations:
     8    traefik.ingress.kubernetes.io/router.entrypoints: websecure
     9spec:
    10  tls:
    11    - secretName: cert-local-choral-io
    12  rules:
    13    - host: whoami.local.choral.io
    14      http:
    15        paths:
    16          - path: /
    17            pathType: Prefix
    18            backend:
    19              service:
    20                name: whoami
    21                port:
    22                  number: 80
    23EOF
    
  • 配置Ingress注解自动创建Certificate资源

    配置Ingress注解,使用cert-manager.io/issuer指定Issuer,或使用cert-manager.io/issuer指定ClusterIssuer,这会触发指定的IssuerClusterIssuer签发TLS证书,并保存至spec.tls[*].secretName字段指定的Secret对象中。

     1cat <<EOF | kubectl apply -f - > /dev/null
     2apiVersion: networking.k8s.io/v1
     3kind: Ingress
     4metadata:
     5  name: whoami
     6  namespace: apps-choral
     7  annotations:
     8    cert-manager.io/issuer: cloudflare-acme-issuer
     9    traefik.ingress.kubernetes.io/router.entrypoints: websecure
    10spec:
    11  tls:
    12    - hosts:
    13        - whoami.local.choral.io
    14      secretName: cert-local-choral-io
    15  rules:
    16    - host: whoami.local.choral.io
    17      http:
    18        paths:
    19          - path: /
    20            pathType: Prefix
    21            backend:
    22              service:
    23                name: whoami
    24                port:
    25                  number: 80
    26EOF
    

参考资料