云原生-01-测试团队在Kubernetes场景里最常处理哪些真实问题

一提到 Kubernetes,最容易先聊的是这些话题:

  • 集群怎么搭
  • 节点怎么加
  • Helm 怎么装
  • Pod、Service、Ingress 分别是什么

这些内容当然重要,但对测试团队来说,日常最常处理的往往不是“概念理解”,而是更具体的现场问题:

  • 某个版本在测试环境里发布后,Pod 一直起不来
  • 服务已经 Running,但页面还是 502 或 404
  • 接口偶发超时,测试结果不稳定,但应用日志里看不出明显报错
  • 配置明明改过,容器里实际跑的却还是旧逻辑
  • 冒烟用例失败后,没人能快速回答问题到底出在镜像、配置、网络还是依赖服务

如果把 Kubernetes 只当成部署容器的平台,测试团队会很容易陷入一种被动状态:

  • 应用起不来,只能等运维排
  • 接口不通,只能等开发看
  • 环境波动,只能把失败先归为“环境问题”
  • 证据散落在流水线、日志平台、Kibana、Prometheus 和聊天记录里,最后没人说得清根因

真正更贴近测试工作的视角应该是:

Kubernetes 不是一个额外的概念层,而是测试环境、发布链路、服务连通性、配置治理和证据收集方式都被重新组织之后的新现场。

所以测试团队在 Kubernetes 场景里最常处理的真实问题,通常集中在下面五层:

  • 发布层:镜像、版本、滚动更新、回滚是否正常
  • 运行层:Pod、容器、探针、资源限制是否稳定
  • 网络层:Service、Ingress、DNS、网络策略是否通畅
  • 配置层:ConfigMap、Secret、环境变量和外部依赖是否一致
  • 证据层:日志、事件、监控、发布记录是否能串成一条时间线

这篇文章不讲空泛的云原生概述,只聚焦一个问题:

测试团队在 Kubernetes 场景里最常处理哪些真实问题,以及这些问题应该怎么分层、怎么排、怎么把证据收清。

一、先把问题分层,别把所有异常都叫“环境问题”

Kubernetes 场景里的很多故障之所以越排越乱,不是因为系统太复杂,而是因为问题没有先分层。

测试执行失败之后,如果排查起点只是:

  • 这个环境不稳定
  • 集群好像有问题
  • K8s 抽风了

后面的排查就很容易失去方向。

更合适的方式,是先把问题按下面五层拆开。

1. 发布层:版本到底有没有真正发布成功

测试团队最常碰到的第一类问题,不是业务逻辑错,而是版本根本没有以预期方式落到环境里

典型现象包括:

  • 流水线显示发布成功,但 Pod 实际还是旧镜像
  • Deployment 更新了,测试流量却还落在旧副本上
  • 某个 Pod 已经重建,但新旧配置混跑
  • 回滚后页面恢复了,但一部分接口仍然命中旧逻辑

这一层最该先确认的是:

  • 当前命名空间下实际跑的是哪个镜像 tag
  • Deployment 的 generationobservedGeneration 是否对齐
  • ReplicaSet 是否真的完成切换
  • 滚动更新期间是否存在旧 Pod 残留
  • 回滚动作是只改了镜像,还是连配置一起回退

很多测试失败一开始看像业务回归,后面追下来其实只是版本没有换干净。

2. 运行层:服务有没有真正稳定运行

第二类高频问题是服务“看起来活着”,但实际上没有进入稳定可用状态。

典型现象包括:

  • Pod 状态在 CrashLoopBackOff
  • 容器频繁重启
  • Readiness probe 一直不过
  • 应用启动很慢,冒烟任务比服务准备更早开始
  • 压测时某些副本被 OOMKilled

这一层真正需要回答的是:

  • 进程是否成功启动
  • 启动后有没有立刻退出
  • 探针失败是因为应用没准备好,还是探针设计不合理
  • 容器资源限制是不是太紧
  • 节点资源是否已经接近上限

只看 Pod 是不是 Running 远远不够。Running 只能说明容器在跑,不代表服务真的可用。

3. 网络层:流量到底卡在了哪一段

第三类问题最常见,也最容易被误判成“应用异常”。

测试场景里常见的网络问题包括:

  • Ingress 已经配了,外部访问还是 404 或 502
  • 服务名能解析,但连接超时
  • 页面能打开,接口请求偶发失败
  • 同一个集群里 A 服务调 B 服务失败
  • 测试环境可以访问,流水线节点却访问不了

这一层不能只问“能不能访问”,而要继续拆:

  • DNS 是否解析正确
  • Ingress 是否命中了预期规则
  • Service 的 selector 是否选中了正确的 Pod
  • Endpoints 是否已经生成
  • 容器监听端口和 Service 暴露端口是否一致
  • 网络策略是否挡住了跨命名空间或跨节点访问

很多“服务没起来”的结论,最后根因其实是流量根本没打到目标容器。

4. 配置层:代码没错,但跑的不是预期配置

Kubernetes 场景里,配置问题的比例通常比传统部署更高。

原因很简单:配置被拆成了更多层,而且经常通过环境变量、ConfigMap、Secret、挂载文件和外部配置中心共同生效。

典型现象包括:

  • 容器里读取到的环境变量和发布单填写的不一致
  • ConfigMap 已更新,但应用没有重载
  • Secret 已变更,老 Pod 仍在使用旧凭据
  • 相同镜像在两个命名空间里表现不同
  • 测试环境偶发访问错库、错缓存、错消息队列

这类问题的难点不在“有没有配置”,而在最终生效的是哪一份配置

所以配置层至少要回答四个问题:

  • 配置源是什么
  • 配置注入方式是什么
  • 配置何时生效
  • 配置变更后是否要求重启或滚动更新

5. 证据层:问题出现后能不能快速闭环

第五层经常被忽略,但它直接决定排障效率。

已经有:

  • 集群事件
  • 容器日志
  • Prometheus 指标
  • Grafana 看板
  • 流水线记录
  • 测试报告

但一旦出现问题,真正的现场依然很难还原,因为这些证据没有按同一个执行对象收口。

最常见的失真表现是:

  • 只知道某次回归失败,不知道命中了哪一次发布
  • 只拿到了应用日志,没有抓到 Pod 重建前的旧日志
  • 看到错误率升高,但对不上具体 Pod 和具体时间窗
  • 报告里只有“接口超时”,没有配套的事件、探针和资源证据

Kubernetes 场景下,如果证据层没有收清,前四层的问题就算定位到了,也很难高效复盘。

二、测试团队在 Kubernetes 里最常处理的 7 类真实问题

把问题按层拆开之后,测试团队日常最常遇到的其实是下面 7 类。

1. 版本更新了,但业务仍然跑在旧副本上

这种问题通常出现在滚动更新、缓存路由、Ingress 转发或 Service selector 配置不一致时。

表面现象通常是:

  • 同一条用例一会儿通过,一会儿失败
  • 某个接口只有部分返回值和新版本一致
  • 前端页面已经是新样式,后端接口却还是旧逻辑

这里最关键的不是重跑,而是先确认:

  • 新旧 ReplicaSet 数量
  • 当前 Pod 的镜像 digest
  • Service 实际挂载的 endpoints
  • 是否有旧 Pod 未被摘流

2. Pod 起不来,或者能起但很快重启

这是最典型的运行层问题,常见根因包括:

  • 启动参数错误
  • 依赖服务不可达
  • 配置缺失
  • JVM、Node 或 Python 应用启动时资源不足
  • 探针过早触发导致容器反复被杀

这类问题最容易被误判成“代码挂了”,但实际常常是部署和运行条件不满足。

3. 页面或接口不通,但容器日志没有明显异常

这通常是网络层问题。

常见根因包括:

  • Ingress host 或 path 规则配置不匹配
  • Service 端口映射错误
  • 应用监听 127.0.0.1 而不是 0.0.0.0
  • 上游转发超时
  • 网关证书或 TLS 配置不一致

如果只盯应用日志,很容易在错误方向上浪费大量时间。

4. 同一个版本在两个环境表现不同

这类问题很多时候不是镜像问题,而是配置和依赖差异。

最常见的差异点有:

  • 环境变量不一致
  • ConfigMap 内容不同
  • Secret 指向不同账号
  • 外部中间件地址不同
  • DNS 或服务发现配置不同

只要环境配置是漂移状态,测试结果就很难稳定。

5. 压测或批量回归时服务波动明显

这类问题往往和资源限制、弹性策略、节点分布有关。

例如:

  • requests 太低导致调度看起来没问题,实际运行被抢占
  • limits 太紧导致峰值时 OOM
  • HPA 指标滞后,扩容来不及
  • 大量并发流量都打到同一个节点或同一批旧 Pod

如果测试团队只从业务接口看超时,很难解释为什么“平时能跑,一压就散”。

6. 回归失败后,证据留不住

Kubernetes 环境里,Pod 是动态对象,旧容器和旧事件很容易很快消失。

这会带来两个很现实的问题:

  • 问题复现一次后,再想回看第一次失败现场时证据已经不在
  • 只知道最近有过重启,但拿不到重启前最后几秒的日志和事件

所以回归和冒烟一旦失败,证据收集动作必须尽量前置,而不是等人工再去看。

7. 环境性失败和业务性失败混在一起

Kubernetes 场景里,环境波动和业务缺陷更容易互相伪装。

例如:

  • 接口 500,可能是代码异常,也可能是依赖服务连接信息错误
  • 登录超时,可能是业务链路慢,也可能是 Ingress 或 DNS 波动
  • 某条用例失败,可能是逻辑回归,也可能是 Pod 在执行中途被驱逐

如果测试报告没有把 Kubernetes 现场证据一起带上,很多失败最终只能先人工归类,反馈效率会明显下降。

三、测试团队在 Kubernetes 现场的最小排查骨架

Kubernetes 问题一旦上来就满屏命令,排查通常会失控。更有效的方式是先有一套固定骨架。

下面这套骨架更适合测试团队在回归、冒烟、联调和发布校验时快速收口。

1. 先确认对象:到底是哪次发布、哪个命名空间、哪个服务

先固定下面三个对象:

  • 发布版本或镜像 tag
  • 命名空间
  • 服务名、Deployment 名、Pod 名

如果这一步都不固定,后面看日志、查 Pod、看事件都可能看错对象。

2. 再确认发布:版本有没有真的落下去

建议优先看下面几类信息:

1
2
3
4
kubectl -n <namespace> get deploy <deploy-name>
kubectl -n <namespace> rollout status deploy/<deploy-name>
kubectl -n <namespace> get rs -l app=<app-name>
kubectl -n <namespace> get pods -o wide -l app=<app-name>

这一层主要看:

  • rollout 是否完成
  • ReplicaSet 是否已经切换
  • 是否仍然存在旧 Pod
  • Pod 是否分布异常

3. 再确认运行:服务是不是稳定可用

这一层优先看:

1
2
3
4
kubectl -n <namespace> describe pod <pod-name>
kubectl -n <namespace> logs <pod-name> --tail=200
kubectl -n <namespace> logs <pod-name> --previous --tail=200
kubectl -n <namespace> top pod

重点观察:

  • 容器退出码
  • 探针失败信息
  • OOMKilled、Back-off、ImagePullBackOff 等事件
  • 当前和上一个容器实例日志

4. 再确认网络:流量是否真的到达目标容器

1
2
3
4
kubectl -n <namespace> get svc <svc-name>
kubectl -n <namespace> get endpoints <svc-name>
kubectl -n <namespace> describe ingress <ingress-name>
kubectl -n <namespace> exec -it <pod-name> -- sh

这里不是为了把所有网络问题都自己解决,而是先把边界切清:

  • DNS 是否能解析
  • Service 有没有 endpoints
  • Ingress 规则有没有命中
  • 容器内是否能访问依赖服务

5. 再确认配置:容器里实际生效的是什么

1
2
3
4
kubectl -n <namespace> get configmap
kubectl -n <namespace> describe configmap <configmap-name>
kubectl -n <namespace> describe secret <secret-name>
kubectl -n <namespace> exec -it <pod-name> -- env

重点看:

  • 环境变量和预期是否一致
  • ConfigMap 是否已经被新 Pod 挂载
  • Secret 是否更新后未重启
  • 同名配置在不同环境里是否漂移

6. 最后收证据:把一次失败变成可复盘的问题包

至少要收下面这些证据:

  • 发布版本、镜像 tag、流水线编号
  • 失败时间窗
  • 目标 Pod 列表和状态
  • 关键事件
  • 当前日志和前一个实例日志
  • Service、Endpoints、Ingress 快照
  • 相关监控图或错误率截图

对测试团队来说,最重要的不是命令记得有多全,而是每次失败都能按照同一顺序收出同一组证据。

四、这些常见坑,比单纯的业务缺陷更容易拖慢测试效率

1. 把 Running 当成“服务已就绪”

很多自动化链路只看 Pod 状态,不看 readiness,结果服务还没准备好,冒烟就已经开始。

后果通常是:

  • 第一轮失败很多
  • 补跑又都通过
  • 现象很容易被判断成用例不稳定

实际上根因只是校验开始得太早。

2. 回归失败后才临时去抓现场

Kubernetes 环境变化快,Pod 重建、日志轮转、事件淘汰都可能让证据很快消失。

失败后再临时人工进入集群抓日志,经常已经错过最关键的几分钟。

3. 只看应用日志,不看事件和探针

应用日志适合看业务错误,但不适合解释容器为什么起不来、为什么被杀、为什么没被摘流。

如果缺少 describe pod 和事件信息,很容易漏掉真正的运行层根因。

4. 只看 Ingress,不看 Service 和 Endpoints

很多访问问题最后并不是网关没转,而是后端根本没有有效 endpoints。

如果一开始只盯 Ingress 配置,很容易陷入错误方向。

5. 配置变更后没有定义“何时生效”

配置已经改了,只是这几个问题还没有定义清楚:

  • 是热加载生效,还是必须重启
  • 是所有副本同步生效,还是滚动替换
  • 是立刻生效,还是下一次调度生效

没有这些边界,测试结果就很难解释。

6. 测试报告不带集群现场

如果报告里只有接口失败截图,没有版本、Pod、事件、日志摘要和监控证据,Kubernetes 场景里的问题推进效率会很差。

因为研发、运维、测试看到的是不同现场,很难快速对齐。

五、把 Kubernetes 问题治理成测试资产,关键在三个动作

测试团队如果长期在 Kubernetes 环境里做回归、联调和发布校验,最值得先建设的不是更多命令,而是下面三个动作。

1. 给回归和冒烟补上环境前置探活

在业务用例开始前,先做一层轻量环境检查:

  • Deployment rollout 是否完成
  • Pod readiness 是否全部通过
  • Service endpoints 是否存在
  • 关键依赖接口是否可达

这层探活可以明显减少把环境波动误判成业务缺陷的次数。

2. 给失败结果补上集群现场摘要

每次失败都尽量自动收下面几类摘要:

  • 失败时间窗内的 Pod 状态变化
  • 最近事件摘要
  • 关键日志片段
  • 服务路由和 endpoints 快照
  • 资源使用峰值

这样问题单和测试报告会更像“现场问题包”,而不只是“失败通知”。

3. 把环境性失败和业务性失败先分流

更合适的做法是先把失败归为三类:

  • 业务失败
  • 环境失败
  • 待确认失败

然后再要求每一类最少附哪些证据。

这样比简单地把所有失败都算进通过率或失败率,更能体现 Kubernetes 场景里的真实质量状态。

六、真实案例:发布后接口批量超时,问题不在代码而在流量根本没进目标副本

下面用一个更接近现场的问题,把前面的排查骨架串起来。

场景

某个测试环境在发布新版本后,回归任务里有一批核心接口连续超时。

现象一开始很像业务严重回归:

  • 登录后多个接口超时
  • 页面部分区域空白
  • 自动化脚本连续失败
  • 研发反馈本地联调正常

流水线侧显示 Deployment 已经发布完成,测试报告里只有接口超时和页面空白,没有更具体的集群信息。

执行

先按固定骨架收现场:

  1. 确认发布单、命名空间、服务名和镜像 tag
  2. 查看 Deployment rollout 状态
  3. 查看当前 Pod、ReplicaSet 和 Service endpoints
  4. 查看 Ingress 规则和后端服务端口
  5. 抽查目标 Pod 的应用日志、事件和 readiness 状态

现象

现场很快暴露出几个关键信号:

  • Deployment 的 rollout 已结束
  • 新 Pod 都是 Running
  • 但 Service 的 endpoints 只有一部分
  • 某些新 Pod 的 readiness 一直没通过
  • Ingress 后端指向的 Service 端口和应用实际监听端口不一致

进一步看日志后发现,应用本身已经启动,只是 readiness 检查命中的路径和新版本路由改动不一致,导致一部分副本始终没有被加入 endpoints。与此同时,Service 的端口映射也有一处遗漏,流量经过 Ingress 后无法正确落到新副本。

排查

这一轮排查真正起作用的不是某条复杂命令,而是顺序没有乱:

  1. 先确认不是“没发布成功”
  2. 再确认 Pod 不是“根本起不来”
  3. 然后把网络路径拆到 Ingress、Service、Endpoints
  4. 最后才把问题收敛到 readiness 和端口映射

如果一开始只看应用日志,问题很容易被收敛成接口处理逻辑变慢;如果只看流水线结果,又容易把结论落到发布成功、问题在业务代码。

修复

最终修复动作包括:

  • 修正 readiness 检查路径
  • 修正 Service 目标端口映射
  • 发布前补一层 Service endpoints 和 readiness 联合检查
  • 回归失败时自动附带 Pod 状态、事件和 endpoints 快照

修复完成后,同类问题的收敛速度明显提高,因为团队已经不再把“接口超时”直接等同于“代码超时”,而是先按发布、运行、网络和配置分层排查。

七、结语

测试团队在 Kubernetes 场景里最常处理的真实问题,通常并不抽象,反而非常具体:

  • 版本有没有真正切换
  • 服务是不是稳定可用
  • 流量有没有打到目标副本
  • 配置到底生效了没有
  • 失败现场能不能被完整留下

只要把这些问题分层,再用一套固定的最小排查骨架收现场,很多原本看起来像“复杂云原生故障”的问题,都会变成可以逐层切边界、逐层收证据的工程问题。

对测试团队来说,Kubernetes 最值得先掌握的不是更多概念,而是:

把一次业务失败快速拆成发布问题、运行问题、网络问题、配置问题或证据问题。

这一步一旦做稳,后面的自动化探活、失败分流、环境治理和平台化证据收集,才有真正落地的基础。