ljzsdut
GitHubToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

集群node的load过高排查

第一步:定位问题进程

Linux load average 高的"元凶"

如何找出系统中load高时处于运行队列的进程

系统有很高的负载但是CPU使用率却很低,或者负载很低而CPU利用率很高,这两者没有直接关系,如何用脚本统计出来处于运行队列的进程呢?

每隔1s统计一次:

#!/bin/bash
LANG=C
PATH=/sbin:/usr/sbin:/bin:/usr/bin
interval=1
length=86400
for i in $(seq 1 $(expr ${length} / ${interval}));do
date
LANG=C ps -eTo stat,pid,tid,ppid,comm  --no-header | sed -e 's/^ \*//' | perl -nE 'chomp;say if (m!^\S*[RD]+\s*!)'
date
cat /proc/loadavg
echo -e "\n"
sleep ${interval}
done

从统计出来的结果可以看到:

image-20201029101933830

注:R代表运行中的队列,D是不可中断的睡眠进程

在load比较高的时候,有大量的java处于R或者D状态,他们才是造成load上升的元凶,和我们底层的负载确实是没有关系的。而这个进程的PID为“18440”.

Linux CPU使用率高的"元凶"

查CPU使用率比较高的线程小脚本:

#!/bin/bash
LANG=C
PATH=/sbin:/usr/sbin:/bin:/usr/bin
interval=1
length=86400
for i in $(seq 1 $(expr ${length} / ${interval}));do
date
LANG=C ps -eT -o%cpu,pid,tid,ppid,comm | grep -v CPU | sort -n -r | head -20
date
LANG=C cat /proc/loadavg
{ LANG=C ps -eT -o%cpu,pid,tid,ppid,comm | sed -e 's/^ *//' | tr -s ' ' | grep -v CPU | sort -n -r | cut -d ' ' -f 1 | xargs -I{} echo -n "{} + " && echo ' 0'; } | bc -l
sleep ${interval}
done
fuser -k $0

第二步:定位问题容器

docker 在宿主机上根据进程PID查找归属容器ID

参考:https://www.cnblogs.com/ryanyangcs/p/13384118.html

在使用docker时经常出现一台docker主机上跑了多个容器,可能其中一个容器里的进程导致了整个宿主机load很高,其实一条命令就可以找出罪魁祸首

  • 查找容器ID
docker inspect -f "{{.Id}} {{.State.Pid}}" $(docker ps -q) |grep <PID>

示例:
root@provider-ceph01:~# docker inspect -f "{{.Id}} {{.State.Pid}}" $(docker ps -q) |grep 2935963
592144d1addfe07a78d20e5a68ecc170f4b3da86bc6ff2cf4a69449548565ef0 2935963
  • 查找k8s pod name
docker inspect -f "{{.Id}} {{.State.Pid}} {{.Config.Hostname}}"  $(docker ps -q) |grep <PID>

示例:网络类型为host,所以无法根据Hostname来判断是哪个pod,但可以通过如下方法判断
root@provider-ceph01:~# docker inspect -f "{{.Id}} {{.State.Pid}} {{.Config.Hostname}}"  $(docker ps -q) |grep 2935963
592144d1addfe07a78d20e5a68ecc170f4b3da86bc6ff2cf4a69449548565ef0 2935963 provider-ceph01

root@provider-ceph01:~# docker ps |grep 592144d
592144d1addf        cad3aa186528                                                 "ceph-mgr --fsid=37e…"   8 days ago          Up 8 days                               k8s_mgr_rook-ceph-mgr-a-645f799969-dvhzr_rook-ceph_22889f45-3e3b-11ec-a539-acde481d7756_2  

k8s_<控制器名字>_<pod 名字>_<命名空间>_<pod id>
#k8s_mgr_rook-ceph-mgr-a-645f799969-dvhzr_rook-ceph_22889f45-3e3b-11ec-a539-acde481d7756_2  名字解析
#下划线分割字段;
#k8s_mgr:好像是集群名字(不确定)
#rook-ceph-mgr-a-645f799969-dvhzr: pod名字
#rook-ceph:名称空间
#22889f45-3e3b-11ec-a539-acde481d7756
  • 如果PID是容器内运行子进程那docker inspect就无法显示了
for i in  `docker ps |grep Up|awk '{print $1}'`;do echo \ &&docker top $i &&echo ID=$i; done |grep -A 10 <PID>

示例:

image-20201029102505218