Docker 容器进程查找与内存CPU使用情况
一、获取 PID 对应的容器
有的时候我们经常会排查服务资源使用情况,往往使用 top 命令来查看负载情况和当前进程的资源使用情况,那如何根据这些进程来查找到对应的 docker 容器呢
那么此时就会有大聪明来说了,docker top 不是能看到吗,我说你说的对,但是当一台机器上有几百个容器的时候你一个一个去 top 吗,此时你又说,那我不会写脚本吗,我说你还是说得对,但是我不接受你的建议,因为我觉着下面的方法比较更好一点。
1. 首先拿到进程号
$ top
任务: 312 total, 1 running, 311 sleeping, 0 stopped, 0 zombie
%Cpu(s): 15.8 us, 7.3 sy, 0.0 ni, 76.3 id, 0.0 wa, 0.0 hi, 0.6 si, 0.0 st
MiB Mem : 7780.5 total, 1176.4 free, 3213.0 used, 3391.0 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 4218.4 avail Mem
进程号 USER PR NI VIRT RES SHR %CPU %MEM TIME+ COMMAND
665 root 20 0 2006120 90576 36928 S 10.4 1.1 455:10.50 kubelet
26609 root 20 0 1184492 326996 43744 S 9.8 4.1 496:48.63 kube-apiserver
839 root 20 0 2001100 74616 18876 S 6.7 0.9 251:10.22 dockerd
2217 root 20 0 826372 76348 28560 S 3.0 1.0 131:50.31 kube-controller
22350 root 20 0 10.7g 59508 14772 S 2.4 0.7 130:23.39 etcd
32033 root 20 0 1747804 42408 26236 S 2.4 0.5 140:38.98 calico-node
2421 root 20 0 754792 34556 16772 S 1.2 0.4 28:55.32 kube-scheduler
35368 systemd+ 20 0 1789544 425052 5612 S 1.2 5.3 54:57.48 mysqld 比如说,我们就以 mysqld 这个进程来做实验,他的 pid 为 35368
2. 获取容器 ID
$ ps -eo 'pid,cgroup' | grep 35368 | grep 'docker-' | sed -n 's/.*docker-\([0-9a-f]\+\)\.scope.*/\1/p'| cut -c1-12
89f62f34c4743. 获取容器的信息
$ docker ps |grep 89f62f34c474
89f62f34c474 ae2502152260 "docker-entrypoint.s…" 3 days ago Up 3 days k8s_halodb_halodb-deployment-8769885fd-86tcq_default_a2e73d77-66be-490d-b6b4-7cdbd4c7c963_2 由此可以看到 k8s_halodb_halodb-deployment-8769885fd-86tcq_default_a2e73d77-66be-490d-b6b4-7cdbd4c7c963_2 就是容器名称此时你也就知道是哪个服务占用的资源了
二、获取容器内存CPU的使用情况
背景还是老样子,上面知道了资源率使用高的容器了,这次要看一下到底占用了多少
1. 查看内存使用情况
输入 top 命令进入交互式查看,通过按住键盘上的 shift + m 来查看内存使用量升序排列
top - 21:33:18 up 3 days, 23:06, 4 users, load average: 4.71, 4.06, 2.35
任务: 314 total, 1 running, 313 sleeping, 0 stopped, 0 zombie
%Cpu(s): 17.2 us, 5.3 sy, 0.0 ni, 77.2 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
MiB Mem : 7780.5 total, 1087.2 free, 3220.0 used, 3473.3 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 4211.2 avail Mem
进程号 USER PR NI VIRT RES SHR %CPU %MEM TIME+ COMMAND
35742 root 20 0 3906716 879340 42112 S 0.0 11.0 13:31.25 java
35368 systemd+ 20 0 1789544 425052 5612 S 1.5 5.3 55:13.21 mysqld
26609 root 20 0 1184492 330884 43800 S 13.8 4.2 499:02.09 kube-apiserver2. 获取容器 ID
从上面已经获取到了进程号 35742 的 Java 服务占用内存排名第一
$ cat /proc/35742/cgroup | grep 'docker' | sed 's/.*\///' | head -n 1 | sed 's/docker-//g' | cut -c1-12
123a063e96b6
$ docker ps |grep 123a063e96b6
123a063e96b6 c0787117a504 "sh -c 'java ${JVM_O…" 3 days ago Up 3 days k8s_halo_halo-deployment-76944766fc-w644j_default_18e3efaa-6689-4eab-b092-3d1be7f4fd7d_23. 获取 PID 对应的内存使用情况
# 获取 pid 进程对应的内存使用情况,默认kb
$ ps -p 35742 -o rss=
8793120
# 转换为 G
$ echo "scale=2; 8793120 / 1024 / 1024" | bc
8.38这样以来你就知道 top 查看负载均衡所知道的内存占用比较高的服务了,并且也知道了他的内存使用情况
4. 更简单的方法
通过这个命令获取到内存使用率前十排名,RSS 那一列就是内存情况,默认就是KB表示
$ ps -eo pid,comm,%mem,rss --sort=-%mem|head -n 10
PID COMMAND %MEM RSS
35742 java 11.0 879200
35368 mysqld 5.3 425052
26609 kube-apiserver 4.1 331148
2722463 ruby 2.6 214528
4444 gnome-shell 2.0 162336
665 kubelet 1.1 90436
2217 kube-controller 0.9 76348
839 dockerd 0.9 74648
22350 etcd 0.7 616205. 查看 CPU 使用情况
输入 top 命令进入交互式查看,通过按住键盘上的 shift + p 来查看内存使用量升序排列
top - 21:39:39 up 3 days, 23:12, 4 users, load average: 1.16, 1.93, 1.97
任务: 314 total, 1 running, 313 sleeping, 0 stopped, 0 zombie
%Cpu(s): 15.8 us, 10.1 sy, 0.0 ni, 74.0 id, 0.0 wa, 0.0 hi, 0.2 si, 0.0 st
MiB Mem : 7780.5 total, 1081.4 free, 3222.8 used, 3476.3 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 4208.4 avail Mem
进程号 USER PR NI VIRT RES SHR %CPU %MEM TIME+ COMMAND
26609 root 20 0 1184492 326424 43816 S 8.3 4.1 499:36.18 kube-apiserver
665 root 20 0 2006120 90636 36964 S 5.9 1.1 457:28.56 kubelet
839 root 20 0 2001100 74368 18876 S 5.0 0.9 252:24.68 dockerd用发一样这里就不再过多叙述,只是把 mem 换成 cpu 即可
$ ps -eo pid,comm,%cpu --sort=-%cpu | head -n 10
PID COMMAND %CPU
26609 kube-apiserver 8.7
665 kubelet 8.0
839 dockerd 4.4
32033 calico-node 2.4
2217 kube-controller 2.3
22350 etcd 2.2
2722463 ruby 2.1
35368 mysqld 0.9
2362000 nginx 0.86. 脚本自动获取
$ vim find_docker_containers.sh
#!/bin/bash
# 默认参数
SORT_BY="mem" # 默认按照内存排序
TOP_N=5 # 默认获取前 5 个进程
# 打印帮助信息的函数
print_help() {
echo "用法: $0 [选项]"
echo ""
echo "选项:"
echo " -s <排序方式> 按照 'cpu' 或 'mem' 排序,默认为 'mem'(内存)。"
echo " -n <前N个> 显示前 N 个进程,默认为 5。"
echo " --help 显示帮助信息。"
echo ""
echo "示例:"
echo " $0 -s mem -n 10 # 按照内存使用量排序,显示前 10 个进程。"
echo " $0 -s cpu -n 5 # 按照 CPU 使用量排序,显示前 5 个进程。"
echo " $0 --help # 显示帮助信息。"
}
# 解析命令行参数
while [[ "$1" == -* ]]; do
case "$1" in
-s) # 根据内存 (mem) 或 CPU (cpu) 排序
if [[ "$2" == "cpu" || "$2" == "mem" ]]; then
SORT_BY=$2
shift 2
else
echo "无效的排序选项。请选择 'mem' 或 'cpu'。"
print_help
exit 1
fi
;;
-n) # 获取前 N 个进程
if [[ "$2" =~ ^[0-9]+$ ]] && [ "$2" -gt 0 ]; then
TOP_N=$2
shift 2
else
echo "无效的进程数量。请输入一个正整数。"
print_help
exit 1
fi
;;
--help) # 打印帮助信息
print_help
exit 0
;;
*) # 处理无效选项
echo "无效的选项: $1"
print_help
exit 1
;;
esac
done
# 根据用户选择的排序依据调整排序字段
if [ "$SORT_BY" == "mem" ]; then
SORT_OPTION="--sort=-%mem"
elif [ "$SORT_BY" == "cpu" ]; then
SORT_OPTION="--sort=-%cpu"
fi
# 获取 top 排名前 N 的 PID 和 CPU、内存使用情况
top_pids=$(ps -eo pid,%cpu,%mem --sort=-%mem | head -n $(($TOP_N + 1)) | tail -n $TOP_N)
# 循环处理每个 PID
while read -r pid cpu mem; do
# 检查 PID 是否有效
if [ -d "/proc/$pid" ]; then
# 从 /proc/<pid>/cgroup 中提取容器 ID,并去掉前缀 docker- 和负号
container_id=$(cat /proc/$pid/cgroup | grep 'docker' | sed 's/.*\///' | head -n 1 | sed 's/docker-//g' | cut -c1-12)
# 如果找到容器 ID,获取容器的内存使用情况
if [ -n "$container_id" ]; then
container_name=$(docker inspect --format '{{.Name}}' $container_id | sed 's/\///')
# 获取 PID 对应的内存使用情况(单位:KB)
mem_usage_kb=$(ps -p $pid -o rss=)
# 将内存使用量从 KB 转换为 GB(确保小数后两位)
mem_usage_gb=$(echo "scale=2; $mem_usage_kb / 1024 / 1024" | bc)
# 如果小于 1 GB,确保显示为小数点后两位
if (( $(echo "$mem_usage_gb < 1" | bc -l) )); then
mem_usage_gb=$(printf "%.2f" $mem_usage_gb)
fi
# 输出 PID、容器 ID、容器名称、内存和 CPU 使用情况(单位:GB)
echo "PID: $pid, 容器 ID: $container_id, 容器名称: $container_name, CPU 使用量: ${cpu}%, 内存使用量: ${mem_usage_gb}GB"
else
echo "PID: $pid, 未找到 Docker 容器, CPU 使用量: ${cpu}%, 内存使用量: ${mem}%"
fi
fi
done <<< "$top_pids"$ bash find_docker_containers.sh
PID: 31017, 容器 ID: 801faca021db, 容器名称: k8s_worker_worker-67b758f4bb-4fqqn_default_ac910347-f9c6-4d27-9042-71a91dd588e8_0, 内存使用量: 3.96GB
PID: 25321, 容器 ID: 4d338bb6156c, 容器名称: k8s_arangodb_arangodb-0_default_1a9f4a06-181a-45b5-904d-5b4dad2a6e51_0, 内存使用量: 2.50GB
PID: 27181, 容器 ID: 916301a1546d, 容器名称: k8s_bos-foundation_bos-foundation-0_default_0eafdd49-d197-43b0-a236-c2c5645c1370_244, 内存使用量: 1.31GB
PID: 30340, 容器 ID: 8a9e4a509f46, 容器名称: k8s_bos-center_bos-center-797cbf9d4f-md74x_default_3f07e8d0-4e83-41e1-9355-99e802bd5b3a_246, 内存使用量: 1.28GB
PID: 30123, 容器 ID: 30932fd5a3d0, 容器名称: k8s_gateway_gateway-7996b7488-5s4ll_default_2eb46269-850d-4695-a745-3d830c641355_0, 内存使用量: 1.26GB
License:
CC BY 4.0