文章目录
-
- [Requesting Certificates介绍](#Requesting Certificates介绍)
- [ingress 注解](#ingress 注解)
-
- ingress注解方案
- ingress-shim工作机制
- ingress配置讲解
- 请求issuer注解
- [ACME HTTP01注解](#ACME HTTP01注解)
- [Certificate 通用字段映射类注解](#Certificate 通用字段映射类注解)
- [Certificate 私钥字段映射类注解](#Certificate 私钥字段映射类注解)
- 注解使用建议
Requesting Certificates介绍
证书申请介绍
当配置好 Issuer 后,即可开始正式申请证书,当前通过 cert-manager 申请证书有以下几种常见场景和方法:
- ingress 集成:为集群中的 Ingress 资源提供安全通信;
- OpenFaaS 函数:使用 cert-manager 为 OpenFaaS 服务提安全通信;
- 与 Garden 集成:Garden 是用于开发 Kubernetes 应用程序的开发者工具,提供对 cert-manager 集成支持。
- Knative 集成:使用可信 HTTPS 证书为 Knative 服务提供安全通信;
- Istio 网关集成:在 Kubernetes 中使用 cert-manager 保护 Istio 网关,提供安全通信。
提示 :本文主要关注和 ingress 的集成,其他更多方案参考Requesting Certificates 。
在 cert-manager 里,Certificate 资源不是最终的证书文件本身,而是一个"人类可读的证书申请声明"。
通俗的理解:
- 告知 cert-manager,需要哪个域名的证书
- 用哪个 Issuer/ClusterIssuer 去签发
- 证书放到哪个 Secret
- 证书要什么用途、什么主题、什么有效期
- 私钥如何生成、是否轮换
cert-manager 再根据这个声明进行下一步操作:
- 生成私钥
- 生成 CertificateRequest
- 调用指定的 Issuer 去签发,通过
certificate.spec.issuerRef - 把签发结果写回 Secret
- 后续自动续期
即Issuer 决定"谁给签发",Certificate 决定"需什么证书"。
- Issuer / ClusterIssuer:签发能力提供者
- Certificate:证书申请模板
- Secret:最终落地结果
也就是说Certificate 资源的核心职责主要是如下4件:
- 定义证书申请参数
- 指定签发器
- 管理证书和私钥输出到 Secret
- 自动续期和按条件重新签发
证书申请配置
最简示例:
shell
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com
namespace: web
spec:
secretName: example-com-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- example.com
- www.example.com
privateKey:
algorithm: RSA
size: 2048
rotationPolicy: Always
duration: 2160h
renewBefore: 360h
usages:
- digital signature
- key encipherment
- server auth
证书申请配置至少需要如下字段:
- spec.secretName
- spec.issuerRef
- 至少一个身份字段:
- dnsNames
- 或 commonName
- 或 uris
- 或 emailAddresses
- 或 ipAddresses
- 或 otherNames
总结:最简配置至少需要谁发证书、谁来签、签好后放哪儿的一个声明。
以下是一个官方 Certificate 资源示例,适用于 example.com 和 www.example.com DNS 名称,包含 spiffe://cluster.local/ns/sandbox/sa/example URI 主题备用名称,有效期为 90 天并在到期前 15 天续期。
该示例列出了 Certificate 资源所有可能的配置选项,但仅标注了必需字段的子集。
shell
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com
namespace: sandbox
spec:
# Secret 名称必填
secretName: example-com-tls
# secretTemplate 是可选的。如果设置了它,这些注解(annotations)和标签(labels)
# 将会被复制到名为 example-com-tls 的 Secret 上。
# 如果 Certificate 的 secretTemplate 发生变化,这些标签和注解会被重新协调(re-reconciled)。
# secretTemplate 也会被强制生效,因此如果第三方对该 Secret 上相关标签或注解进行了修改,
# cert-manager 会将其覆盖为与 secretTemplate 保持一致。
secretTemplate:
annotations:
my-secret-annotation-1: "foo"
my-secret-annotation-2: "bar"
labels:
my-secret-label: foo
privateKey:
algorithm: RSA
encoding: PKCS1
size: 2048
# 可选:额外输出格式(示例)
keystores:
pkcs12:
create: true
passwordSecretRef:
name: example-com-tls-keystore
key: password
profile: Modern2023
duration: 2160h # 90d
renewBefore: 360h # 15d
isCA: false
usages:
- server auth
- client auth
subject:
organizations:
- cert-manager
# 应避免在终端实体(leaf)证书中将 commonName 用作 DNS 名称。
# 除非环境中确实对此有特定需求,否则应仅使用 dnsNames,以避免 commonName 带来的问题。
# 通常,commonName 用于为 CA 证书提供便于人类识别的名称,
# 对于其他证书,一般可以避免使用。
commonName: example.com
# literalSubject 字段与 subject / commonName 互斥。
# 它允许将 subject 直接指定为字符串。
# 这在以下场景中很有用:当 subject 字段的顺序很重要时,或者当 subject 包含可通过其 OID 指定的特殊类型时。
# literalSubject: "O=jetstack, CN=example.com, 2.5.4.42=John, 2.5.4.4=Doe"
# commonName(或 literalSubject)、dnsNames、uris、emailAddresses、ipAddresses 或 otherNames 中,至少需要提供一个。
dnsNames:
- example.com
- www.example.com
uris:
- spiffe://cluster.local/ns/sandbox/sa/example
emailAddresses:
- john.doe@cert-manager.io
ipAddresses:
- 192.168.0.5
# cert-manager 1.14+ 且启用 OtherNames feature flag
otherNames:
# 仅支持ut8的 oid 类型值
- oid: 1.3.6.1.4.1.311.20.2.3 # User Principal Name "OID"
utf8Value: upn@example.local
# Issuer 引用始终是必需的
issuerRef:
name: ca-issuer
# 可以通过修改此处的 kind 来引用 ClusterIssuer。
# 默认值是 Issuer(即命名空间内的本地 Issuer)。
kind: Issuer
# group是可选的,因为 cert-manager 会默认使用该值;
# 但如果使用的是外部 issuer,请将其改为对应 issuer 所属的 group。
group: cert-manager.io
主要配置释义:
secretName:输出目标,必填项,它表示:证书签发成功后,要把结果写到哪个 Secret,生成的 Secret 一般在同命名空间下,通常包含:
- tls.key:私钥
- tls.crt:证书链
- ca.crt:上级 CA 证书(如果签发器能提供)
后续的Ingress或者Gateway,Pod 挂载等可能都要引用这个 Secret。
issuerRef:签发来源,表示这个 Certificate 要使用哪个签发器,name:Issuer / ClusterIssuer,kind:Issuer 或 ClusterIssuer,group:API Group,默认通常是 cert-manager.io。如果希望跨命名空间复用统一签发器,通常会用ClusterIssuer。
dnsNames:证书身份信息,这是 Certificate 中最核心的一块,最常见,用于 TLS 网站证书。对于 Web 服务,这通常是最主要字段。现代 TLS 实际校验主要基于 SAN(Subject Alternative Name),而不是 commonName。
提示:
- 对终端实体(leaf)DNS 证书,尽量不要依赖 commonName 表示 DNS 名称,除非环境确实需要。
- 以下之一必须存在:
- commonName(或通过 literalSubject 表达)
- dnsNames
- uris
- emailAddresses
- ipAddresses
- otherNames
privateKey:私钥配置,证书配套私钥应该怎样生成。algorithm常见的有RSA、ECDSA、Ed25519,不同的算法可能影响性能、兼容性、密钥长度要求、签名效率,一般兼容优先使用RSA 2048/3072,性能优先使用ECDSA。
rotationPolicy:私钥轮换,cert-manager >= v1.18.0:默认是 Always。两种区别是:
| 项目 | 描述 |
|---|---|
| Never | 只要 Secret 里已有 tls.key,后续重新签发时就复用旧私钥 |
| Always | 每次重签发都生成新私钥cert-manager 会等新证书成功签发后,再覆盖 Secret 中的 tls.key |
duration / renewBefore / renewBeforePercentage:控制证书有效期与续期。
duration:表示期望的证书有效期,默认值是 90 天,某些 Issuer 可能不接受指定的时长,最终实际签出来的有效期,可能由 Issuer 决定。
renewBefore:表示在证书到期前多久开始续期。
renewBeforePercentage:这是相对新的机制,它不是写固定时长,而是按证书实际有效期的百分比计算续期提前量。
isCA:是 CA 证书还是叶子证书(业务证书),配置为True通常适合自建 PKI,或者签发中间 CA。
secretTemplate:把标签和注解复制到目标 Secret 上,不是只创建时复制一次,如果之后修改 secretTemplate,cert-manager 会重新同步到 Secret,如果第三方改了这些受控 labels/annotations,cert-manager 会直接覆盖掉。适用于给 Secret 打统一标签场景。
证书交付物
最终生成的 Secret 是证书申请的交付物。通常生成的 Secret 至少会包含 tls.crt 和 tls.key,有时还会有:ca.crt 。
tls.crt:当证书由中间 CA 签发且 Issuer 能提供签发证书的链时, tls.crt 的内容将是请求的证书后接证书链,即:tls.crt = 叶子证书/业务证书 + 中间证书链,也就是说它通常不只是单张叶子证书。
tls.key:对应私钥。
ca.crt:如果 cert-manager 知晓 issuing CA,则可能写入 ca.crt。如ACME:通常不知道稳定可用的 ca.crt,所以可能没有。某些 CA / SelfSigned / 内部 CA:通常会有。
证书重签发
cert-manager 不只是"签一次证书",它持续负责两类事情:
- 证书到期前自动续期
- 当配置变化时重新签发
对于证书续期和重签发,需要注意:
- duration 最小值:1 小时,renewBefore 最小值:5 分钟,且必须满足:duration > renewBefore
- 对于默认续期时间,如果你不显式设置:cert-manager 默认会在证书生命周期的 2/3 处安排续期。
- 90d(90天)是错误的写法,字段底层是基于Go time.Duration 格式,可用的后缀是
s、m、h。 - 虽然issuer里配置了多个字段,但签发机构不一定完全照办,cert-manager 会尝试按照配置提出请求,但某些 Issuer 可能被忽略,或者强制加默认值,甚至删除某些用法。
同时除了自然到期,下面情况也会触发重新签发,当修改了 Certificate.spec 中这些字段之一:
- commonName
- dnsNames
- ipAddresses
- uris
- emailAddresses
- subject
- isCA
- usages
- duration
- issuerRef
这些字段一旦变更,cert-manager 会认为:这是"不同的证书需求",需要重新申请。
注意 :不建议删除目标 Secret 试图让 cert-manager 重建证书,而应该使用 cmctl renew <certificate-name> 方式重新签发。
提示:基于保护业务,删除 Certificate 时,Secret 不会自动删除,Secret 是基于 Certificate 生成的产物,但是证书不再自动续期。
ingress 注解
ingress注解方案
方案介绍
cert-manager 的常见应用场景是为 Ingress 资源申请 TLS 签名证书以实现安全加密。只需在 Ingress 资源中添加注解,cert-manager 即可代为创建 Certificate 资源。该功能由 cert-manager 的子组件 ingress-shim 负责实现。
本方案主要是描述如何通过给 Ingress 打注解,让 cert-manager 自动创建 Certificate 并管理 TLS Secret。
即Annotated Ingress resource(带 cert-manager 注解的 Ingress)。
核心思路:
- 不手工写 Certificate
- 只需要在 Ingress 上加 cert-manager 相关注解
- cert-manager 的 ingress-shim 组件获知后,自动创建对应的 Certificate
- 最终证书写入 spec.tls[].secretName 指定的 Secret
所以它本质上是:Ingress → 自动派生 Certificate → 自动签发证书 → 自动填充 TLS Secret ,从而实现自动化全链路流程。
组件关系梳理:
- Ingress 不负责签发证书;
- Ingress 也不是证书对象,真正证书管理对象仍然是 Certificate ;
方案优点
使用 Ingress 注解方式,而不是手工创建 Certificate,有几个明显优点:
- 更符合"应用入口即 TLS 配置"的思维,开发/平台侧只改 Ingress 就行,不用关心额外 Certificate YAML。
- 简化使用,尤其对普通 Web 应用部署非常方便。
- 适合标准化平台,平台可以规定Ingress 写法统一,注解统一,所有业务自动获得证书管理能力。
ingress-shim工作机制
ingress-shim 是 cert-manager 的一个子组件,它做的是:监听 Ingress,并根据注解自动生成/维护对应的 Certificate 对象。即 ingress-shim 理解成一个"Ingress 到 Certificate 的转换控制器"。
其工作的核心流程是:
- ingress-shim 监听整个集群的 Ingress
- 如果发现某个 Ingress 上有 cert-manager 支持的注解,它就检查这个 Ingress 的:
- spec.tls[].hosts
- spec.tls[].secretName
- issuer 相关注解
- 然后在同 namespace 中创建或维护一个 Certificate
- Certificate 再触发后续 cert-manager 签发流程
- 最终证书写入 secretName 对应的 Secret
- Ingress 通过这个 Secret 提供 HTTPS
Ingress 本身不直接申请证书,是 ingress-shim 看到注解后,自动创建 Certificate。
ingress配置讲解
典型的配置示例如下:
shell
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
# 添加一个标注,以指示要使用的发布者。
cert-manager.io/cluster-issuer: nameOfClusterIssuer
name: myIngress
namespace: myIngress
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: myservice
port:
number: 80
- host: www.example.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: myservice
port:
number: 80
tls: # 在 TLS 配置中放置主机将决定最终出现在证书的 subjectAltNames 中的内容
- hosts:
- example.com
- www.example.com
secretName: myingress-cert # cert-manager 将创建的证书存储在这个密钥中
配置释义:
annotations.[]:指定用哪个 ClusterIssuer 来签发证书。
tls.hosts:决定"证书包含哪些域名",这里的 host 会成为 Certificate 中的 SAN / DNS 名称来源。即 Ingress 的 tls.hosts 会映射成生成的 Certificate 的主机名集合。
tls.secretName:ingress-shim 会让自动生成的 Certificate 使用这个 Secret 名称。最终 Ingress 就通过这个 Secret 提供 HTTPS。
请求issuer注解
cert-manager.io/issuer
该cert-manager.io/issuer: <issuer-name>的主要作用是用来指定要使用的 Issuer。
注意:这个注解并不一定只表示 namespaced Issuer。
它默认会指向 cert-manager.io group 下的 Issuer,但对于外部 issuer,它既可以表示 namespaced,也可以表示 cluster-scoped 类型,只是需要配合 kind/group 说明。
如果用的是 namespaced issuer,那么该 issuer 必须和 Ingress 在同一个 namespace。
cert-manager.io/cluster-issuer
该 cert-manager.io/cluster-issuer: <clusterissuer-name> 的主要作用是用来指定 cert-manager 内置的 ClusterIssuer。
注意:这个注解Ingress 在哪个 namespace 都可以引用,因为 ClusterIssuer 本身是 cluster-scoped。
它默认会指向 cert-manager.io group 下的 ClusterIssuer,但对于外部 ClusterIssuer(也就是集群的Issuer 没有写在默认的 cert-manager 命名空间),不要使用该方式,而要使用 cert-manager.io/issuer,再配 issuer-kind 和 issuer-group 。
-
cert-manager.io/issuer-kind: AWSPCAIssuer指定外部 issuer 的 kind,只对 out-of-tree issuer 有用。
-
cert-manager.io/issuer-group: awspca.cert-manager.io指定外部 issuer 的 API Group,同样只在外部 issuer 场景下需要。
如上四个注解选择方式如下:
内置 namespaced Issuer,使用 cert-manager.io/issuer: my-issuer 。
内置 ClusterIssuer,使用 cert-manager.io/cluster-issuer: letsencrypt-prod 。
外部 issuer,使用:
shell
cert-manager.io/issuer: my-external-issuer
cert-manager.io/issuer-kind: AWSPCAIssuer
cert-manager.io/issuer-group: awspca.cert-manager.io
ACME HTTP01注解
如果你的 issuer 是 ACME,并且使用 HTTP01,需要了解如下几个注解。
acme.cert-manager.io/http01-ingress-class: nginx
acme.cert-manager.io/http01-ingress-class: nginx 用于指定用于 ACME HTTP01 challenge 的 ingress class 。
如果业务 Ingress 的 class,和用来做 ACME challenge质询的 ingress 需要区分开,例如:业务 Ingress 是内部 Ingress,但 HTTP01 challenge 需要经由公网入口验证,这时 challenge 可能要走另一个 ingress class。
acme.cert-manager.io/http01-edit-in-place: "true"
作用是控制 HTTP01 challenge 时,是直接修改现有 Ingress,还是新建一个专门用于 challenge 的 Ingress
值为 "true" 时,cert-manager 直接修改现有 Ingress,在当前 Ingress 中添加 challenge 路由。默认为 false,即cert-manager 会单独创建一个 challenge Ingress。
提示:如果同时存在默认 issuer 配置以及 Ingress 上显式 cert-manager.io/issuer / cluster-issuer,那么显式注解优先于默认 issuer。
Certificate 通用字段映射类注解
此部分注解非常实用,它允许在 Ingress 上直接控制自动生成的 Certificate.spec 某些字段。
即可直接在ingress添加注解来控制 Certificate 证书申请的行为。
-
cert-manager.io/common-name该注解映射到 Certificate 的
spec.commonName。 -
cert-manager.io/email-sans该注解映射到 Certificate 的
spec.emailAddresses,支持逗号分隔:cert-manager.io/email-sans: "me@example.com,you@example.com"。 -
其他字段
支持如下丰富的字段注解来映射到 Certificate.spec.subject.*:
- cert-manager.io/subject-organizations
- cert-manager.io/subject-organizationalunits
- cert-manager.io/subject-countries
- cert-manager.io/subject-provinces
- cert-manager.io/subject-localities
- cert-manager.io/subject-postalcodes
- cert-manager.io/subject-streetaddresses
- cert-manager.io/subject-serialnumber
总结:Ingress 注解不仅能让你"自动建证书",还允许你把一些证书主体信息直接从 Ingress 层下发到 Certificate。
不过实际公网 Web TLS 场景里,如上字段一般不是最常用,通常主要还是:
- hosts
- secretName
- issuer
-
cert-manager.io/duration该注解映射到 Certificate 的
spec.duration。 -
cert-manager.io/renew-before该注解映射到 Certificate 的
spec.renewBefore,从而能在 Ingress 侧控制证书期望有效期,续期提前量。
Certificate 私钥字段映射类注解
此部分注解相当于把 Certificate.spec.privateKey.* 相关能力融合到 Ingress 注解层。它允许在 Ingress 上直接控制自动生成的 Certificate.spec.privateKey 某些字段。
即可直接在ingress添加注解来控制 Certificate 证书申请的私钥有关配置。
-
cert-manager.io/private-key-algorithm私钥的加密算法类型,支持
RSA、ECDSA、Ed25519,默认为RSA。 -
cert-manager.io/private-key-encoding支持``PKCS1
、PKCS8,默认PKCS1` 。 -
cert-manager.io/private-key-size私钥的加密算法长度,如果算法是:
RSA:支持 2048 / 4096 / 8192
ECDSA:支持 256 / 384 / 521
Ed25519:忽略 size
默认:
RSA 默认 2048
ECDSA 默认 256
cert-manager.io/private-key-rotation-policy
证书是否自动续期,默认是cert-manager.io/private-key-rotation-policy: Always。
注解使用建议
使用ingress注解实现自动化证书申请,需要关注以下几个点:
- 当多个 Ingress 生成多个证书时,即要从多个 Ingress 生成多个 Certificate,则每个 Ingress 都必须有 issuer 相关注解,且每个 Ingress 都必须有唯一的 tls.secretName。
总结:一个自动生成的 Ingress TLS 证书,最好对应一个唯一 Secret。
- 安装 cert-manager 时,ingress-shim 通常就已经随 cert-manager 一起部署好了,不需要额外管理。
- 通过ingress注解方式自动申请证书只是"自动化捷径",即把整个链条自动化,但不是唯一方式,完全可以手工创建 Certificate来使用。
- ingress-shim 是桥梁,不是签发器,后面的签发逻辑仍然由 Certificate / CertificateRequest / Issuer 完成。