k8s 运维与故障排查

导读
生产级集群的稳定性依赖成熟的运维手段与可复用的排障路径。本文覆盖集群升级策略、etcd 与 Velero 备份恢复、分层故障诊断方法论,以及 kubectl debug 临时容器等实战技能。掌握这些内容,能在事故发生时快速定位根因并恢复服务。
核心概念
集群升级有三条主流路径。滚动升级通过 kubeadm 逐个节点升级控制面与工作节点,期间业务 Pod 被驱逐再重建,适合大多数场景。蓝绿升级额外维护一套备用集群,流量整体切换,回滚快但资源成本翻倍。金丝雀升级把新版本先导入少量节点或少量流量,观察指标无异常后再全量推进,适合对稳定性要求极高的核心业务。三种策略的选择本质上是停机容忍度与资源成本的权衡。
备份恢复是运维的最后一道防线。etcd 存储了集群所有状态数据,其快照是集群级恢复的基础。Velero 则面向工作负载,能把命名空间、Deployment、ConfigMap 等资源 YAML 连同 PV 卷快照一并备份到对象存储。两者互补:etcd 备份应对控制面灾难,Velero 备份应对应用级误删与迁移。
故障诊断需要分层方法。Kubernetes 的声明式模型让问题往往层层传递:Pod 异常可能源于调度失败,调度失败可能源于节点资源不足,节点资源不足可能源于上层资源配额。从 Pod 状态出发,逐层上溯到节点与集群,能避免在错误层级打转。下图把常见 Pod 异常状态拆成四条诊断分支。
图 1 给出了从 Pod 异常出发的四分支决策树。Pending 指向调度层问题,根因集中在资源与调度策略;CrashLoopBackOff 指向应用层问题,需查看前一次容器退出日志;ImagePullBackOff 指向镜像与仓库层问题;Evicted 指向节点压力,根因多为磁盘或内存耗尽。每条分支都对应一组确定的诊断命令与根因方向,避免无目的试探。
图解原理
Velero 由服务端 Controller 与客户端 CLI 组成,是 Kubernetes 原生的备份恢复工具。它的核心思路是把集群状态拆成两类产物分别持久化:一类是 Kubernetes 资源的 YAML 清单,另一类是持久卷的快照。两类产物都写入对象存储,恢复时再从对象存储反向拉取重建。下图刻画了这条双向数据流的完整路径。
图 2 展示了 Velero 备份与恢复的双向数据流。备份阶段资源 YAML 与卷快照并行写入对象存储,互不依赖,任一失败不影响另一份产物。恢复阶段两者从对象存储反向拉取,资源重建与卷数据恢复同步推进。这种分离设计让跨集群迁移成为可能,只要目标集群能访问同一对象存储桶并安装对应 CSI 驱动,即可恢复完整工作负载。
kubectl debug 通过注入临时容器(Ephemeral Container)到目标 Pod 实现排障。临时容器不修改 Pod 规约、不参与重启循环,而是共享目标 Pod 的网络与存储命名空间,特别适合诊断 distroless 或精简镜像里无法安装排障工具的场景。容器退出后自动清理,不留痕迹。
动手实操
运维操作的落地依赖准确的命令序列。以下按 etcd 备份、Velero 工作负载备份、分层诊断与临时容器四个场景给出可复用的命令模板,所有命令均基于 kubectl 与对应工具 CLI。生产环境执行前应在测试集群验证参数与权限。
etcd 快照备份与恢复
# 在任一 etcd 节点执行快照
ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-snapshot.db \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/etcd/ca.crt \
--cert=/etc/etcd/server.crt \
--key=/etc/etcd/server.key
# 验证快照完整性
ETCDCTL_API=3 etcdctl snapshot status /backup/etcd-snapshot.db -w table
# 灾难恢复:停止 etcd 后用快照恢复成员数据目录
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot.db \
--data-dir=/var/lib/etcd-restored恢复后需将该目录指向 etcd 静态 Pod 配置并重启 kubelet,控制面才会基于恢复的数据重新拉起。整个恢复过程要求先停止所有 etcd 成员,属于停机操作,因此 etcd 快照恢复只用于灾难场景。日常运维的细粒度恢复应交给 Velero 按命名空间粒度处理。
Velero 安装与备份
# 安装 Velero CLI 后,连接 S3 兼容对象存储部署服务端
velero install \
--provider aws \
--bucket k8s-backup \
--backup-location-config region=us-east-1 \
--snapshot-location-config region=us-east-1 \
--secret-file credentials-velero
# 按命名空间创建备份,包含卷快照
velero backup create app-backup --include-namespaces production --snapshot-volumes
# 查看备份状态与详情
velero backup describe app-backup --details
# 恢复到目标集群
velero restore create --from-backup app-backup备份创建后用 describe 查看 Hooks 与卷快照状态,确认 VolumeSnapshots 资源已生成。跨集群恢复时目标集群需安装相同 CSI 驱动并配置同一对象存储访问凭证。恢复默认按备份顺序重建资源,可通过 –restore-volumes 控制是否恢复卷数据。
分层故障诊断命令
# Pod 层:查看状态、事件与日志
kubectl get pod <pod-name> -n <ns>
kubectl describe pod <pod-name> -n <ns>
kubectl logs <pod-name> -n <ns> --previous --tail=100
# 节点层:查看资源占用与压力状况
kubectl describe node <node-name>
kubectl get --raw /api/v1/nodes/<node-name>/proxy/stats/summary
# 集群层:检查关键组件与节点就绪状态
kubectl get cs
kubectl get nodes -o widedescribe 的 Events 段按时间倒序排列,最近的调度与拉取事件排在最前。节点 stats 接口能拿到容器运行时的实时资源占用,比 kubectl top 更细。控制面组件异常时优先查 kube-apiserver 与 kube-scheduler 的日志。
kubectl debug 临时容器
# 给运行中的 Pod 注入带排障工具的临时容器
kubectl debug -it <pod-name> --image=busybox:1.36 --target=<container-name> -n <ns>
# 在节点上创建调试 Pod,共享节点命名空间
kubectl debug node/<node-name> -it --image=ubuntu:22.04–target 指定共享进程命名空间的容器,便于在不进入目标容器内部的前提下诊断其进程。节点级调试会创建特权 Pod 挂载节点文件系统,适合排查 CNI、容器运行时等节点级问题。临时容器不写入 Pod 规约,退出后随 Pod 生命周期清理,不污染声明式配置。
常见问题与避坑
升级阶段,滚动升级期间若 PodDisruptionBudget 设置过严,节点驱逐会卡住导致升级停滞;金丝雀升级若缺乏自动指标门控,异常版本可能被手动全量铺开。升级前应核对 PDB 与节点冗余度,保证每个工作负载在驱逐后仍有足够副本承接流量。控制面升级前必须完成 etcd 快照,这是升级失败的唯一回滚依据。
备份环节,Velero 默认不备份不带 PV 的临时数据,依赖 emptyDir 的有状态应用恢复后会丢数据。etcd 快照恢复属于集群级操作,会覆盖现有全部状态,破坏性远超想象。生产环境应在隔离的恢复集群验证快照完整性后再切流,切勿直接在原集群覆盖恢复。
排障阶段,CrashLoopBackOff 的日志需用 –previous 参数读取上一次退出容器,直接 kubectl logs 往往只能看到空输出。Pending 状态要优先看 describe 的 Events 段而非日志,调度拒绝原因都记录在那里。节点 Evicted 的 Pod 不会自动删除,堆积后会干扰调度判断,需定期清理 pod-phase=Failed 的残留对象。
小结与进阶
运维的本质是用可复用的流程把不确定性收敛为确定操作——升级走灰度、备份分两层、排障按状态分支逐层定位,Kubernetes 的复杂度终将被这套纪律驯服。