本文边界:本文聚焦业务入口 TLS、证书 Secret 与 cert-manager 的协作;Ingress 资源和 Ingress Controller 的路由模型请阅读入口专题。
说明:本文由 Codex 根据作者提问、上下文讨论与官方文档辅助整理,属于 AI 生成/整理内容。涉及生产环境证书与集群控制面维护时,请结合实际发行版、安装方式和官方文档交叉验证。
先说结论#
在 Kubernetes 里,Ingress、Ingress Controller 和 cert-manager 是三类不同角色:
Ingress 是规则;
Ingress Controller 是执行规则的网关或反向代理;
cert-manager 是自动签发、续期、分发证书的控制器。它们常见的协作链路是:
Client
-> DNS
-> LoadBalancer / NodePort
-> Ingress Controller
-> Service
-> Pod
cert-manager
-> Issuer / ClusterIssuer
-> CA / Let's Encrypt / Vault / 私有 CA
-> Secret(tls.crt, tls.key)
-> Ingress Controller 加载 TLS 证书证书方面可以先抓住一个边界:
- 控制面证书保护 Kubernetes 自身,例如 API Server、etcd、controller-manager、scheduler、kubelet。
- 业务入口证书保护应用入口,例如 Ingress HTTPS 证书。
- 扩展组件证书保护 webhook、aggregated API server、operator 等扩展链路。
- 服务间 mTLS 证书保护 Pod 到 Pod 的通信,常见于 service mesh。
cert-manager 很适合管理业务层和扩展层证书,但不建议把 Kubernetes 控制面 PKI 全部交给 cert-manager 管。
Ingress、Ingress Controller 与 cert-manager 的区别#
Ingress#
Ingress 是 Kubernetes API 资源对象,描述外部 HTTP/HTTPS 流量应该如何进入集群。
它通常定义:
- 域名:例如
app.example.com - 路径:例如
/api、/ - 后端服务:例如
app-service:80 - TLS Secret:例如
app-tls - IngressClass:例如
nginx - Controller 专属注解:例如 NGINX rewrite、限流、白名单等
示例:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app
namespace: demo
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app
port:
number: 80需要注意:只创建 Ingress 资源本身不会让流量真正进入集群。Kubernetes 官方文档也强调,必须有 Ingress Controller 来满足这个 Ingress。
Ingress Controller#
Ingress Controller 是真正处理流量的组件。
常见实现包括:
- ingress-nginx
- Traefik
- HAProxy
- Envoy / Contour
- AWS Load Balancer Controller
- GCE Ingress Controller
- Azure Application Gateway Ingress Controller
它通常以 Deployment 或 DaemonSet 运行,并通过一个 Service 暴露 80/443。
以 ingress-nginx 为例,常见 Helm 安装方式是:
helm upgrade --install ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--namespace ingress-nginx \
--create-namespaceIngress Controller 的核心工作:
- watch
Ingress、Service、EndpointSlice、Secret、IngressClass - 判断哪些 Ingress 属于自己处理
- 把 Ingress 规则转换为 NGINX、Traefik、Envoy 或云 LB 配置
- 接收外部 HTTP/HTTPS 流量
- 按 host/path 转发到后端 Service
- 读取 TLS Secret,完成 HTTPS 终止
在云厂商集群中,Ingress Controller 常通过 LoadBalancer 类型 Service 对外暴露。在裸金属环境中,则常见使用 NodePort、hostNetwork 或 MetalLB。
cert-manager#
cert-manager 是 Kubernetes 里的证书生命周期管理器。
它会安装一组 CRD,例如:
IssuerClusterIssuerCertificateCertificateRequestOrderChallenge
它的基本模型是:
Certificate
-> Issuer / ClusterIssuer
-> 外部或内部 CA
-> Secret常见安装方式:
helm install cert-manager oci://quay.io/jetstack/charts/cert-manager \
--version v1.20.3 \
--namespace cert-manager \
--create-namespace \
--set crds.enabled=truecert-manager 负责:
- 根据
Certificate资源申请证书 - 通过
Issuer或ClusterIssuer找到签发方 - 对接 Let’s Encrypt、Vault、私有 CA 等
- 完成 ACME HTTP-01 或 DNS-01 验证
- 把证书和私钥写入 Kubernetes Secret
- 在证书过期前自动续期
三者如何配合工作#
最典型的场景是:Ingress + ingress-nginx + cert-manager + Let’s Encrypt。
流程如下:
sequenceDiagram
participant User as Client
participant DNS as DNS
participant IC as Ingress Controller
participant APP as App Service/Pod
participant CM as cert-manager
participant LE as Let's Encrypt
participant SEC as Kubernetes Secret
CM->>CM: 监听 Ingress 注解与 Certificate
CM->>LE: 请求签发 app.example.com 证书
LE->>CM: 返回 ACME Challenge
CM->>IC: 创建临时 HTTP-01 solver Ingress
LE->>DNS: 解析 app.example.com
LE->>IC: 访问 /.well-known/acme-challenge/...
IC->>CM: 转发到 solver Pod
CM->>LE: 验证通过
LE->>CM: 签发证书
CM->>SEC: 写入 tls.crt / tls.key
IC->>SEC: 加载 TLS Secret
User->>DNS: 访问 app.example.com
DNS->>IC: 指向入口地址
IC->>APP: TLS 终止后转发请求如果 Ingress 上有这样的注解:
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod并且 spec.tls.secretName 指定了 Secret 名称,cert-manager 的 ingress-shim 会自动创建或维护对应的 Certificate。
一个典型 ClusterIssuer:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
email: ops@example.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-prod-account-key
solvers:
- http01:
ingress:
ingressClassName: nginxHTTP-01 的关键要求是:Let’s Encrypt 必须能从公网访问这个域名的 80 端口,并最终打到 cert-manager 创建的 solver Pod。
DNS-01 则不要求公网 HTTP 可达,而是通过 DNS TXT 记录证明域名所有权。它更适合:
- 泛域名证书,例如
*.example.com - 内网服务证书
- 不方便暴露 HTTP-01 路径的场景
集群中常见证书类型#
CA 证书#
CA 是信任根,负责签发和验证其他证书。
在 kubeadm 集群中,常见 CA 有:
| 证书 | 作用 | 常见路径 |
|---|---|---|
| Kubernetes CA | 签发 API Server、组件客户端、用户等证书 | /etc/kubernetes/pki/ca.crt |
| etcd CA | 签发 etcd server、peer、client 证书 | /etc/kubernetes/pki/etcd/ca.crt |
| front-proxy CA | 用于聚合 API / extension API server | /etc/kubernetes/pki/front-proxy-ca.crt |
ca.key、etcd/ca.key、front-proxy-ca.key 是私钥,必须严格保护。
服务端证书#
服务端证书证明“我是这个服务”。
| 证书 | 谁使用 | 谁验证 |
|---|---|---|
apiserver.crt | kube-apiserver | kubectl、kubelet、controller-manager、scheduler |
etcd/server.crt | etcd server | kube-apiserver、etcdctl |
| kubelet serving cert | kubelet HTTPS endpoint | kube-apiserver、metrics-server |
| Ingress TLS Secret | Ingress Controller | 浏览器、外部客户端 |
| webhook serving cert | admission webhook / conversion webhook | kube-apiserver |
服务端证书最容易踩坑的是 SAN,即 Subject Alternative Name。客户端访问的 IP 或 DNS 必须包含在证书 SAN 中,否则会出现类似:
x509: certificate is valid for ..., not ...客户端证书#
客户端证书证明“调用方是谁”。
| 证书 | 调用方向 | 身份含义 |
|---|---|---|
admin.conf 中的 client cert | admin / kubectl -> apiserver | 管理员身份 |
controller-manager.conf | controller-manager -> apiserver | system:kube-controller-manager |
scheduler.conf | scheduler -> apiserver | system:kube-scheduler |
| kubelet client cert | kubelet -> apiserver | system:node:<nodeName> |
| kube-proxy client cert | kube-proxy -> apiserver | kube-proxy 身份 |
apiserver-etcd-client.crt | apiserver -> etcd | apiserver 作为 etcd 客户端 |
apiserver-kubelet-client.crt | apiserver -> kubelet | apiserver 作为 kubelet 客户端 |
Kubernetes 认证时会从证书中读取 CN、O 等字段,并结合 RBAC 判断这个身份可以做什么。
etcd peer 证书#
etcd 比较特殊,它除了 server/client 证书,还有 peer 证书。
| 证书 | 作用 |
|---|---|
etcd/peer.crt | etcd 节点之间互相认证和通信 |
etcd/server.crt | etcd 对客户端提供 TLS 服务 |
etcd/healthcheck-client.crt | 健康检查客户端访问 etcd |
apiserver-etcd-client.crt | apiserver 访问 etcd |
etcd 集群内部通常启用双向 TLS。也就是说,节点之间既要证明自己,也要验证对方。
Ingress 业务证书#
Ingress 证书一般存放在 Kubernetes Secret 中:
tls.crt
tls.key它只负责业务入口 HTTPS,例如:
Browser
-> Ingress Controller
-> Service
-> Pod它和 Kubernetes 控制面证书不是一类东西。它面向业务域名,例如 app.example.com,通常适合由 cert-manager 维护。
webhook 与聚合 API 证书#
Admission webhook、conversion webhook、aggregated API server 都可能需要服务端证书。
链路通常是:
kube-apiserver
-> webhook service
-> webhook pod如果 webhook 证书过期、CA bundle 不对,常见错误是:
failed calling webhook
x509: certificate signed by unknown authority
certificate has expired or is not yet valid这类证书适合由 cert-manager 管理,配合 cainjector 自动注入 CA bundle。
service mesh / workload mTLS 证书#
如果集群中使用 Istio、Linkerd、Consul Connect、SPIFFE/SPIRE,还会有 workload 证书。
特点:
- 生命周期通常较短
- 每个 workload 有独立身份
- 常使用 SPIFFE ID
- 不一定存放在 Kubernetes Secret 中
- 通常由 service mesh 或 SPIRE 自己维护
这类证书主要保护服务间通信,不是 Ingress 对外 HTTPS 证书。
证书有没有过期时间#
大多数 X.509 证书都有过期时间,包括 CA、服务端证书和客户端证书。
以 kubeadm 默认配置为例:
| 类型 | 默认有效期 | 通常谁维护 | 是否适合 cert-manager |
|---|---|---|---|
| Kubernetes CA | 10 年 | kubeadm / 外部 CA | 通常不适合 |
| etcd CA | 10 年 | kubeadm / 外部 CA | 通常不适合 |
| front-proxy CA | 10 年 | kubeadm / 外部 CA | 通常不适合 |
| apiserver server cert | 1 年 | kubeadm | 不建议 |
| apiserver-etcd-client cert | 1 年 | kubeadm | 不建议 |
| apiserver-kubelet-client cert | 1 年 | kubeadm | 不建议 |
| controller-manager / scheduler / admin client cert | 1 年 | kubeadm | 不建议 |
| kubelet client cert | 通常 1 年左右 | kubelet 自动轮转 + Kubernetes CSR | 不是典型职责 |
| kubelet serving cert | 取决于配置 | kubelet / CSR / 发行版机制 | 通常不建议 |
| Ingress TLS 证书 | 常见 90 天 | cert-manager | 适合 |
| webhook serving cert | 取决于配置 | chart / operator / cert-manager | 适合 |
| workload mTLS 证书 | 小时到天级常见 | service mesh / SPIRE | 通常由 mesh 管 |
kubeadm 支持在配置中调整证书有效期:
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
certificateValidityPeriod: 8760h # 默认 1 年
caCertificateValidityPeriod: 87600h # 默认 10 年cert-manager 的 Certificate 也可以指定有效期和提前续期时间:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: app-cert
namespace: demo
spec:
secretName: app-tls
duration: 2160h # 90 天
renewBefore: 360h # 提前 15 天续期
dnsNames:
- app.example.com
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuercert-manager 默认 duration 是 90 天。如果没有设置 renewBefore,它会在证书实际有效期走到约 2/3 时尝试续期。
cert-manager 能不能管理所有证书#
结论:不能简单地把所有证书都交给 cert-manager,尤其不要把控制面 PKI 依赖在集群内的 cert-manager 上。
原因很直接:
cert-manager 运行在 Kubernetes 集群里;
cert-manager 依赖 kube-apiserver 正常工作;
控制面证书失效时,kube-apiserver、etcd 或认证链路可能已经不可用;
此时 cert-manager 也可能无法正常补救。所以更合理的职责边界是:
| 证书范围 | 推荐维护方式 |
|---|---|
| 控制面证书 | kubeadm、发行版工具、外部 CA、集群生命周期管理工具 |
| etcd 证书 | kubeadm、etcd 运维流程、发行版工具、外部 CA |
| kubelet client cert | kubelet certificate rotation + Kubernetes CSR |
| Ingress HTTPS 证书 | cert-manager |
| 应用 TLS Secret | cert-manager |
| webhook serving cert | cert-manager / operator / Helm chart |
| service mesh workload cert | Istio、Linkerd、SPIRE 等自身 CA 系统 |
常用排查命令#
查看 kubeadm 控制面证书过期时间#
kubeadm certs check-expiration续期 kubeadm 管理的证书#
kubeadm certs renew all续期后通常需要重启相关控制面静态 Pod 或节点服务,让组件加载新证书。具体操作要结合集群发行版和高可用部署方式。
查看 cert-manager 管理的证书#
kubectl get certificate -A查看某个证书详情#
kubectl describe certificate -n <namespace> <name>查看 CertificateRequest / Order / Challenge#
kubectl get certificaterequest -A
kubectl get order -A
kubectl get challenge -A查看 TLS Secret 内容#
kubectl get secret -n <namespace> <secret-name> -o yaml解码证书并查看有效期#
kubectl get secret -n <namespace> <secret-name> \
-o jsonpath='{.data.tls\.crt}' \
| base64 -d \
| openssl x509 -noout -text -dates手动触发 cert-manager 续期#
cmctl renew -n <namespace> <certificate-name>不建议通过删除 Secret 来作为常规续期手段。cert-manager 官方更推荐通过 cmctl renew 或调整 Certificate 资源触发重新签发。
生产实践建议#
控制面证书#
- 定期运行
kubeadm certs check-expiration或发行版提供的检查命令。 - 将证书过期时间接入监控和告警。
- 保持 Kubernetes 小版本和补丁版本及时升级;kubeadm 会在控制面升级时处理证书续期。
- 不要等证书过期后再处理,尤其是 apiserver、etcd、admin.conf。
- 对 CA 轮换保持谨慎,CA 轮换比 leaf certificate 续期风险更高。
Ingress 证书#
- 优先使用 cert-manager 管理。
- HTTP-01 要确认公网能访问 80 端口。
- DNS-01 要确认 DNS provider 权限、TXT 记录传播和递归 DNS 行为。
- 不同环境建议分开使用 staging 和 production Issuer,避免触发 Let’s Encrypt 限流。
- 对重要域名监控
Certificate状态和 Secret 证书过期时间。
webhook 证书#
- webhook 证书过期会影响资源创建、更新甚至集群扩展组件运行。
- 如果使用 cert-manager 管理 webhook 证书,应确认
cainjector正常工作。 - 排查 webhook 错误时同时看
ValidatingWebhookConfiguration/MutatingWebhookConfiguration中的caBundle。
service mesh 证书#
- 不要把 mesh 的工作负载证书和 Ingress 证书混为一类。
- 按 mesh 自身文档维护根 CA、中间 CA、workload cert rotation。
- 重点关注根证书过期、trust bundle 分发和多集群信任域。
关键区别速记#
Ingress:声明 HTTP/HTTPS 路由规则。
Ingress Controller:真正接收和转发流量。
cert-manager:签发和续期证书。
server cert:证明服务是谁。
client cert:证明调用方是谁。
CA cert:证明谁有资格签发和校验证书。
控制面证书:不要依赖集群内 cert-manager 兜底。
业务入口证书:非常适合 cert-manager。
webhook 证书:适合 cert-manager,但要关注 caBundle 注入。
service mesh 证书:通常由 mesh 自己管理。