Kubespray 部署 cert-manager 完全指南:CA 证书创建、Ingress TLS 安全与内部 CA 信任配置
【免费下载链接】kubesprayDeploy a Production Ready Kubernetes Cluster项目地址: https://gitcode.com/GitHub_Trending/ku/kubespray
本文基于 kubespray 仓库的 cert-manager 官方文档 与配套 Ansible 角色源码,讲解如何用 Kubespray 在生产级 Kubernetes 集群中启用 cert-manager:如何编写 TLS Root CA 配置并生成根证书、如何通过 Ingress 注解让 ingress-shim 自动签发并轮换证书、如何用cert_manager_trusted_internal_ca让 cert-manager 信任内部 CA,以及 Kubespray 内部部署该组件的完整实现链路(角色任务、清单模板、变量默认值),供运维与平台工程师直接复用。
cert-manager 是什么,为什么 Kubespray 把它作为 Addon 提供
cert-manager 是一个原生的 Kubernetes 证书管理控制器,可以从多种来源签发证书,包括 Let's Encrypt、HashiCorp Vault、Venafi、简单签名密钥对(CA Issuer)或自签名方式。它会持续保证证书处于有效且最新状态,并在到期前按配置的时间点尝试续期,从而免除手工滚动更新 TLS 证书的工作。
Kubespray 将 cert-manager 作为可选 Addon 集成在kubernetes-apps/ingress_controller角色组中:
- 入口定义在 roles/kubernetes-apps/ingress_controller/meta/main.yml,当
cert_manager_enabled为真时加载kubernetes-apps/ingress_controller/cert_manager子角色,并打上apps、ingress-controller、cert-manager三个标签; - 默认关闭,见 roles/kubespray_defaults/defaults/main/main.yml 第 476 行:
cert_manager_enabled: false; - 当前仓库锁定的组件版本为
1.15.3,见 roles/kubespray_defaults/defaults/main/download.yml,三个核心镜像(controller、cainjector、webhook)均来自 quay 仓库的jetstack命名空间。
启用 cert-manager:修改集群 Addon 清单变量
启用方式非常直接——编辑你的 K8s 集群 addons inventory(例如inventory/sample/group_vars/k8s_cluster/addons.yml),把cert_manager_enabled置为true:
# Cert manager deployment cert_manager_enabled: true仓库内置的示例变量文件 inventory/sample/group_vars/k8s_cluster/addons.yml 中列出了全部可用的 cert-manager 相关变量(默认均为注释状态),包括:
| 变量 | 默认值(见角色 defaults) | 作用 |
|---|---|---|
cert_manager_enabled | false | 总开关,控制角色是否执行 |
cert_manager_namespace | cert-manager | 部署命名空间 |
cert_manager_tolerations | [] | 为三个 Deployment 注入容忍度 |
cert_manager_affinity | {} | 注入亲和性规则 |
cert_manager_nodeselector | {} | 注入节点选择器 |
cert_manager_dns_policy | ClusterFirst | Pod DNS 策略 |
cert_manager_dns_config | {} | 自定义 nameservers 等 DNS 配置 |
cert_manager_controller_extra_args | [] | 追加到 controller 启动参数(如--dns01-recursive-nameservers-only=true) |
cert_manager_trusted_internal_ca | 未定义 | 内部 CA 证书 PEM,定义后自动挂载信任 |
cert_manager_leader_election_namespace | kube-system | leader election 所在命名空间,GKE Autopilot 等禁止改动 kube-system 的环境需改值 |
这些默认值集中在 roles/kubernetes-apps/ingress_controller/cert_manager/defaults/main.yml。此外该角色还定义了cert_manager_http_proxy/https_proxy/no_proxy三个变量,默认继承全局http_proxy、https_proxy、no_proxy,用于代理环境下访问 ACME 服务器。
Kubespray 如何实际部署 cert-manager
roles/kubernetes-apps/ingress_controller/cert_manager/tasks/main.yml 揭示了部署链路,全部任务只在groups['kube_control_plane'][0](第一个控制平面节点)上执行:
- 清理遗留目录:删除旧版 addon 目录
{{ kube_config_dir }}/addons/cert_manager(带upgrade标签),保证升级路径干净; - 重建 addon 目录:创建
0755权限的addons/cert_manager; - 渲染模板:将
cert-manager.yml.j2与cert-manager.crds.yml.j2渲染为cert-manager.yml和cert-manager.crds.yml; - 应用清单:调用
kube模块,用集群自带 kubectl({{ bin_dir }}/kubectl)依次以state: latest应用cert-manager(全部资源)与cert-manager.crds(CRD 类型),保证幂等更新。
清单模板 roles/kubernetes-apps/ingress_controller/cert_manager/templates/cert-manager.yml.j2 是标准 Helm chart 的模板化移植,包含 Namespace、三个 ServiceAccount、完整 RBAC(各控制器 ClusterRole/ClusterRoleBinding、leader election Role/RoleBinding)、两个 Service,以及三个 Deployment:
- cert-manager(controller):核心控制器,监听 9402(metrics,
/metrics端口并带 prometheus scrape 注解)与 9403(healthz),启动参数含--cluster-resource-namespace=$(POD_NAMESPACE)、--leader-election-namespace={{ cert_manager_leader_election_namespace }},并通过{% for extra_arg in cert_manager_controller_extra_args %}循环追加自定义参数(模板第 997-999 行); - cert-manager-cainjector:把集群中 Issuer/ClusterIssuer 引用的 CA 证书自动注入到需要 CA 的组件(如 webhook、API Service);
- cert-manager-webhook:准入 Webhook(MutatingWebhookConfiguration + ValidatingWebhookConfiguration),secure-port 10250,健康检查端口 6080,通过动态 CA Secret(
cert-manager-webhook-ca)提供 TLS。
三个容器均设置runAsNonRoot: true、allowPrivilegeEscalation: false、capabilities.drop: [ALL]、readOnlyRootFilesystem: true与seccompProfile: RuntimeDefault,且 tolerations/nodeSelector/affinity/dnsPolicy/dnsConfig 均按变量条件化渲染。
Kubernetes TLS Root CA Certificate/Key Secret
如果你计划用 TLS 客户端证书保护 ingress 资源,需要先创建并部署一个 Kubernetesca-key-pairSecret,其中包含 Root CA 证书与私钥,供集群中的 CA 类型 Issuer 使用。
补充说明:kubespray 仓库本身并不自动创建这个 Secret——文档中给出的方案是在集群外(例如用 cfssl 或 ssh-keygen/OpenSSL)生成 CA 密钥对后,自行以
kubectl create secret tls ca-key-pair --cert=... --key=...之类的方式部署到cert-manager命名空间。Kubespray 只负责把 cert-manager 控制器本身装好。
保护 Ingress 资源:ingress-shim 自动签发与轮换
cert-manager 最常见的用例就是为 ingress 资源申请 TLS 签名证书。做法很简单:在 Ingress 资源上加注解即可,cert-manager 负责为你创建对应的 Certificate 资源。承担这一职责的是 cert-manager 的一个子组件ingress-shim——从模板 RBAC 可以看到其独立权限集(cert-manager-controller-ingress-shimClusterRole,模板第 307-343 行):它可以对certificates、certificaterequests执行 create/update/delete,并 watch 集群内的ingresses资源,以及gateway.networking.k8s.io的gateways/httproutes。
例如使用 Traefik ingress 控制器时,给 Prometheus ingress 加上注解cert-manager.io/cluster-issuer: ca-issuer并在定义中补充spec.tls段:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: prometheus-k8s namespace: monitoring labels: prometheus: k8s annotations: cert-manager.io/cluster-issuer: ca-issuer spec: ingressClassName: "traefik" tls: - hosts: - prometheus.example.com secretName: prometheus-dashboard-certs rules: - host: prometheus.example.com http: paths: - path: / pathType: ImplementationSpecific backend: service: name: prometheus-k8s port: name: web部署后,cert-manager 会每 3 个月自动轮换prometheus.example.com的 TLS 证书与私钥,并把结果持续写入 Kubernetes Secretprometheus-dashboard-certs。完整的证书申请、Order/Challenge 机制与 HTTP-01/DNS-01 验证流程,建议进一步查阅 cert-manager 官方文档的 Ingress 使用指南、Ingress 教程与 ACME 章节(HTTP Validation、DNS Validation、ACME FAQ)。
ACME 签发
ACME Issuer 类型代表注册到某个 ACME 证书颁发服务器(Automated Certificate Management Environment)上的单一账户。创建新的 ACME Issuer 时,cert-manager 会生成一把私钥用于向 ACME 服务器证明身份。
- 公共 ACME 服务器签发的证书通常被客户端计算机默认信任:由 ACME 证书支撑的网站访问时,绝大多数浏览器会直接信任;
- ACME 证书通常是免费的;
- 验证方式分两类:HTTP01 挑战与 DNS01 挑战,对应 ACME HTTP Validation 与 DNS Validation 教程。
注意 challenges 控制器的 RBAC 中同时声明了对pods、services、ingresses、httproutes的 CRUD 权限(模板第 279-295 行)——这正是 HTTP01 验证时临时创建验证用 Pod/Service、并改写 Ingress 以承载验证路由所需的底层能力。
ACME + 内部 CA:cert_manager_trusted_internal_ca
当 ACME 服务器由内部证书颁发机构(CA)承载时,需要 cert-manager 在部署层面信任该 CA。Kubespray 提供了对应变量:把 CA 证书加入group_vars下的addons.yml(仓库示例位于 inventory/sample/group_vars/k8s_cluster/addons.yml):
cert_manager_trusted_internal_ca: | -----BEGIN CERTIFICATE----- [REPLACE with your CA certificate] -----END CERTIFICATE-----CA 被信任后,就可以按常规方式定义你的 Issuer 了。
源码层面的实现细节值得展开:在 cert-manager.yml.j2 第 940-950 行,只要cert_manager_trusted_internal_ca被定义,模板就会渲染出名为ca-internal-truststore的 ConfigMap(键为internal-ca.pem);随后在第 1040-1050 行,该 ConfigMap 以defaultMode: 420(即 0644)的卷挂载到 controller 容器的/etc/ssl/certs/internal-ca.pem。这解释了"信任必须发生在部署层面"的机制——cert-manager 进程启动时即能看到这份内部根证书,从而在验证 ACME 响应与构造信任链时将其纳入信任存储。
从零创建 TLS Root CA 证书与密钥
没有现成的 TLS Root CA 证书与密钥时,可以按以下步骤用 Cloudflare PKI/TLScfssl工具链创建(cfssl不可用时也可以用ssh-keygen和 OpenSSL 完成同样目标)。
1. 安装 cfssl 工具链
以 Ubuntu/Debian 为例,工具链包含在golang-cfssl包中:
sudo apt-get install -y golang-cfssl2. 创建 Root CA 签名配置文件
默认 TLS 证书有效期为8760h,即证书创建之日起 1 年:
$ cat > ca-config.json <<EOF { "signing": { "default": { "expiry": "8760h" }, "profiles": { "kubernetes": { "usages": ["signing", "key encipherment", "server auth", "client auth"], "expiry": "8760h" } } } } EOF其中profiles.kubernetes同时声明了 signing、密钥加密、服务端认证、客户端认证四类用途,usages决定了该 profile 签出的叶子证书可用于哪些场景。
3. 创建证书签名请求(CSR)配置文件
names字段可按自身组织需求修改:
$ cat > ca-csr.json <<EOF { "CN": "Kubernetes", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "US", "L": "Portland", "O": "Kubernetes", "OU": "CA", "ST": "Oregon" } ] } EOF4. 生成 TLS Root CA 证书与密钥
$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca ca.pem ca-key.pem5. 验证根证书
检查Not Before/Not After时间窗符合预期,并确认其 X509v3 扩展包含CA:TRUE(即确实是一个合法的证书颁发机构):
$ openssl x509 -text -noout -in ca.pem Certificate: Data: Version: 3 (0x2) Serial Number: 6a:d4:d8:48:7f:98:4f:54:68:9a:e1:73:02:fa:d0:41:79:25:08:49 Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Oregon, L = Portland, O = Kubernetes, OU = CA, CN = Kubernetes Validity Not Before: Jul 10 15:21:00 2020 GMT Not After : Jul 9 15:21:00 2025 GMT Subject: C = US, ST = Oregon, L = Portland, O = Kubernetes, OU = CA, CN = Kubernetes Subject Public Key Info: ... X509v3 extensions: X509v3 Key Usage: critical Certificate Sign, CRL Sign X509v3 Basic Constraints: critical CA:TRUE X509v3 Subject Key Identifier: D4:38:B5:E2:26:49:5E:0D:E3:DC:D9:70:73:3B:C4:19:6A:43:4A:F2 ...实操建议与验证路径
- 部署后确认:cert-manager 清单由
kube模块以state: latest应用,重新执行cluster.yml(或--tags apps)即可完成版本升级;从源码结构看,升级时还会先清理旧 addon 目录,因此重复执行是安全的。 - DNS 出网受限环境:通过
cert_manager_dns_policy、cert_manager_dns_config指定自定义 nameservers(示例中为 1.1.1.1 / 8.8.8.8),并通过cert_manager_controller_extra_args追加--dns01-recursive-nameservers-only=true与--dns01-recursive-nameservers=...,避免 DNS01 挑战时 Pod 默认解析器把请求发往集群内不存在的 DNS。 - 专用节点调度:示例变量中给出了在控制平面节点上以 NoSchedule 容忍 + 权重 100 的 preferred 亲和运行的写法,以及
kubernetes.io/os: linux节点选择器,便于把 cert-manager 固定在合适的节点上。 - GKE Autopilot:此类环境禁止修改
kube-system命名空间,需将cert_manager_leader_election_namespace改为其他命名空间(该变量注释中亦明确了这一适用场景)。 - 验证 Issuer 链路:创建
ca-issuerClusterIssuer(CA 类型,指向前文部署的ca-key-pairSecret)后,应用带cert-manager.io/cluster-issuer: ca-issuer注解的 Ingress,再检查cert-manager命名空间中的 Certificate 状态与目标 Secret(如prometheus-dashboard-certs)是否按期更新,即可确认 ingress-shim 全链路工作正常。
小结
Kubespray 通过cert_manager_enabled一个开关即可把 cert-manager 1.15.3(controller + cainjector + webhook)以幂等方式装入集群;cert_manager_trusted_internal_ca把内部 CA 以 ConfigMap 挂载进 controller 完成部署级信任;配合 cfssl 生成的 Root CA 密钥对与 Ingress 注解,就能让 ingress-shim 为入口流量提供自动签发、自动轮换的 TLS 证书,或对接 ACME(含内部 ACME)完成免费公钥证书的全自动化管理。所有变量、任务与清单模板均可在上述相对路径中逐行核对:角色默认值在 defaults/main.yml,部署流程在 tasks/main.yml,清单渲染逻辑在 templates/cert-manager.yml.j2。
【免费下载链接】kubesprayDeploy a Production Ready Kubernetes Cluster项目地址: https://gitcode.com/GitHub_Trending/ku/kubespray
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考