给K8S证书上个闹钟:使用kubeadm certs check-expiration实现自动化证书巡检与续期
Kubernetes证书生命周期管理从预警到续期的全链路实践当你凌晨三点被报警短信惊醒发现整个Kubernetes集群因为证书过期而瘫痪时那种绝望感足以让任何运维人员刻骨铭心。证书过期这类低级错误每年都在重复上演而预防措施往往被排到待办清单的末尾——直到灾难真正发生。1. 证书过期Kubernetes集群的隐形杀手2017年某跨国电商平台因Kubernetes证书过期导致全球服务中断12小时直接损失超过800万美元。事后分析显示他们的监控系统覆盖了节点状态、Pod健康度和API响应时间却唯独漏掉了证书有效期这个基础指标。Kubernetes集群依赖多种证书维持安全通信主要包括证书类型用途默认有效期apiserverAPI服务器服务端认证1年apiserver-kubelet-clientAPI服务器访问kubelet的客户端认证1年etcd-serveretcd集群内部通信1年admin.conf集群管理员kubeconfig文件1年front-proxy-client聚合API的前端代理认证1年这些证书就像定时炸弹到期后会导致各种诡异现象Unable to connect to the server: x509: certificate has expired- kubectl完全失效控制器管理器无法与API服务器通信导致Deployment停止更新节点被错误标记为NotReady状态新节点无法加入集群最危险的是CA证书通常有效期10年过期时整个集群将无法通过简单续期恢复需要重建集群。这正是为什么我们需要建立系统的证书管理流程。2. 构建证书健康度监控体系2.1 基础检查工具kubeadm certs check-expirationKubeadm自1.18版本起提供了专业的证书检查命令kubeadm certs check-expiration典型输出示例CERTIFICATE EXPIRES RESIDUAL TIME admin.conf Dec 30, 2023 08:15 UTC 364d apiserver Dec 30, 2023 08:15 UTC 364d apiserver-etcd-client Dec 30, 2023 08:15 UTC 364d这个命令实际上读取的是/etc/kubernetes/pki目录下的证书文件因此即使API服务器不可用也能执行检查。对于生产环境建议每月至少运行一次该命令。2.2 自动化监控方案方案一Prometheus Alertmanager监控栈创建证书检查的Exporter脚本cert-exporter.sh#!/bin/bash # 获取所有证书过期时间 kubeadm certs check-expiration --config/etc/kubernetes/kubeadm-config.yaml | \ awk /CERTIFICATE/{flag1;next}/CERTIFICATE AUTHORITY/{flag0}flag | \ grep -v EXTERNALLY MANAGED /tmp/cert-expiry.txt # 转换为Prometheus指标格式 echo # HELP kube_cert_expiry_timestamp Certificate expiry timestamp echo # TYPE kube_cert_expiry_timestamp gauge while read -r line; do cert$(echo $line | awk {print $1}) expiry$(echo $line | awk {print $2 $3 $4 $5 $6}) timestamp$(date -d $expiry %s) echo kube_cert_expiry_timestamp{cert\$cert\} $timestamp done /tmp/cert-expiry.txt配置Node Exporter的textfile收集器# /etc/systemd/system/cert-exporter.service [Unit] DescriptionCertificate Exporter Afternetwork.target [Service] ExecStart/opt/scripts/cert-exporter.sh Userroot Grouproot Restartalways [Install] WantedBymulti-user.target设置Alertmanager规则groups: - name: certificate-alerts rules: - alert: KubernetesCertificateExpiringSoon expr: (kube_cert_expiry_timestamp - time()) / 86400 30 for: 5m labels: severity: warning annotations: summary: Kubernetes certificate will expire soon (instance {{ $labels.instance }}) description: Certificate {{ $labels.cert }} will expire in {{ $value }} days方案二CronJob定期检查对于没有监控系统的环境可以创建Kubernetes CronJobapiVersion: batch/v1 kind: CronJob metadata: name: cert-checker spec: schedule: 0 3 * * * # 每天凌晨3点运行 jobTemplate: spec: template: spec: containers: - name: checker image: bitnami/kubectl:latest command: - /bin/sh - -c - | kubectl get nodes if [ $? -ne 0 ]; then echo 集群可能已因证书过期而不可用 exit 1 fi kubeadm certs check-expiration | grep -v EXTERNALLY MANAGED | \ awk $6 ~ /d/ {if ($50 30) print 警告: $1 证书将在$5天后过期} restartPolicy: OnFailure3. 证书续期操作指南3.1 标准续期流程当检测到证书即将过期时执行以下完整流程准备工作备份关键配置cp -r /etc/kubernetes /etc/kubernetes_backup cp -r $HOME/.kube/config $HOME/.kube/config_backup确保有足够的磁盘空间至少100MB空闲执行续期kubeadm certs renew all --config/etc/kubernetes/kubeadm-config.yaml更新kubeconfigsudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config重启控制平面组件# 对于使用systemd的环境 systemctl restart kubelet # 对于容器化部署 docker ps | grep -E kube-apiserver|kube-controller-manager|kube-scheduler | \ grep -v pause | awk {print $1} | xargs docker restart3.2 特殊场景处理场景一证书已过期导致集群不可用此时kubectl命令会报x509: certificate has expired错误需要直接操作控制平面节点手动备份并删除旧证书mv /etc/kubernetes/pki/apiserver.{crt,key} ~/强制生成新证书kubeadm certs renew apiserver --config/etc/kubernetes/kubeadm-config.yaml重启API服务器容器crictl ps | grep kube-apiserver | awk {print $1} | xargs crictl restart场景二大规模集群的滚动更新对于多控制平面集群建议采用分阶段更新在一个控制节点上执行kubeadm certs renew all将该节点上的/etc/kubernetes/pki目录内容同步到其他控制节点rsync -avz /etc/kubernetes/pki/ control-plane-2:/etc/kubernetes/pki/逐个重启各节点的控制平面组件4. 高级维护策略4.1 自定义证书有效期通过修改kubeadm配置文件可以调整证书有效期apiVersion: kubeadm.k8s.io/v1beta3 kind: ClusterConfiguration certificateValidityPeriod: 8760h # 1年改为2年然后重新生成证书kubeadm certs renew all --configkubeadm-config.yaml注意延长有效期会降低安全性建议配合自动化更新使用4.2 完全自动化方案结合GitOps工作流实现全自动证书管理创建证书检查的Pipeline# .gitlab-ci.yml stages: - cert-check cert-monitor: stage: cert-check image: bitnami/kubectl script: - kubectl get secret -n cert-manager | grep kubernetes.io/tls - kubeadm certs check-expiration | tee cert-status.txt - grep -q RESIDUAL TIME.*[0-9]d cert-status.txt exit 1 || exit 0 allow_failure: true设置自动续期工作流# cert-renewer.py import subprocess from datetime import datetime, timedelta def check_certs(): result subprocess.run( [kubeadm, certs, check-expiration], capture_outputTrue, textTrue) for line in result.stdout.split(\n): if RESIDUAL TIME in line and d in line: days_left int(line.split()[5].replace(d, )) if days_left 30: renew_certs() def renew_certs(): subprocess.run([kubeadm, certs, renew, all]) # 触发ArgoCD同步 subprocess.run([argocd, app, sync, cluster-components])4.3 证书轮换的最佳实践时间规划在证书到期前30天开始监控告警提前15天执行非业务时间的更新测试提前7天执行生产环境更新验证步骤# 检查新证书有效期 openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates # 验证API连通性 kubectl --insecure-skip-tls-verify get nodes # 检查组件日志 journalctl -u kube-apiserver -n 50 | grep -i cert回滚方案# 如果更新后出现问题 cp -r /etc/kubernetes_backup/* /etc/kubernetes/ systemctl restart kubelet在管理Kubernetes证书的三年里我总结出一个铁律证书不会在你方便的时候过期它只会在最糟糕的时刻失效。建立完善的证书监控体系就像给集群上了保险——平时感觉不到它的存在但当危机来临时你会庆幸自己做了正确准备。