055.Kubernetes cert-manager安装及签发器介绍
cert-manager是Kubernetes的证书自动化控制器,通过CRD实现声明式证书管理。它支持从Let's Encrypt等机构自动获取、续期证书,并将证书存储为Kubernetes Secret供Ingress使用。核心概念包括Issuer/ClusterIssuer(证书签发器)和Certificate(证书申请)。安装方式支持manifest单文件部署和Helm(推荐OCI方式),默
文章目录
cert-manager介绍
cert-manager概述
cert-manager 是 Kubernetes 里的证书自动化控制器(controller)。它通过 CRD(自定义资源)引入一套对象,从而实现基于 “声明式” 的方式管理证书生命周期:
流程大致为:
- 声明:需要某域名的证书(Certificate 资源)
- cert-manager 自动完成:
- 生成私钥
- 走 ACME 流程去 Let’s Encrypt 申请证书
- 完成域名验证(HTTP-01 或 DNS-01)
- 拿到证书后写入一个 Kubernetes Secret(kubernetes.io/tls)
- 快到期前自动续期、更新 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:对每一张证书,它用“这张证书自己的私钥”给“这张证书”签名——也就是自签名。
对于 “自签名证书” 最大的问题不是生成,而是信任分发:
- 签一张自签名证书给服务端用,客户端并不会自动信任它
- 必须把证书(或其 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 证书的客户端无法信任这些证书,需要事先在客户端导入这些证书。
更多推荐
所有评论(0)