宿主机上一个 PID 占用很高,怎么反查它属于哪个 Pod

节点告警来了:某台宿主机的 CPU 或内存被吃满,但上面跑了十几个 Pod,光看 kubectl top pod 往往只能看出大概,还想落到某个具体进程上确认是谁家的。容器里的进程在宿主机上就是一个普通进程,所以只要拿到 PID,再顺着 cgroup 路径就能定位到容器 ID,最后一步用容器运行时查名字。整条链路三步命令就够。

第一步:在节点上锁定高耗进程

登录宿主机执行 top,按大写 P 让 CPU 列排序。下面这台机器上 PID 5174 明显异常,就按它来查。

k8s-podpid01

第二步:从 PID 读到 cgroup 路径

容器的隔离靠 cgroup 实现,进程属于哪个容器,/proc/<pid>/cgroup 里写得很清楚:

[root@localhost ~]# cat /proc/5174/cgroup
k8s-podpid02

输出里那串 64 位的十六进制就是容器 ID,不同运行时(docker、containerd)前缀层级不太一样,但容器 ID 本身是通用的。只想把它单独取出来的话,用分隔符切一下:

#通过下面的命令过滤出来对应的ID号
cat /proc/5174/cgroup | awk -F '/|-' '{print $8}'

这里用 / 和 - 一起当分隔符,取第 8 段。这个下标跟具体那行 cgroup 路径的层数有关,Kubernetes 的 cgroup parent 层级变了(比如 cgroup v2、或者 Pod 目录下多了一层 kubepods-burstable-podUID.slice)就得相应调整,别照抄。稳妥办法是肉眼先确认一次再写脚本。

第三步:用容器 ID 反查容器

Docker 运行时直接过滤:

[root@localhost ~]# docker ps | grep 6f2953085ed6
k8s-pid

输出里的容器名通常就是 k8s_容器名_Pod名_命名空间_PodUID_数字 这种格式,Pod 名和命名空间一步就读出来了。

几个容易踩的点

  • docker ps 查不到时先想想容器是不是已经退出,加上 -a 再看;节点用的是 containerd 的话,换成 crictl 或 ctr 按同样的 ID 去匹配。
  • 用 ID 前 12 位去 grep 一般够用,但极端情况下可能撞上短前缀重复,此时用完整 64 位 ID。
  • 只看 CPU 排序容易漏掉内存、磁盘 IO 型的问题,配合 top 的 M、iostat、pidstat 一起看更稳。
  • 定位到 Pod 之后别忘了 kubectl describe pod 看它有没有被限流(CPU throttling),资源占用高和被限流经常同时出现。
© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容