Cert-Manager 安装与配置文档
Cert-Manager 安装与配置文档
本文档介绍如何在 Kubernetes 集群中安装和配置 Cert-Manager,用于自动管理 TLS 证书(支持 Let’s Encrypt)。
一、安装 Helm(如已安装可跳过)
# 下载安装脚本curl-fsSL-oget_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3# 赋予执行权限chmod700get_helm.sh# 执行安装./get_helm.sh# 验证安装helm version二、添加 Cert-Manager 仓库
# 添加 Jetstack 仓库helm repoaddjetstack https://charts.jetstack.io# 更新本地仓库缓存helm repo update# (可选) 搜索可用的 chart 版本helm search repo cert-manager-l三、下载 Chart 包(可选)
# 指定版本下载 Chart 包helm pull jetstack/cert-manager--versionv1.20.2# 解压 Chart 包(如需本地修改配置)tar-zxvfcert-manager-v1.20.2.tgzcdcert-manager四、安装 Cert-Manager
基础安装命令
helminstallcert-manager jetstack/cert-manager\--namespacecert-manager\--create-namespace\--versionv1.20.2\--setinstallCRDs=true使用国内镜像代理安装(推荐 测试失败,建议使用基础安装命令,后期再补充正确地址)
helminstallcert-manager jetstack/cert-manager\--namespacecert-manager\--create-namespace\--versionv1.20.2\--setinstallCRDs=true\--setimage.repository=k8s.m.daocloud.io/quay.io/jetstack/cert-manager-controller\--setwebhook.image.repository=k8s.m.daocloud.io/quay.io/jetstack/cert-manager-webhook\--setcainjector.image.repository=k8s.m.daocloud.io/quay.io/jetstack/cert-manager-cainjector\--setstartupapicheck.image.repository=k8s.m.daocloud.io/quay.io/jetstack/cert-manager-ctl验证安装
# 查看 Pod 状态kubectl get pods-ncert-manager# 等待所有 Pod 状态变为 Runningkubectlwait--for=condition=ready pod-lapp.kubernetes.io/name=cert-manager-ncert-manager--timeout=300s五、配置 ClusterIssuer(Let’s Encrypt)
Cert-Manager 支持多种域名所有权验证方式,最常用的是HTTP-01和DNS-01。
- HTTP-01:配置简单,但要求域名必须能够被公网访问(开放 80 端口),不支持泛域名证书。
- DNS-01:不需要公网访问网站,支持内网环境,支持泛域名证书(如
*.aioil.top),但需要配置 DNS 服务商的 API 密钥。
请根据你的实际情况选择以下其中一种方式进行配置。
方式一:使用 HTTP-01 挑战验证(单域名证书)
创建cluster-issuer-http01.yaml文件:
apiVersion:cert-manager.io/v1kind:ClusterIssuermetadata:name:letsencrypt-prod-http01spec:acme:# Let's Encrypt 生产环境地址server:https://acme-v02.api.letsencrypt.org/directory# 用于接收证书过期通知的邮箱email:xxx@hotmail.com# 用于存储 ACME 账户私钥的 SecretprivateKeySecretRef:name:letsencrypt-prod-http01# 使用 HTTP-01 挑战验证域名所有权# ⚠️ 重要提示:使用 HTTP-01 验证方式时,必须满足以下条件:# 1. 提前在 DNS 服务商处配置好域名的 A 记录,指向你的 Ingress 节点的公网 IP。# 2. 确保 Let's Encrypt 的服务器可以通过公网(80 端口)访问到该节点。solvers:-http01:ingress:class:nginx# 使用 nginx Ingress Controller应用配置:
kubectl apply-fcluster-issuer-http01.yaml方式二:使用 DNS-01 挑战验证(以阿里云 DNS 为例)
如果你使用的是阿里云 DNS,可以通过部署 webhook 来实现自动化 DNS 验证。
1. 部署 alidns-webhook
alidns-webhook负责处理与阿里云 DNS API 的交互逻辑。
# 添加并更新 helm 仓库helm repoaddcert-manager-alidns-webhook https://devmachine-fr.github.io/cert-manager-alidns-webhook helm repo update# 安装 webhookhelminstallalidns-webhook cert-manager-alidns-webhook/alidns-webhook\--namespacecert-manager\--create-namespace\--setgroupName=aioil.top# ⚠️ 注意:此处的 groupName 必须与 ClusterIssuer 配置中的 groupName 严格一致如果网络不好,可以下载 Helm 包进行离线安装:
wgethttps://github.com/DEVmachine-fr/cert-manager-alidns-webhook/releases/download/alidns-webhook-0.8.3/alidns-webhook-0.8.3.tgztarxvf alidns-webhook-0.8.3.tgzcdalidns-webhook helminstallalidns-webhook.\--namespacecert-manager\--create-namespace\--setgroupName=aioil.top注:groupName确保了 Cert-Manager 知道将验证任务转发给哪个 Webhook 处理。
2. 配置阿里云 DNS 权限
获取阿里云具有AliyunDNSFullAccess权限的 RAM 用户 AccessKey ID 和 Secret。
(⚠️ 安全警告:请遵循最小权限原则,并在 K8s Secret 中妥善保管。)
可以先将密钥进行 Base64 编码:
echo-n"你的AccessKeyID"|base64echo-n"你的AccessKeySecret"|base64创建alidns-secret.yaml:
apiVersion:v1kind:Secretmetadata:name:alidns-secretsnamespace:cert-managertype:Opaquedata:# 填入上述 base64 编码后的值access-token:<BASE64_ACCESS_KEY_ID>secret-key:<BASE64_ACCESS_KEY_SECRET>应用 Secret:
kubectl apply-falidns-secret.yaml3. 创建 DNS-01 ClusterIssuer
创建cluster-issuer-dns01.yaml文件:
apiVersion:cert-manager.io/v1kind:ClusterIssuermetadata:name:letsencrypt-prod-dnsspec:acme:email:xxx@hotmail.comserver:https://acme-v02.api.letsencrypt.org/directoryprivateKeySecretRef:name:letsencrypt-prod-dnssolvers:-dns01:webhook:config:accessTokenSecretRef:key:access-tokenname:alidns-secretsregionId:cn-beijingsecretKeySecretRef:key:secret-keyname:alidns-secrets# groupName 必须与 webhook 部署时配置的 groupName 一致groupName:aioil.topsolverName:alidns-solver应用配置:
kubectl apply-fcluster-issuer-dns01.yaml验证 ClusterIssuer 配置
# 查看所有 ClusterIssuerkubectl get clusterissuer# 查看 HTTP-01 ClusterIssuer 详细信息及状态(若配置了方式一)kubectl describe clusterissuer letsencrypt-prod-http01 kubectl get clusterissuer letsencrypt-prod-http01-owide# 查看 DNS-01 ClusterIssuer 详细信息及状态(若配置了方式二)kubectl describe clusterissuer letsencrypt-prod-dns kubectl get clusterissuer letsencrypt-prod-dns-owide六、测试 HTTPS 配置
1. 创建测试应用
创建my-nginx.yaml文件:
apiVersion:apps/v1kind:Deploymentmetadata:name:my-nginxspec:selector:matchLabels:run:my-nginxreplicas:2template:metadata:labels:run:my-nginxspec:containers:-name:my-nginximage:nginx:latestresources:limits:memory:"128Mi"cpu:"500m"ports:-containerPort:80---apiVersion:v1kind:Servicemetadata:name:nginx-servicespec:selector:run:my-nginxtype:ClusterIPports:-protocol:TCPport:8080targetPort:802. 独立申请 Certificate 证书(推荐)
不再依赖 Ingress 的 annotation 自动申请,而是提前创建一个独立的Certificate资源,这样可以方便地管理泛域名证书。
创建certificate-aioil.yaml文件:
apiVersion:cert-manager.io/v1kind:Certificatemetadata:name:aioil-top-tlsspec:secretName:aioil-top-tlscommonName:aioil.topdnsNames:-aioil.top-"*.aioil.top"issuerRef:name:letsencrypt-prod-dnskind:ClusterIssuer应用并查看证书状态:
kubectl apply-fcertificate-aioil.yaml kubectl describe certificate aioil-top-tls3. 创建支持 HTTPS 的 Ingress
这里提供两种配置 Ingress 的方式,请根据你的需求选择:
方式 A:直接引用独立证书(适用于 DNS-01 泛域名证书)
创建example-ingress.yaml文件,直接引用刚刚生成的aioil-top-tls证书:
apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:example-ingressannotations:nginx.ingress.kubernetes.io/rewrite-target:/$1spec:ingressClassName:nginxtls:-hosts:-nginx.aioil.topsecretName:aioil-top-tls# ✅ 直接用已有证书,无需 cert-manager.io/cluster-issuer 自动申请rules:-host:nginx.aioil.tophttp:paths:-path:/pathType:Prefixbackend:service:name:nginx-serviceport:number:8080方式 B:通过 Ingress 自动申请证书(适用于 HTTP-01 或自动按需申请)
如果你没有提前创建独立的Certificate资源,可以通过 Ingress 的 annotation 触发 Cert-Manager 自动签发证书。创建example-ingress-auto.yaml文件:
apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:example-ingress-autoannotations:# 启用 Cert-Manager 自动颁发证书# ⚠️ 注意:指定你创建的 ClusterIssuer 的名称(如果是 HTTP-01 则填写 letsencrypt-prod-http01,如果是 DNS-01 则填写 letsencrypt-prod-dns)cert-manager.io/cluster-issuer:"letsencrypt-prod-http01"nginx.ingress.kubernetes.io/rewrite-target:/$1spec:ingressClassName:nginxtls:-hosts:-nginx.aioil.top# 你的域名secretName:nginx.aioil.top-tls# 自动生成的证书将会保存在这个 Secret 中rules:-host:nginx.aioil.tophttp:paths:-path:/pathType:Prefixbackend:service:name:nginx-serviceport:number:80804. 应用配置并验证
# 部署测试应用和 Ingresskubectl apply-fmy-nginx.yaml kubectl apply-fexample-ingress.yaml# 查看证书申请状态kubectl get certificate-ndefault kubectl describe certificate aioil-top-tls# 查看证书 Secretkubectl get secret aioil-top-tls# 验证证书自动续期机制# 查看输出中的 Not After (过期时间) 和 Renewal Time (计划续期时间)kubectl describe certificate aioil-top-tls-ndefault# 示例输出(关键部分):# ...# Not After: 2026-08-17T13:06:43Z# Not Before: 2026-05-19T13:06:44Z# Renewal Time: 2026-07-18T13:06:43Z# Revision: 1# ...# 上述输出表明:Cert-Manager 将在证书到期前自动发起证书更新。# 测试 HTTPS 访问(将 nginx.aioil.top 解析到 Ingress 节点 IP)curl-vhttps://nginx.aioil.top七、签发状态追踪与故障排查
Cert-manager 的签发流程是多步的,涉及Certificate->CertificateRequest->Order->Challenge。需要追踪这些中间状态进行排查。
1. 追踪证书签发流程
使用kubectl describe是最强大的追踪工具。
步骤 1: 检查 Certificate 状态
检查是否成功引用了 Issuer,以及是否创建了请求。
kubectl describe certificate aioil-top-tls-ndefault关注Events和Status.Conditions。如果一切正常,它会显示Ready: False,然后是创建CertificateRequest的事件。
步骤 2: 检查 CertificateRequest (CR)
CR 是 Cert-manager 发起的实际请求。
kubectl describe certificaterequest-ndefaultCR 会引用一个Order。
步骤 3: 检查 Order (订单)
Order资源代表与 ACME 服务器(Let’s Encrypt)协商签发证书的订单。
kubectl describe order-ndefault关注Status.State。订单状态会从pending变为ready或valid。如果卡在pending,通常是因为挑战尚未完成。
步骤 4: 检查 Challenge (挑战)
Challenge资源描述了具体的验证方法(此处为 DNS-01)。这是 Cert-manager 与 Webhook 交互的关键点。
kubectl describe challenge-ndefault如果挑战状态显示Presenting,则说明 Cert-manager 已经将请求转发给 alidns-webhook,要求它去创建 TXT 记录。
2. 查看日志进行故障排查
如果挑战卡住或失败,我们需要检查两个关键 Pod 的日志:
A. Cert-manager Controller 日志:
确认 Cert-manager 是否正确处理了资源对象,以及与 ACME 服务器的通信是否正常。
kubectl logs-f-ncert-manager deploy/cert-manager--tail100B. alidns-webhook 日志:
检查 Webhook 是否接收到了挑战请求,以及它调用阿里云 DNS API 时是否遇到了鉴权或网络错误。
kubectl logs-f-ncert-manager deploy/alidns-webhook--tail100例如,如果 alidns-webhook 日志中出现类似Forbidden或InvalidAccessKeyId,则说明alidns-secrets中的凭证是错误的或权限不足。如果看到成功添加 TXT 记录的日志,则挑战很快会完成。
3. 验证最终 Secret
当Certificate资源的Ready状态变为True时,证书签发成功。
kubectl get secret aioil-top-tls-ndefault# 验证 Secret 中包含 tls.crt, tls.key 等字段通过这一套流程,我们成功地将证书管理从人工干预中解耦出来,实现了 K8s 证书的自动化生命周期管理。
八、其他常见问题
1. 证书申请一直处于 Pending 状态
# 查看 Certificate 详情kubectl describe certificate aioil-top-tls# 查看 Challenge 状态(HTTP-01 验证)kubectl get challenges kubectl describe challenge<challenge-name># 常见原因:# 1. 域名未解析到 Ingress 节点 IP (HTTP-01)# 2. Ingress Controller 未正确配置 (HTTP-01)# 3. Webhook 权限配置错误 (DNS-01)2. 证书过期未自动续期
# 检查 cert-manager Pod 日志kubectl logs-ncert-manager deployment/cert-manager# 手动触发续期(删除 Certificate 的 Secret 会自动重建)kubectl delete secret aioil-top-tls-ndefault# 或使用 annotations 强制触发轮换(推荐方式)kubectl annotate certificate aioil-top-tls-ndefault cert-manager.io/force-renewal=true--overwrite3. 国内镜像拉取失败
# 检查镜像是否正确拉取crictl images|grepcert-manager# 如果未拉取,手动拉取镜像crictl pull k8s.m.daocloud.io/quay.io/jetstack/cert-manager-controller:v1.20.2# 重新打标签crictl tag k8s.m.daocloud.io/quay.io/jetstack/cert-manager-controller:v1.20.2 quay.io/jetstack/cert-manager-controller:v1.20.2