7 月 Kubernetes 排障 Top 10:最常踩的坑与最快的解法

📅 2026/7/27 10:57:06 👁️ 阅读次数 📝 编程学习
7 月 Kubernetes 排障 Top 10:最常踩的坑与最快的解法

7 月 Kubernetes 排障 Top 10:最常踩的坑与最快的解法

一、一个月 47 张工单背后的共同模式

七月团队共处理 Kubernetes 相关排障工单 47 张,平均每天超过 1.5 张。对 47 张工单做归类后发现,Top 10 问题占据了总量的 83%。每个问题的共性是:根因往往不是 Kubernetes 本身的 Bug,而是配置不当、资源边界理解不足、或者对控制器行为预期偏差。

以下按频率降序排列,每一类问题都给出最直接的排查路径和修复方案。基础设施领域的排障不需要走弯路——知道往哪个方向看,问题就解决了一半。

二、排障全景:Top 10 问题的归类与分布

问题一:ImagePullBackOff 与镜像拉取失败(14 张)

频率最高的问题,七月中 30% 的工单与此相关。最常见的三个根因:Secret 中 Docker config 过期(40%)、镜像仓库网络不可达(35%)、imagePullPolicy 为 Always 但本地已有镜像的节点重启后反复拉取(25%)。

排查链路固定:先kubectl describe pod看 Events 中的具体错误信息,是认证失败还是连接超时。如果事件显示unauthorized: authentication required,直接检查对应 namespace 下的 imagePullSecret 是否和当前仓库凭据一致。如果是dial tcp: i/o timeout,从 Pod 所在节点上用 curl 测试到镜像仓库的网络连通性,特别注意私有仓库是否在 Pod 安全组白名单内。

对于经常被忽略的imagePullPolicy: Always问题:当一个常用基础镜像的节点重启后,即使本地缓存还在,Always 策略也会强制重新拉取。如果此时镜像仓库正好挂掉,所有节点上的 Pod 会集体启动失败。建议对稳定版本的基础镜像使用IfNotPresent

问题二:OOMKilled 与资源 Limit 不合理(11 张)

23% 的工单是 OOM 导致的 Pod 重启。典型案例:Java 服务设置了limits.memory: 2Gi,但 JVM 堆设了-Xmx2g,加上堆外内存和 Metaspace,实际内存峰值超过 3Gi。Cgroup 在达到 2Gi 时直接 Kill,Pod 陷入反复启动-被杀循环。

排查这类问题需要三步:首先确认kubectl describe pod中的Last StateOOMKilled;其次检查应用本身的内存配置是否与 K8s Limit 对齐——Java 看 JVM 参数,Go 看 GOMEMLIMIT,Python 看 worker 数量;最后用 Prometheus 查看container_memory_working_set_bytes的实际峰值,修正 Limit 值。

修复策略不是简单把 Limit 调大。正确做法是先设置一个合理的 request(如实际稳定运行时的 1.2 倍),Limit 设为 request 的 1.5-2 倍。同时启用automountServiceAccountToken: false减少不必要的 Sidecar 内存开销。

问题三:CrashLoopBackOff 启动探针误配(9 张)

19% 的工单是探针配置导致。三种常见误配:

  • startupProbe 缺失导致 readiness 延迟不够:应用启动需要 30s,但 readiness 的initialDelaySeconds只给了 5s。结果 Pod 一直处于 Running 但 Not Ready,Service 不会分流量但 K8s 认为 Pod 重启了。
  • livenessProbe 过于激进periodSeconds: 5+failureThreshold: 2,意味着只要应用有 10s 卡顿就被 Kill。在 GC 密集型应用或数据库连接池初始化的场景下,频繁误杀。
  • exec 探针本身消耗资源:用exec执行 heavy 检查脚本每秒一次,CPU 被探针吃掉了 30%。

修正方案:永远先配 startupProbe(failureThreshold: 30, periodSeconds: 2),给应用充足的启动时间;livenessProbe 设置保守的periodSeconds: 30failureThreshold: 5;ready 检查用 HTTP GET 代替 exec,减少 CPU 开销。

问题四:Pending 状态与节点资源不足(7 张)

Pod 一直 Pending 且 Events 显示0/10 nodes are available: 2 Insufficient cpu, 3 Insufficient memory, 5 node(s) had taint。这里的关键是不要只看资源总量,要看 request 而非 limit 的调度决策。

排查用kubectl describe nodes | grep -A 5 "Allocated resources"看实际分配的 request,把 Pod 的 request 调小(和 Limit 解耦)通常是比扩容节点更快的解法。另外 nodeAffinity 和 taint/toleration 也是常见的 Pending 原因,kubectl get nodes -o json | jq '.items[].spec.taints'能快速检查。

问题五:DNS 解析超时与服务发现(6 张)

七月份有一半的 DNS 问题集中在 Alpine 镜像的 musl libc DNS 行为差异上。Alpine 的 musl 默认不走 search domain 的 ndots 逻辑,K8s 默认的 ndots:5 配置在 Alpine 环境中会产生大量不必要的 DNS 查询。

解法:在 Pod spec 中显式设置dnsConfig.options.ndots: 2,同时对高频调用的内部服务使用 clusterIP 的 FQDN 而非短域名。

问题六:PV/PVC 挂载失败(5 张)

主要是 CSI driver 版本和 K8s 版本不兼容。七月有两个集群升级 K8s 到 1.29 后,旧的 AWS EBS CSI Driver 1.22 无法正常工作。排障时重点关注kubectl describe pvc的 Events 中是否有 Provisioner 相关的错误日志。

问题七:Service Endpoint 不更新(4 张)

当 Pod 的 Label 变更但 Service 的 Endpoint 没有同步更新时,通常是 endpoint controller 卡住。排查方法:kubectl get endpoints确认 endpoint 数量和 Pod 数量是否一致,不一致时检查 kube-controller-manager 日志。

问题八:HPA 伸缩不生效(4 张)

大多是metrics-server不可用或者自定义指标 adapter 配置错误。20% 的情况是 HPA 的minReplicasmaxReplicas设置相同导致伸缩被禁用。检查链路:kubectl get hpakubectl describe hpa→ 看是否显示unable to get metrics

问题九:节点 NotReady 与 Kubelet 异常(3 张)

节点 NotReady 后 Pod 会被打上node.kubernetes.io/unreachable的 toleration 倒计时。问题在于默认的tolerationSeconds: 300往往太长——300 秒的业务中断不可接受。对核心服务建议自定义 toleration,将驱逐时间缩短到 60 秒。

问题十:ConfigMap 更新后 Pod 不重启(2 张)

K8s 不会自动重启引用 ConfigMap 的 Pod。如果用 subPath 挂载单个文件,ConfigMap 更新后文件不会热更新。解法:使用 Reloader 这类工具自动触发滚动更新,或者在 ConfigMap 名称中加版本 hash。

三、统一排查工具箱

47 张工单中有 32 张可以用以下三个命令在 5 分钟内定位到根因:

# 1. 快速总览 kubectl describe pod <pod-name> -n <ns> | grep -A 20 "Events:" # 2. 资源实际使用 kubectl top pod <pod-name> -n <ns> --containers # 3. 最近日志(含前一个容器的崩溃日志) kubectl logs <pod-name> -n <ns> --previous --tail=100

操作顺序固定:Events → 资源使用 → 日志。不要跳步骤,不要先去看日志再回来看 Events。90% 的问题在 Events 里就已经写明了根因。

四、排障过程中容易忽略的系统性问题

以上十个问题各自独立,但它们存在三个系统性的共性问题容易被忽略:

  1. 监控覆盖不足:OOM 问题中 30% 是在用户投诉后才发现的,因为 Pod 重启太快,Prometheus 的 scrape interval 来不及采集到内存尖峰。
  2. 告警规则不精确:大量 CrashLoopBackOff 的告警被和 ImagePullBackOff 混在同一个 PromQL 中,噪声比高导致真正需要处理的告警被忽略。
  3. 版本升级回归测试缺失:PV 挂载和 DNS 问题都发生在集群升级后,说明缺乏针对 CSI driver 和 CoreDNS 的专项回归检查。

五、总结

七月 Top 10 排障问题按频率的前三名是镜像拉取、OOM 和探针误配,合计占工单量的 72%。这三类问题的共同特点是:都不是 K8s 的 Bug,而是配置和资源规划问题。治理方向有三条:

  • 镜像治理:统一基础镜像版本、强制设定 imagePullPolicy 策略、定期轮转 imagePullSecret。
  • 资源规划:建立资源 request/Limit 的基线标准,将 OOM 告警从"事后通知"升级为"基于趋势的预警"。
  • 探针规范:制定 startupProbe/livenessProbe/readinessProbe 的配置模板,禁止无 startupProbe 的 Pod 部署到生产环境。

基础设施的稳定不是靠一次排障就能保证的,靠的是把每类问题的根因固化为规范。