问题现象
某个 Kubernetes 集群执行 kubectl get pod 需要等待约 6 秒才返回,但实际返回的数据量很小,集群规模也正常:
| |
而加上 -v=9 看真正的 LIST 请求,仅耗时约 104ms:
| |
真正的请求并不慢,慢在别处。
环境信息
| |
集群中存在大量 CRD、Prometheus、Rancher、custom metrics。
初步怀疑
最初怀疑包括:apiserver 性能问题、etcd 性能问题、APIService 超时、kubectl 版本过老、discovery cache 损坏。
验证 apiserver
kubectl get pod -v=9 显示 GET /api/v1/pods 仅 104ms,说明网络、apiserver、etcd 都正常,真正的请求并不慢。
验证 discovery
| |
慢发生在 API Discovery 阶段。
检查 kubectl 缓存
| |
明显异常。进一步定位:
| |
142MB 集中在 custom.metrics.k8s.io/v1beta1 这一个文件上。
定位 custom metrics
| |
结果:546833。
| 场景 | 数量 |
|---|---|
| metrics-server | 2~10 |
| 普通 custom metrics | 10~100 |
| 大型平台 | 数百 |
| 超大平台 | 数千 |
本集群 546833,已经严重异常。
查看具体 metric
| |
| |
metric name 中包含了用户名、UFS、文件路径、日期目录,例如 /xxx/daytime_20240821,全部进了 metric name。
根因分析
Alluxio 导出的 metric 存在极高基数,每一个路径都会生成一个新的 metric:
| |
连锁反应如下:
| |
为什么 kubectl get pod 会受影响
kubectl 启动时需要执行 Discovery,会请求 GET /api、GET /apis、GET /apis/apps/v1、GET /apis/custom.metrics.k8s.io/v1beta1 等接口。其中 custom metrics 返回了 546833 resources、142MB JSON,kubectl 本地需要:
- 下载 JSON
- 解析 JSON
- 构建 RESTMapper
- 写入 discovery cache
最终导致:
| |
修复过程
Alluxio 已经下线,删除对应的 ServiceMonitor 停止采集。一段时间后再次查看:
| |
结果:9983,从 546833 降到了 9983。
清理客户端缓存
| |
修复结果
| |
问题解决。
排查流程总结
- 判断是否是 apiserver:
kubectl get pod -v=9,看真正的 LIST 请求耗时。 - 判断是否是 discovery:
time kubectl api-resources。 - 查看 discovery cache:
du -sh ~/.kube/cache。 - 找超大资源文件:
du -sh ~/.kube/cache/discovery/*/*/*。 - 检查 custom metrics 数量:
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1 | jq '.resources | length'。
经验总结
如果出现「kubectl get 很慢、apiserver 很快、LIST 请求只有几十毫秒」,优先检查:
| |
特别留意 Prometheus Adapter、custom metrics、高基数 metric、失效的监控系统——它们可能导致 kubectl discovery 变慢,而不是 Kubernetes 本身变慢。
最终根因
| |