cert-manager介绍

cert-manager概述

cert-manager 是 Kubernetes 里的证书自动化控制器(controller)。它通过 CRD(自定义资源)引入一套对象,从而实现基于 “声明式” 的方式管理证书生命周期:

流程大致为:

  1. 声明:需要某域名的证书(Certificate 资源)
  2. cert-manager 自动完成:
    1. 生成私钥
    2. 走 ACME 流程去 Let’s Encrypt 申请证书
    3. 完成域名验证(HTTP-01 或 DNS-01)
    4. 拿到证书后写入一个 Kubernetes Secret(kubernetes.io/tls)
    5. 快到期前自动续期、更新 Secret

Ingress-Nginx 引用这个 Secret,就能自动变 HTTPS 并跟随续期更新。

cert-manager 能够从多种证书颁发机构获取证书,包括:Let’s Encrypt、HashiCorp Vault、CyberArk Certificate Manager 以及私有 PKI。

涉及概念

使用 cert-manager 的时候主要有如下概念:
Issuer / ClusterIssuer:签发器,向谁申请/由谁签,用于指示 cert-manager 签发证书的方式。

  • Issuer 作用域是 namespace
  • ClusterIssuer 集群级(一般建议用它,所有 namespace 都能用)

提示:Issuer 与 ClusterIssuer 之间的区别是:Issuer 只能用来签发自身所在 namespace 下的证书,ClusterIssuer 可以签发任意 namespace 下的证书。

Certificate:证书申请单,要哪些域名、存到哪个 Secret、用哪个 Issuer,用于向 cert-manager 传递域名证书的信息、签发证书所需要的配置,以及对 Issuer/ClusterIssuer 的引用。
Order / Challenge:ACME 协议内部过程对象(一般无需手动创建)
Secret:最终落地的证书与私钥,kubernetes.io/tls 类型,被 Ingress 的 spec.tls[].secretName 引用。
Ingress:让 HTTPS 生效,Ingress-Nginx 读取指定的 TLS Secret,Secret 一更新,Ingress-Nginx 会自动加载(通常无需重启)。

免费证书签发原理

Let’s Encrypt 利用 ACME 协议校验域名的归属,校验成功后可以自动颁发免费证书。免费证书有效期只有90天,需在到期前再校验一次实现续期。使用 cert-manager 可以自动续期,即实现永久使用免费证书。校验域名归属的两种方式分别是 HTTP-01 和 DNS-01,校验原理可参考:使用 cert-manager 签发免费证书

cert-manager安装

manifest 方式安装

这种方式指所有资源(CustomResourceDefinitions 以及 cert-manager、cainjector 和 webhook 组件)均包含在单个 YAML 清单文件中。

[root@master01 ~]# mkdir cert-manager
[root@master01 ~]# cd cert-manager/
[root@master01 cert-manager]# CM_VER=v1.19.4
[root@master01 cert-manager]# kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/${CM_VER}/cert-manager.yaml

默认情况下,cert-manager 将被安装到 cert-manager 命名空间。

确认验证:
如下 cert-manager 、 cert-manager-cainjector 和 cert-manager-webhook 的 pod 均处于 Running 状态。其中 webhook 组件的成功启动时间可能略长于其他组件。

[root@master01 cert-manager]# kubectl get pods --namespace cert-manager
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-59976b9f8b-2q2b2              1/1     Running   0          3m4s
cert-manager-cainjector-689d8b44f5-gtvpp   1/1     Running   0          3m4s
cert-manager-webhook-58dcbfd978-pk92v      1/1     Running   0          3m4s

提示:更多安装参考: kubectl 安装 cert-manager

helm 方式安装

cert-manager 将 Helm 图表作为在 Kubernetes 和 OpenShift 上的首选安装方式。

cert-manager 作为 OCI Helm 图表提供,同时也发布于 Helm 仓库。
对于较新版本的 cert-manager,推荐使用 OCI Helm 图表。

OCI Helm 图表是官方来源,发布后即刻更新。而位于 https://charts.jetstack.io 的传统 HTTP Helm 仓库会在 OCI 图表发布几小时后更新。

  • 启用 OCI Helm Chart方式
[root@master01 cert-manager]# helm install \
  cert-manager oci://quay.io/jetstack/charts/cert-manager \
  --version v1.19.4 \
  --namespace cert-manager \
  --create-namespace \
  --set crds.enabled=true

[root@master01 cert-manager]# kubectl get pods --namespace cert-manager
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-746886b79c-g5twr              1/1     Running   0          3m27s
cert-manager-cainjector-5664b56fc6-npljq   1/1     Running   0          3m27s
cert-manager-webhook-7f644f6b8f-jcxvx      1/1     Running   0          3m27s

[root@master01 cert-manager]# helm -n cert-manager list
NAME            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
cert-manager    cert-manager    1               2026-03-05 15:28:37.385314815 +0800 CST deployed        cert-manager-v1.19.4    v1.19.4 
  • 采用 Helm repository方式
[root@master01 cert-manager]# helm repo add jetstack https://charts.jetstack.io --force-update      #添加仓库

[root@master01 cert-manager]# helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.19.4 \
  --set crds.enabled=true
  
[root@master01 cert-manager]# kubectl get pods --namespace cert-manager
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-746886b79c-l2ldj              1/1     Running   0          79s
cert-manager-cainjector-5664b56fc6-7w59h   1/1     Running   0          79s
cert-manager-webhook-7f644f6b8f-w9bnt      1/1     Running   0          78s
[root@master01 cert-manager]# helm -n cert-manager list
NAME            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
cert-manager    cert-manager    1               2026-03-05 15:32:53.389566373 +0800 CST deployed        cert-manager-v1.19.4    v1.19.4

提示:建议采用OCI Helm Chart方式,以便于及时获取最新版的版本。

提示:若需要修改helm安装的默认值,可参考:cert-manager,该说明包括了所有helm chart可配置的值。

验证自签名

完整验证安装成功与否的最佳方法是签发测试证书。
可在 cert-manager-test 命名空间中创建一个自签名签发者(Issuer)和一个证书(Certificate)资源。

[root@master01 cert-manager]# cat <<EOF > test-resources.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: cert-manager-test
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: test-selfsigned
  namespace: cert-manager-test
spec:
  selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: selfsigned-cert
  namespace: cert-manager-test
spec:
  dnsNames:
    - linuxsb.com
  secretName: selfsigned-cert-tls
  issuerRef:
    name: test-selfsigned
  privateKey:
    rotationPolicy: Always
EOF

[root@master01 cert-manager]# kubectl apply -f test-resources.yaml

[root@master01 cert-manager]# kubectl -n cert-manager-test get secret selfsigned-cert-tls
NAME                  TYPE                DATA   AGE
selfsigned-cert-tls   kubernetes.io/tls   3      6m6s
[root@master01 cert-manager]# kubectl -n cert-manager-test get certificate
NAME              READY   SECRET                AGE
selfsigned-cert   True    selfsigned-cert-tls   5m56s
[root@master01 cert-manager]# kubectl -n cert-manager-test describe certificate selfsigned-cert
# ……
Events:
  Type    Reason     Age   From                                       Message
  ----    ------     ----  ----                                       -------
  Normal  Issuing    6m2s  cert-manager-certificates-trigger          Issuing certificate as Secret does not exist
  Normal  Generated  6m2s  cert-manager-certificates-key-manager      Stored new private key in temporary Secret resource "selfsigned-cert-rwmgl"
  Normal  Requested  6m2s  cert-manager-certificates-request-manager  Created new CertificateRequest resource "selfsigned-cert-1"
  Normal  Issuing    6m2s  cert-manager-certificates-issuing          The certificate has been successfully issued

cert-manager Issuer 签发器

Issuer 签发器介绍

安装 cert-manager 后,首先需配置的是 Issuer 或 ClusterIssuer 。这些资源代表能够响应证书签名请求(CSR)的证书颁发机构(CA)。

cert-manager 自带多种内置证书签发者,均属于 cert-manager.io 分组。除内置类型外,还可安装外部签发者。内置与外部签发者处理方式相同,配置方法也相似。

使用 ClusterIssuer 资源类型时,ClusterIssuer 资源具有集群作用域。这意味着通过 secretName 字段引用 Secret 时,将在 Cluster Resource Namespace 中查找 Secret 资源。默认命名空间为 cert-manager ,但可通过 cert-manager-controller 组件的标志 --cluster-resource-namespace=my-namespace 进行修改。

当前已集成的签发器包括:Issuers 签发方

SelfSigned 自签名签发器

SelfSigned 发行者通常用于在本地引导 PKI(公钥基础设施),即本地内部私有环境。自签名签发者( SelfSigned )本身不代表证书颁发机构,而是表示证书将使用指定私钥"自行签署"。换言之,证书的私钥将被用于签署证书本身。

SelfSigned 创建

由于 SelfSigned 发行方不依赖任何其他资源,其配置最为简单。发行方规范中仅需包含 SelfSigned 配置段,无需其他设置。

SelfSigned Issuer 是最简单的 issuer 类型,不依赖外部系统(不像 ACME 要连 Let’s Encrypt、DNS、HTTP 验证),不依赖现有 CA Secret(不像 CA issuer 一开始就需要有个 CA Secret)。

Issuer:namespace 级。它引用的 Secret 也在同 namespace。
ClusterIssuer:集群级(不在任何 namespace)。但它要引用 CA 私钥的 Secret,Secret 又必须放在某个 namespace。
cert-manager 的约定是:ClusterIssuer 引用的 Secret 默认在 cert-manager namespace 。

[root@master01 cert-manager]# cat selfsigned-resources.yaml 
---
apiVersion: v1
kind: Namespace
metadata:
  name: test

---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: selfsigned-issuer
  namespace: test
spec:
  selfSigned: {}

---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: selfsigned-cluster-issuer           #集群级别的资源
spec:
  selfSigned: {}

[root@master01 cert-manager]# kubectl apply -f selfsigned-resources.yaml
[root@master01 cert-manager]# kubectl -n test get issuers.cert-manager.io -owide
NAME                READY   STATUS   AGE
selfsigned-issuer   True             13s
[root@master01 cert-manager]# kubectl get clusterissuers.cert-manager.io -owide
NAME                        READY   STATUS   AGE
selfsigned-cluster-issuer   True             30s
SelfSigned 构建 CA

CA(证书颁发机构):有一对固定的 CA 私钥/证书(Root/Intermediate),用它去给别的证书签名。被签发的证书链能追溯到这个 CA。
SelfSigned Issuer:对每一张证书,它用“这张证书自己的私钥”给“这张证书”签名——也就是自签名。

对于 “自签名证书” 最大的问题不是生成,而是信任分发:

  1. 签一张自签名证书给服务端用,客户端并不会自动信任它
  2. 必须把证书(或其 CA)分发到所有客户端/命名空间/系统信任库里

在生产环境中会涉及:信任库分发、轮换、吊销、灾备等一整套 PKI 运维。

因此官方的建议是:使用 SelfSigned “引导(bootstrap)出一个真正的 CA” ,然后对于每个需要自签名的证书,后续不使用 SelfSigned 自签,而是用 CA Issuer 去签发其它证书。

单纯使用 selfSigned 也可以实现自签名证书的创建,但每一张证书都是孤岛,客户端信任管理会更难,即:
selfSigned:每张证书都得单独信任(或 TOFU),轮换时更麻烦,
CA issuer:只要客户端信任“根 CA”,后续业务证书怎么换都行(链路更合理)。

所以 selfSigned 更像“临时/引导工具”,CA issuer 才是“自建 PKI 的最佳方式”。

相当于用 SelfSigned 只做第一步:生成一张“Root CA 证书”(自签名、isCA=true),把它保存成 Secret。
然后用这个 Root CA Secret 配一个 CA Issuer,后续所有业务证书都用 CA Issuer 去签(形成“同一个私有 CA”体系),这样就从“每张证书都自签”变成了“由统一 CA 签发”。相当于先构建一个CA,然后由CA去签名。

这是 SelfSigned 签发器的理想用例之一,即为私有 PKI 引导自定义根证书,包括配合 cert-manager CA 签发器使用。

以下 YAML 配置将创建 SelfSigned 签发器,签发根证书并使用该根证书作为 CA 签发器:

  • 命名空间级别

命名空间级别的 ca 的特点:

  • 资源放在 sandbox 里(示例先创建了 Namespace: sandbox)
  • 生成 Root CA 的 Certificate 也在 sandbox,产物 Secret 是:sandbox/root-secret
  • 最终创建的是 Issuer(不是 ClusterIssuer):kind: Issuer + spec.ca.secretName: root-secret,这个 my-ca-issuer 只能在 sandbox 这个 namespace 里被引用。

适用场景:你只想在某个 namespace 内部使用私有 CA,不打算全集群共享。

[root@master01 cert-manager]# vi selfsigned-root-ns.yaml
---
# 创建命名空间
apiVersion: v1
kind: Namespace
metadata:
  name: sandbox

---
# 创建集群级别的 SelfSigned Issuer(工具人)
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: selfsigned-issuer
spec:
  selfSigned: {}

---
# 用 SelfSigned Issuer 签一张 Root CA 证书
# cert-manager 生成 Root CA 的私钥
# 用 SelfSigned issuer 让这张 Root CA 证书“自签”
# 把 Root CA 证书+私钥 保存到 root-secret 这个 Secret
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: my-selfsigned-ca
  namespace: sandbox
spec:
  isCA: true
  commonName: my-selfsigned-ca
  secretName: root-secret
  privateKey:
    algorithm: ECDSA
    size: 256
    rotationPolicy: Always
  issuerRef:
    name: selfsigned-issuer
    kind: ClusterIssuer
    group: cert-manager.io

---
# 创建 CA Issuer(真正干活的 CA)
# 以后凡是引用这个 my-ca-issuer 的 Certificate
# 都会用 root-secret 里那对 CA 私钥/证书来签发
# 从此就有了一个“私有 CA”
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: my-ca-issuer
  namespace: sandbox
spec:
  ca:
    secretName: root-secret

[root@master01 cert-manager]# kubectl apply -f selfsigned-root-ns.yaml

[root@master01 cert-manager]# kubectl get clusterissuers.cert-manager.io
NAME                        READY   AGE
selfsigned-cluster-issuer   True    13m
selfsigned-issuer           True    31s
                   
[root@master01 cert-manager]# kubectl -n test get certificate
NAME               READY   SECRET        AGE
my-selfsigned-ca   True    root-secret   76s
  • 集群级别

也可使用 ClusterIssuer 通过 SelfSigned Certificate CA 为集群中任意位置的 Certificates 签名,请采用以下 YAML 配置(稍作修改):

集群级别的 ca 的特点:
不再需要 sandbox(因为目标是 ClusterIssuer)
Root CA 的 Secret 被放到 cert-manager namespace(通常默认):cert-manager/root-secret
最终创建的是 ClusterIssuer:kind: ClusterIssuer + spec.ca.secretName: root-secret,ClusterIssuer 不在任何 namespace,所以它引用的 secretName 默认会去 cert-manager namespace 找(这是 cert-manager 的约定/实现)。

适用场景:希望全集群任何 namespace 都能引用同一个 CA 来签证书(统一内部 PKI)。

[root@master01 cert-manager]# vim selfsigned-root-cl.yaml
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: selfsigned-issuer
spec:
  selfSigned: {}

---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: my-selfsigned-ca
  namespace: cert-manager
spec:
  isCA: true
  commonName: my-selfsigned-ca
  secretName: root-secret
  privateKey:
    algorithm: ECDSA
    size: 256
    rotationPolicy: Always
  issuerRef:
    name: selfsigned-issuer
    kind: ClusterIssuer
    group: cert-manager.io

---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: my-ca-issuer
spec:
  ca:
    secretName: root-secret

[root@master01 cert-manager]# kubectl apply -f selfsigned-root-cl.yaml

[root@master01 cert-manager]# kubectl get clusterissuers.cert-manager.io 
NAME                        READY   AGE
my-ca-issuer                True    32s
selfsigned-cluster-issuer   True    18m
selfsigned-issuer           True    5m28s
[root@master01 cert-manager]# kubectl -n cert-manager get certificate
NAME               READY   SECRET        AGE
my-selfsigned-ca   True    root-secret   46s

提示:使用 SelfSigned 证书的客户端无法信任这些证书,需要事先在客户端导入这些证书。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐