1. Kubernetes集群运维实战概述
在生产环境中运行Kubernetes集群就像驾驶一艘远洋货轮——看似平稳航行的背后需要持续的系统维护和精细操作。作为过去三年管理过数十个生产级K8s集群的老水手,我总结出节点管理、证书更新和版本升级这三个最让运维团队头疼的"暗礁区"。本文将分享一套经过实战检验的完整操作方案,特别适合已经部署了Kubernetes但尚未建立系统维护流程的团队。
为什么这三个环节如此关键?节点管理不当会导致计算资源浪费或服务中断;证书过期直接造成集群瘫痪(我见过太多凌晨三点被证书过期报警叫醒的案例);而版本升级失败可能让整个集群回滚到初始状态。更棘手的是,这些操作往往相互关联——你可能需要在节点维护期间完成证书轮换,或者在升级版本时同步调整节点配置。
2. 节点全生命周期管理
2.1 节点健康状态监控体系
建立节点健康监控不能仅依赖Kubernetes自带的Ready状态。在我的实践中会部署以下检查层级:
基础资源监控:通过Node Exporter采集的指标包括:
# 关键磁盘空间指标示例 node_filesystem_avail_bytes{mountpoint="/",fstype!="tmpfs"} / node_filesystem_size_bytes{mountpoint="/",fstype!="tmpfs"} * 100 < 10当根分区使用率超过90%时触发预警,这种情况经常导致kubelet异常。
Kubernetes组件监控:使用自定义Probe检查kubelet、container runtime等核心服务:
# 检查kubelet健康状态的简单脚本 curl -sk https://${NODE_IP}:10250/healthz | grep "ok" || echo "kubelet unhealthy"网络连通性矩阵:通过NetworkPolicy和Service Mesh工具监控节点间的网络延迟和丢包率,这对分布式存储类应用尤为重要。
经验:为每个监控指标设置合理的告警阈值和静默期,避免由临时波动引发的告警风暴。我曾遇到一个集群因为默认的5分钟检测间隔导致告警延迟,最终演变成雪崩式故障。
2.2 节点维护的标准操作流程
当需要下线节点进行维护时,正确的驱逐(drain)操作顺序应该是:
标记节点不可调度:
kubectl cordon <node-name>优雅驱逐Pod:
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data这里的
--delete-emptydir-data会清理临时数据,避免残留数据占用空间。维护后重新上线:
kubectl uncordon <node-name>
实际案例:在为某金融客户执行内核升级时,我们发现直接drain会导致某些有本地存储的StatefulSet无法迁移。解决方案是提前通过annotation标记特殊Pod:
kind: Pod metadata: annotations: cluster-autoscaler.kubernetes.io/safe-to-evict: "false"2.3 节点自动修复方案
对于大规模集群,建议实现节点自愈能力。以下是基于Cluster API的自动修复流程:
通过MachineHealthCheck资源定义故障条件:
apiVersion: cluster.x-k8s.io/v1beta1 kind: MachineHealthCheck metadata: name: worker-node-healthcheck spec: clusterName: my-cluster unhealthyConditions: - type: Ready status: Unknown timeout: 5m - type: Ready status: "False" timeout: 15m结合AWS EC2 Auto Scaling或Azure VM Scale Sets实现自动替换。
关键点:新节点加入集群后需要预装必要的监控和安全组件,这可以通过kubeadm的join配置或自定义DaemonSet完成。
3. 证书管理深度解析
3.1 Kubernetes证书体系全貌
一个生产集群通常包含以下证书(以1年有效期为例):
| 证书类型 | 默认路径 | 关键作用 | 过期影响 |
|---|---|---|---|
| CA证书 | /etc/kubernetes/pki/ca.crt | 根证书 | 全部组件无法验证 |
| API Server | /etc/kubernetes/pki/apiserver.crt | 服务端认证 | API不可用 |
| etcd对等 | /etc/kubernetes/pki/etcd/peer.crt | etcd节点间通信 | etcd集群分裂 |
| kubelet客户端 | /var/lib/kubelet/pki/kubelet-client-current.pem | 访问API Server | 节点失联 |
3.2 手动更新证书的七个步骤
以更新API Server证书为例:
备份现有证书:
cp -r /etc/kubernetes/pki /etc/kubernetes/pki.backup生成新证书(注意SAN列表要完整):
openssl req -new -key apiserver.key -out apiserver.csr -subj "/CN=kube-apiserver" \ -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:kubernetes,DNS:kubernetes.default,..."))使用CA签署:
openssl x509 -req -in apiserver.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out apiserver.crt \ -days 365 -extensions SAN -extfile <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:kubernetes,..."))更新Secret(如果使用外部etcd):
kubectl -n kube-system create secret tls etcd-certs --cert=etcd.crt --key=etcd.key --dry-run=client -o yaml | kubectl apply -f -滚动重启控制平面组件:
docker restart kube-apiserver验证新证书:
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text | grep -A 1 "Validity"更新kubeconfig文件:
kubectl config set-cluster my-cluster --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true
血泪教训:曾经因为漏掉了Service Account的key pair更新,导致所有Pod无法访问API Server。现在我会用这个命令检查所有证书:
find /etc/kubernetes/pki -type f -name "*.crt" -exec openssl x509 -noout -dates -in {} \; | awk -F= '{print $2}' | sort
3.3 自动化证书轮换方案
对于Kubernetes 1.19+版本,可以启用kubelet自动证书轮换:
修改kubelet配置:
apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration rotateCertificates: true serverTLSBootstrap: true在Controller Manager启用相关特性:
apiVersion: kube-controller-manager.config.k8s.io/v1 kind: KubeControllerManagerConfiguration controllers: - "*" - "csr-signing" - "csr-approving" - "csr-cleaner"创建ClusterRoleBinding允许节点更新证书:
kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: auto-approve-csrs-for-group subjects: - kind: Group name: system:nodes apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: system:certificates.k8s.io:certificatesigningrequests:nodeclient apiGroup: rbac.authorization.k8s.io
4. 版本升级策略与实践
4.1 升级路径规划
Kubernetes版本支持策略要求N-2版本兼容,这意味着:
- 当前版本:1.24
- 可升级到:1.25或1.26
- 必须跳过:直接升级到1.27会存在风险
推荐升级顺序:
1.24.x → 1.25.y → 1.26.z4.2 控制平面升级详细步骤
使用kubeadm升级控制平面的标准流程:
升级kubeadm工具:
yum install -y kubeadm-1.25.0-0 --disableexcludes=kubernetes检查升级计划:
kubeadm upgrade plan输出会显示可升级版本和需要手动迁移的组件配置。
应用升级:
kubeadm upgrade apply v1.25.0逐个节点升级kubelet:
yum install -y kubelet-1.25.0-0 kubectl-1.25.0-0 --disableexcludes=kubernetes systemctl daemon-reload systemctl restart kubelet
关键检查点:
- 确保etcd版本兼容(kubeadm会自动处理)
- 检查API Deprecations列表
- 验证自定义资源定义(CRD)的apiVersion
4.3 工作节点滚动升级策略
对于超过50个节点的集群,建议采用分批次升级:
创建节点分组标签:
kubectl label nodes node-group-1 upgrade-group=group1使用DaemonSet控制并发度:
apiVersion: apps/v1 kind: DaemonSet metadata: name: node-upgrade-operator spec: updateStrategy: type: RollingUpdate rollingUpdate: maxUnavailable: 2通过PodDisruptionBudget保护关键应用:
apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: zk-pdb spec: maxUnavailable: 1 selector: matchLabels: app: zookeeper
4.4 升级后验证清单
完成升级后必须检查:
核心功能测试:
kubectl get --raw='/readyz?verbose'网络插件兼容性:
kubectl -n kube-system logs -l k8s-app=cilium存储卷测试:
kubectl exec -it test-pod -- df -h /data自定义资源验证:
kubectl get crd -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' | xargs -I {} kubectl get {} -A
5. 运维工具箱推荐
5.1 必备CLI工具
kubectl-neat:清理kubectl输出中的集群模板信息
kubectl get pod my-pod -o yaml | kubectl neatk9s:终端可视化工具,特别适合快速故障排查
stern:多Pod日志聚合工具
stern -n production "app.*" --since 10m
5.2 诊断脚本集锦
节点资源使用分析脚本:
kubectl get nodes --no-headers | awk '{print $1}' | xargs -I {} sh -c \ 'echo {}; kubectl describe node {} | grep -A 5 "Allocated resources"; echo'证书过期提醒脚本:
for cert in $(find /etc/kubernetes/pki -name "*.crt"); do echo "$cert expires on $(openssl x509 -enddate -noout -in $cert | cut -d= -f2)" done | sort -k 35.3 配置管理最佳实践
- 使用GitOps工具(如Argo CD)管理集群状态
- 所有kubeadm配置版本化存储
- 通过Policy-as-Code工具(如OPA)实施安全规范
在长期维护中,我发现将运维手册代码化能显著降低人为错误。比如把证书更新流程转化为Ansible Playbook,或使用Tekton构建升级流水线。记住,可靠的Kubernetes运维不是靠英雄主义,而是靠可重复的自动化流程。