Kubernetes生产运维00:会部署K8s,不等于会运维K8s

在这里插入图片描述

写在前面

我是一名做了8年运维的DevOps工程师,目前管理AWS、腾讯云和阿里云上的6个Kubernetes集群,涉及百台节点和数百个Pod。

刚开始接触Kubernetes时,我也会把重点放在怎么创建Deployment、怎么暴露Service、怎么写Ingress。等真正面对生产故障后才发现:把服务部署进去只是开始,出现问题时能不能快速缩小范围,才是生产运维真正拉开差距的地方。

生产告警通常不会直接告诉你根因。

它只会告诉你:接口超时了、Pod重启了、节点不正常了,或者用户访问失败了。

同一个超时,可能来自应用线程池、Service没有Endpoint、CoreDNS异常、NetworkPolicy拦截、节点连接耗尽,也可能只是上游依赖变慢。命令记得再多,如果没有缩小范围的方法,仍然只能靠猜。

这也是我开启这个专栏的原因。

这套内容不从安装Kubernetes讲起,而是从生产环境最常见的问题出发,讨论如何判断影响、采集证据、验证假设、恢复服务,并在故障后补上监控和治理措施。

在这里插入图片描述


会部署和会运维,区别在哪里

会部署Kubernetes,通常意味着你能够:

  • 创建Deployment、Service和Ingress
  • 使用ConfigMap和Secret注入配置
  • 使用Helm发布应用
  • 查看Pod状态和日志
  • 完成扩缩容与滚动更新

这些能力很重要,但它们处理的是相对确定的问题:目标明确、步骤固定、结果可以预期。

生产故障恰好相反。

维度部署任务生产故障
起点已知目标配置只有模糊现象
路径按步骤执行根据证据动态选择
影响通常可以提前评估可能持续扩大
操作关注是否成功还要考虑是否扩大故障
结果资源创建完成业务恢复且根因被验证

生产排障不是把所有命令都执行一遍,而是每拿到一条证据,就排除一批不可能的方向。

例如,只有一个Pod异常和同一节点上的多个服务同时异常,排查起点完全不同:

  • 只有一个Pod异常,优先看应用、配置、镜像和依赖
  • 同一Deployment的所有Pod异常,优先看发布、公共配置和上游依赖
  • 同一节点上的多个不同服务异常,优先看节点、运行时和网络
  • 多个集群同时异常,优先看公共入口、外部依赖或统一变更

真正的经验,不是看到一个状态就背出十种原因,而是知道下一条最有区分度的证据在哪里。


第一原则:根据影响决定先止损还是先定位

你选择的实战习惯是:根据故障严重程度决定处理顺序。这个判断比固定地先查日志或先重启更符合生产环境。

在这里插入图片描述

可以把事件粗略分为四级。不同公司的等级名称和响应时间会不同,下面是用于理解方法的参考框架。

等级典型影响第一动作后续动作
严重核心业务大面积不可用回滚、切流、降级或隔离恢复后保留数据并调查
较高关键功能受损且影响扩大一边控制影响,一边取证建立时间线并组织协同
一般少量实例异常,有冗余承接先保留现场和采集证据验证根因后修复
较低无用户影响或潜在风险按计划分析纳入治理任务

这里有两个容易混淆的点。

止损不等于盲目重启

如果重启能够快速恢复业务,可以执行,但要尽量先保存容易丢失的信息:

# 保存Pod完整状态
kubectl get pod <pod-name> -n <namespace> -o yaml > pod-before-restart.yaml

# 保存相关事件
kubectl events -n <namespace> --for pod/<pod-name> > pod-events.txt

# 保存当前和上一次容器日志
kubectl logs <pod-name> -n <namespace> --all-containers > pod-current.log
kubectl logs <pod-name> -n <namespace> --all-containers --previous > pod-previous.log

# 保存工作负载版本和发布历史
kubectl rollout history deployment/<deployment-name> -n <namespace>

Events可能过期,崩溃容器的previous日志也可能随着多次重建消失。先花几十秒保存现场,往往能避免业务恢复后再也找不到根因。

取证也不能拖延恢复

如果核心交易已经中断,不能为了追求完美根因让用户一直等待。

更合理的做法是并行分工:一组人执行已验证的回滚或切流方案,另一组人记录时间线、保存现场并观察指标。没有多人协同时,也应先执行风险最低、回退路径最明确的恢复动作。


生产排障的五步框架

在这里插入图片描述

这套专栏会反复使用下面五个步骤。

第一步:判断影响

先回答业务问题,而不是先回答技术问题。

从什么时候开始
影响哪些用户、区域和接口
全部失败还是部分失败
错误率、延迟和流量发生了什么变化
冗余实例是否还能承接
影响是否仍在扩大

只有明确影响范围,才能决定事件等级、参与人员和第一动作。

一个Pod处于CrashLoopBackOff,不一定代表业务故障。如果Deployment还有多个健康副本,Service也只把流量转给Ready Pod,用户可能完全无感。相反,所有Pod看起来都在Running,也不代表业务正常,Readiness、应用错误率或上游依赖仍可能出问题。

第二步:建立时间线

生产故障经常与变更有关,但最近有发布不等于发布一定是根因。

应该把时间对齐:

14:00 新版本发布
14:03 错误率开始上升
14:04 部分Pod Readiness失败
14:06 用户反馈超时
14:08 回滚开始
14:11 错误率恢复

时间线能够形成强线索,但还需要配置差异、日志、指标或回滚结果来验证。

重点核对:

  • 应用发布和镜像变更
  • ConfigMap、Secret和环境变量变更
  • Helm values和副本数变化
  • 节点升级、扩缩容与驱逐
  • 网络策略、Ingress和证书变更
  • 云负载均衡、存储或外部依赖变更

第三步:分层采集证据

Kubernetes故障不是只有Pod一层。可以从上到下分成:

用户与业务
  ↓
入口与负载均衡
  ↓
Ingress或Gateway
  ↓
Service与EndpointSlice
  ↓
Pod与容器
  ↓
Node、kubelet与容器运行时
  ↓
网络、存储和云基础设施

每一层都要回答两个问题:

  1. 请求或资源是否到达这一层
  2. 这一层是否有证据证明自己正常

常用的第一轮信息采集如下:

# 工作负载与Pod分布
kubectl get deployment,pod -n <namespace> -o wide

# Pod状态、容器状态和Events
kubectl describe pod <pod-name> -n <namespace>

# 当前及崩溃前日志
kubectl logs <pod-name> -n <namespace> -c <container-name>
kubectl logs <pod-name> -n <namespace> -c <container-name> --previous

# Service与后端端点
kubectl get service,endpointslice -n <namespace>

# 节点状态和资源压力
kubectl get nodes
kubectl describe node <node-name>

# 按时间查看事件
kubectl events -A --types=Warning

这些命令不是固定套餐。Pod还没有调度时,容器日志并不存在,应该优先看FailedScheduling事件;多个不同服务集中在同一节点异常时,则应尽快转向Node、kubelet、运行时和主机指标。

第四步:提出假设并做最小验证

证据不是越多越好,关键是能够区分不同原因。

例如服务超时,当前有两个假设:

  • 假设A:Redis服务端负载过高
  • 假设B:只有特定节点上的客户端连接异常

有区分度的验证包括:

  • Redis服务端指标是否异常
  • 异常是否集中在特定Pod或Node
  • 同一服务迁移到其他Node后是否恢复
  • 异常Node与正常Node的TCP、连接跟踪和丢包指标是否不同

每次验证尽量只改变一个变量,并提前准备回退方式。不要同时重启Pod、修改资源、切换节点和调整网络,否则即使恢复,也不知道哪个动作真正有效。

第五步:形成闭环

故障恢复不是事件结束。

完整闭环至少包括:

临时恢复
→ 根因验证
→ 永久修复
→ 监控告警
→ Runbook或自动化
→ 复盘行动项

如果问题只能依赖某位老员工凭经验发现,下次仍然会重复消耗时间。应该把关键证据转化为指标、告警、发布检查、配置策略或自动诊断规则。


一个真实案例:Redis超时如何缩小到节点连接泄漏

在这里插入图片描述

下面是一个A级脱敏案例,只保留通用排查逻辑。

故障现象

部分微服务偶发Redis连接超时,但Redis服务本身看起来正常。从Pod内手工测试,基础网络也能连通。

如果只盯着Redis日志,很容易在服务端反复寻找并不存在的问题。

范围收敛

排查过程不是一次猜中,而是逐步排除:

Redis连接超时
→ Redis服务端资源和连接正常
→ Pod到Redis的基础网络可达
→ 不是所有Pod同时发生
→ 异常集中在部分Node
→ 异常Node的TCP分配连接数持续增长
→ 正常Node的同一指标保持稳定
→ 多个服务共用同一Redis客户端依赖
→ 开发定位依赖中的连接释放问题

关键证据是异常节点上的node_sockstat_TCP_alloc持续增长,并且与正常节点形成明显对照。

这条指标本身不能直接证明代码有Bug,但它把范围从Redis服务和整个网络,缩小到了特定节点上的TCP连接行为。再结合多个服务共用同一个客户端依赖,开发最终定位到底层网络调用没有正确释放连接。

修复与预防

  • 临时层面:将受影响工作负载迁离异常节点,恢复连接能力
  • 永久层面:升级公共Redis客户端依赖,修复连接释放问题
  • 监控层面:增加节点TCP分配连接数及增长率告警
  • 复盘层面:把节点级连接指标纳入类似超时问题的排查清单

这个案例说明,真正的排障能力不是会执行更多命令,而是能够根据对照证据不断改变观察层级。

应用层没有发现问题时,继续盯着同一批日志不会自动产生答案。要敢于从应用转向Pod,从Pod转向节点,再从节点指标回到公共代码依赖。


三类证据,避免把经验写成故事

这个专栏会明确标记案例证据等级。

等级来源使用方式
A真实生产处理记录脱敏后呈现现象、证据和处理决策
B本地或临时集群实验给出配置、步骤和实际结果
C官方机制和设计分析明确标注原理说明或待验证方案

这样做有两个目的:

第一,不把网上看来的方案包装成亲自做过。

第二,避免把一次偶然恢复写成确定根因。重启后恢复只能证明重启改变了状态,不能单独证明内存泄漏、网络故障或应用Bug。


生产排障最常见的五个误区

误区一:看到异常就重启

重启有时是正确的止损动作,但它可能清除现场。执行前应判断影响等级,并保存关键状态、Events和日志。

误区二:只看Pod状态

Running只是Pod阶段,不代表应用接口、依赖和业务指标正常。还要看Ready状态、EndpointSlice、错误率和延迟。

误区三:列出十种原因却不排序

排障清单有用,但更重要的是根据当前证据排序。最近变更、异常分布和对照组通常比泛泛的可能性更有价值。

误区四:一次修改多个变量

同时改资源、重启、换节点和回滚,会破坏因果判断。除非正在处理严重故障,否则优先做最小验证。

误区五:业务恢复后不再追查

没有永久修复、监控和Runbook,意味着同类故障还会回来。恢复是应急目标,闭环才是运维目标。


这个专栏会讲什么

整个系列包括导读和15篇正文,分为三个阶段。

第一阶段:Pod与基础排障

  • 生产故障排查方法论
  • kubectl排障工具箱
  • Pod Pending
  • CrashLoopBackOff
  • OOMKilled与内存治理

目标是建立排查顺序,理解Pod状态背后的调度、容器和资源机制。

第二阶段:网络、存储与节点

  • Service访问异常
  • CoreDNS解析故障
  • Ingress 404与502
  • PVC Pending与挂载失败
  • Node NotReady

目标是从单个Pod扩展到完整请求链路和基础设施层。

第三阶段:稳定性与治理

  • 三类探针设计
  • Requests、Limits与QoS
  • RBAC最小权限
  • Kubernetes集群无中断升级
  • 监控、告警与故障复盘

目标是把一次次救火转化为配置标准、升级Runbook和稳定性闭环。


与面试和K8sChat项目的关系

这套专栏不只是为了发文章。

每篇内容都会同步转化为三类资产:

文章内容面试资产K8sChat资产
排查路径结构化场景题答案Agent分析步骤
kubectl命令实操追问答案查询工具定义
故障案例STAR故事素材测试与评估案例
停止条件风险控制话术Agent退出机制
预防措施架构治理能力自动检查建议

例如CrashLoopBackOff文章中的Events、previous日志、退出码和OOM判断,未来可以直接转成K8sChat的工具调用顺序和评估数据。


面试怎么说

60秒回答

我认为Kubernetes生产运维的核心不是记住多少kubectl命令,而是能否根据影响和证据快速缩小故障范围。我的处理顺序是先判断业务影响,严重故障优先通过回滚、切流或隔离止损,影响可控时先保留现场。然后建立时间线,从应用、Pod、Service、Node到基础设施分层采证,每次用最小验证排除一个假设。恢复后还要验证根因,补监控、告警和Runbook,形成闭环。

3分钟项目版

可以结合Redis连接超时案例展开:

  1. Redis服务端和Pod基础连通性正常
  2. 通过异常分布发现问题集中在部分节点
  3. 对比节点指标发现TCP分配连接数持续增长
  4. 将范围缩小到公共Redis客户端依赖
  5. 开发修复连接释放问题
  6. 运维增加节点TCP增长率告警

重点不是宣称一开始就猜到Bug,而是说明每条证据如何推动范围收敛。


延伸问答

问题回答要点
严重故障还需要保留现场吗需要,但不能阻塞止损。优先保存几十秒内可获得的状态、事件和日志,并行执行恢复
回滚后恢复能证明发布是根因吗只能形成强关联,还要对比版本、配置、日志或复现实验,确认具体变化
Pod Running为什么服务仍然不可用Running不等于Ready,应用可能未就绪,Service也可能没有匹配到健康端点
Events和日志哪个先看取决于阶段。Pending优先Events,容器崩溃优先状态、Events和previous日志组合
怎么判断该转向Node层多个不同工作负载集中在同一节点异常,或Pod层证据正常但问题随节点迁移而变化
什么才算根因能解释现象和范围,有证据支持,并能通过修复或复现验证,而不是只与故障同时出现

小结

  1. 会部署Kubernetes解决的是确定性任务,生产运维面对的是模糊现象和持续变化的风险。
  2. 排障第一步不是执行命令,而是判断业务影响和故障范围。
  3. 严重故障优先止损,影响可控时优先保留现场,二者可以并行。
  4. 时间线、异常分布和正常对照组,是缩小范围的重要工具。
  5. 每次验证尽量只改变一个变量,避免恢复后仍不知道原因。
  6. 业务恢复不是结束,还要完成根因验证、永久修复、监控和复盘。
  7. 生产经验的价值不在于一次猜中,而在于建立可重复的证据链。

下一篇预告

下一篇进入这套系列的核心:Kubernetes生产故障排查方法论

我们会把影响评估、时间线、变更检查、分层排查、假设验证和故障记录整理成一份可以直接使用的生产排障清单。


参考资料

本文对官方资料进行了归纳和重新表述,生产案例已脱敏。

更多推荐