Skip to content

cert-manager

2 posts with the tag “cert-manager”

K8s 焦土政策:网关与证书系统的终极卸载指南

这是一份针对 Kubernetes 集群的**“彻彻底底、连根拔起”**清理方案。

当你的网关和证书系统因为各种改动搅得一团糟,且面临诸如 ArgoCD 陷入死锁、命名空间卡在 Terminating 无法删除等极其顽固的底层状态错误时,**“焦土政策(物理核平)”**绝对是最有效、最干净的排障手段。

严格按照以下顺序执行。这套连招能保证把系统里的残留基因拔得干干净净,绝不影响下一次重装。


☢️ 第一阶段:斩断源头 (切断 ArgoCD 重建链)

Section titled “☢️ 第一阶段:斩断源头 (切断 ArgoCD 重建链)”

在使用 GitOps (如 ArgoCD) 时,决不能直接去删底层资源,否则 ArgoCD 会发现“建筑没了”,并立刻把它们重新拉起来。我们必须先切断图纸的下发。

Terminal window
kubectl delete application cert-manager traefik -n argocd

2. 遭遇死锁?强行剥夺 ArgoCD 的遗愿清单

Section titled “2. 遭遇死锁?强行剥夺 ArgoCD 的遗愿清单”

如果上面的命令卡住转圈(报错 metadata.finalizers: Forbidden),说明 ArgoCD 本身陷入了死结。立刻打开新终端,执行强制“拔管”:

Terminal window
kubectl patch application cert-manager -n argocd -p '{"metadata": {"finalizers": null}}' --type merge
kubectl patch application traefik -n argocd -p '{"metadata": {"finalizers": null}}' --type merge

执行后,ArgoCD 面板上的应用会瞬间消失,系统不再自动重建。


💣 第二阶段:深度扫荡 (清理 Webhooks 与 全局 CRDs)

Section titled “💣 第二阶段:深度扫荡 (清理 Webhooks 与 全局 CRDs)”

这是 99% 的人重装失败的根源! 命名空间好删,但全局注册的蓝图规范(CRD)和拦截器(Webhook)如果不清空,下次安装必定会报出各种版本冲突。

Cert-manager 会向 K8s API Server 注入拦截器,必须优先干掉,否则它会拦截你接下来的所有安装请求:

Terminal window
kubectl delete validatingwebhookconfiguration cert-manager-webhook --ignore-not-found
kubectl delete mutatingwebhookconfiguration cert-manager-webhook --ignore-not-found
Terminal window
# 删光 Traefik 和 Cert-manager 的残留基因
kubectl get crd -o name | grep -E 'traefik|cert-manager' | xargs kubectl delete

3. 扫荡残留的“全局权限” (RBAC)

Section titled “3. 扫荡残留的“全局权限” (RBAC)”

这一步经常被忽视,导致重装时报 Ownership/Adoption 错误:

Terminal window
# 清理集群级别的角色与绑定
kubectl get clusterrole,clusterrolebinding -o name | grep -E 'cert-manager|traefik' | xargs kubectl delete
# 清理隐藏在 kube-system 核心区的领导者选举权限
kubectl get role,rolebinding -o name -n kube-system | grep cert-manager | xargs -I {} kubectl delete {} -n kube-system

🧨 第三阶段:核平街区 (强制清理 Namespace 内部残留)

Section titled “🧨 第三阶段:核平街区 (强制清理 Namespace 内部残留)”

如果你发现 Namespace 删不掉,或者里面总剩下一堆 Role, Service, ServiceAccount,那是它们身上带着 Finalizers(保护锁)

在删除 Namespace 之前,先手动清除这些顽固住户的遗愿清单:

Terminal window
# 定义目标命名空间
TARGET_NS=("cert-manager" "traefik")
for ns in "${TARGET_NS[@]}"; do
echo "正在强制碎锁 $ns 中的局部资源..."
# 批量清除 Role, RoleBinding, ServiceAccount, Service 的保护锁
kubectl get rolebinding,role,serviceaccount,service -n $ns -o name | xargs -I {} kubectl patch {} -n $ns -p '{"metadata":{"finalizers":null}}' --type merge
done

现在执行删除指令,由于内部资源已碎锁,它们会随街区一并消失:

Terminal window
kubectl delete namespace cert-manager traefik --force --grace-period=0

💀 第四阶段:物理超度 (清理僵尸命名空间)

Section titled “💀 第四阶段:物理超度 (清理僵尸命名空间)”

如果执行完第三步,使用 kubectl get ns 发现它们依然死死卡在 Terminating 状态,说明遭遇了**“僵尸命名空间”**。动用最后的 API 接口直连手段:

Terminal window
kubectl proxy &

2. 发射核弹指令,清空命名空间的 Finalizers

Section titled “2. 发射核弹指令,清空命名空间的 Finalizers”

直接调用 API 接口,强行抹除 Namespace 最后的执念:

Terminal window
# 针对 cert-manager
curl -H "Content-Type: application/json" -X PUT --data-binary "{\"kind\":\"Namespace\",\"apiVersion\":\"v1\",\"metadata\":{\"name\":\"cert-manager\"},\"spec\":{\"finalizers\":[]}}" http://localhost:8001/api/v1/namespaces/cert-manager/finalize
# 针对 traefik
curl -H "Content-Type: application/json" -X PUT --data-binary "{\"kind\":\"Namespace\",\"apiVersion\":\"v1\",\"metadata\":{\"name\":\"traefik\"},\"spec\":{\"finalizers\":[]}}" http://localhost:8001/api/v1/namespaces/traefik/finalize
Terminal window
# 确认僵尸已经彻底消失
kubectl get ns
# 杀掉后台开启的 kubectl proxy
kill %1

💡 架构师总结 走完这完整的四阶段,你的集群就真正回到了**“像素级纯净”**的状态。所有的 Role、ServiceAccount 和全局权限都已化为灰烬。现在,你可以放心地去推送你配置了 OpenDNS 5353 端口 的新图纸,享受一次零报错的全新丝滑安装体验!

K8s 证书避坑指南:如何安全地测试并申请 Let's Encrypt 泛域名证书

在 Kubernetes 集群中,使用 cert-manager 配合 Let’s Encrypt 自动签发免费的 HTTPS 泛域名证书,是目前的业界标配。

但是,无数新手在第一次配置时都会踩进一个**“死亡陷阱”**:Let’s Encrypt 对正式接口有极其严格的速率限制。如果你因为 DNS 配置填错、Token 权限不对等原因导致申请失败超过 5 次,你的域名将被拉黑封锁 1 个小时;如果反复重试,甚至会被封锁 7 天!

为了避免“坠机”,最标准、最专业的做法是:先用测试服 (Staging) 跑通流程,再切换到正式服 (Production)。

今天这篇文章,就带你完整走一遍这个“演习到转正”的标准全流程。


🚦 第一阶段:使用 Staging (测试服) 进行实战演习

Section titled “🚦 第一阶段:使用 Staging (测试服) 进行实战演习”

Let’s Encrypt 提供了一个专门的 Staging 测试环境,它的请求限制极其宽松,你可以随便报错、随便重试,绝对不会封锁你的域名。

我们的第一步,就是写一份指向测试服的图纸。

创建一个名为 cluster-issuer-and-cert.yaml 的文件。请注意看代码中的注释,有 3 个地方是测试服独有的

# 1. 声明一个测试服的“发证机关” (ClusterIssuer)
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging # 🧪 标志 1:命名为 staging
spec:
acme:
# 🧪 标志 2:必须使用 Staging 的 API 地址!
server: [https://acme-staging-v02.api.letsencrypt.org/directory](https://acme-staging-v02.api.letsencrypt.org/directory)
email: your-email@example.com # ⚠️ 替换为你的真实邮箱,用于接收过期通知
privateKeySecretRef:
# 🧪 标志 3:测试服专用的账号私钥名称,千万别和正式服重名
name: letsencrypt-staging-account-key
solvers:
- dns01:
cloudflare: # 这里以 Cloudflare DNS 验证为例
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token
---
# 2. 提交一份“证书申请单” (Certificate)
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: my-website-tls
namespace: default # ⚠️ 替换为你网关 (如 Traefik/Nginx) 所在的命名空间
spec:
secretName: my-website-tls # 最终生成的证书 Secret 名称
issuerRef:
# 🧪 标志 4:指定上面那个测试服发证机关来处理这张单子
name: letsencrypt-staging
kind: ClusterIssuer
commonName: "*.example.com" # ⚠️ 替换为你的域名
dnsNames:
- "example.com"
- "*.example.com"

将上面的配置应用到集群中:

Terminal window
kubectl apply -f cluster-issuer-and-cert.yaml

接下来,我们不需要去浏览器里看,直接在终端里盯着它的状态:

Terminal window
# 监控证书状态 (将 default 换成你自己的 namespace)
kubectl get certificate my-website-tls -n default -w
  • 成功标志:当你看到 READY 这一列从 False 变成了 True,恭喜你,演习大获全胜!这证明你的 DNS Token 和底层网络链路已经 100% 跑通。

  • 终极查验 (彻底放心):如果你想彻底确认这张申请下来的证书到底是谁发的,建议使用以下兼容性最强的“临时文件法”进行查验:

    Terminal window
    # 1. 提取 Secret 中的证书内容,解码后存入临时文件
    kubectl get secret my-website-tls -n default -o jsonpath='{.data.tls\.crt}' | base64 -d > /tmp/cert_verify.crt
    # 2. 调用 openssl 物理查验该文件并过滤颁发者
    openssl x509 -in /tmp/cert_verify.crt -text -noout | grep "Issuer"
    # 3. 查完即焚,删除临时文件
    rm /tmp/cert_verify.crt

    预计输出结果:

    • 演习环境 (Staging):输出包含 Issuer: ..., CN=(STAGING) Artificial Apricot R3

      这证明 Let’s Encrypt 已经认可了你的域名所有权,并把测试用的“假证书”发给你了。

    • 正式环境 (Production):输出包含 Issuer: ..., CN=R3 (没有 STAGING 字样)。

      这说明你的正式绿锁已经下发。

🚀 第二阶段:销毁假证,正式转正 (Production)

Section titled “🚀 第二阶段:销毁假证,正式转正 (Production)”

既然流程已经跑通,我们就可以放心大胆地去正式服领真绿锁了。

回到你刚才的 cluster-issuer-and-cert.yaml 文件,把那 4 个测试服的标志全部改掉:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod # ✅ 1. 改为 prod
spec:
acme:
# ✅ 2. 换成 Let's Encrypt 的正式服 API
server: [https://acme-v02.api.letsencrypt.org/directory](https://acme-v02.api.letsencrypt.org/directory)
email: your-email@example.com
privateKeySecretRef:
name: letsencrypt-prod-account-key # ✅ 3. 换个正式的工作证名称
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: my-website-tls
namespace: default
spec:
secretName: my-website-tls
issuerRef:
name: letsencrypt-prod # ✅ 4. 向正式服机关提交申请
kind: ClusterIssuer
commonName: "*.example.com"
dnsNames:
- "example.com"
- "*.example.com"

再次应用配置:

Terminal window
kubectl apply -f cluster-issuer-and-cert.yaml

2. 【核心必做】物理销毁旧证书!

Section titled “2. 【核心必做】物理销毁旧证书!”

这是无数人翻车的一步! 虽然你修改了申请单,但 Kubernetes 发现你的系统里已经存在一个叫 my-website-tls 的 Secret(刚才测试服发的那个),并且还没过期,它很可能不会去触发重新签发

你必须手动把那个假证书“撕毁”,倒逼 cert-manager 重新去正式服申请:

Terminal window
# 删除测试服生成的假证书 Secret
kubectl delete secret my-website-tls -n default

删掉假证书后,cert-manager 会立刻反应过来:“哎呀,证书没了,而且现在的发证机关变成了 Prod,我得赶紧去申请一张新的!”

再次查看状态:

Terminal window
kubectl get certificate my-website-tls -n default -w

由于之前的网络链路已经验证过完全没问题,这次的申请会极快通过。当状态再次变为 READY: True 时,刷新你的浏览器页面(建议使用无痕模式清除缓存)。

那把坚不可摧、受全球所有设备信任的 HTTPS 绿色小锁,就已经完美挂在你的域名上了!


💡 总结: 无论是个人折腾还是企业级部署,先用 Staging 测试,再切 Prod 签发,最后 delete secret 强制重签,这套“三步走”战略能帮你避开 99% 的证书签发雷区。