容器CPU持续飙升需分层排查:先用docker stats锁定异常容器,再进容器用top -H和jstack定位高CPU线程,接着检查cgroups节流、上下文切换及内存压力,最后排除日志异常、恶意脚本和非预期重启。

容器 CPU 持续飙升,不能只盯着 docker stats 看百分比。关键是要分层排查:先确认是不是容器本身的问题,再深入内部找进程,最后结合资源限制和运行时行为交叉验证。
第一步:快速锁定高负载容器
用原生命令筛出异常目标:
-
docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemPerc}}" | sort -k2 -r—— 排序后一眼看出谁在“吃”CPU - 注意持续 >80% 且波动小的容器(比如稳定在95%),比间歇性冲高的更可疑
- 同步查宿主机整体负载:
top或htop,确认不是内核线程、中断或其它非容器进程导致
第二步:进容器看进程和线程
进入疑似容器后,重点不是“哪个进程”,而是“哪个线程在干啥”:
-
top -H -p $(pgrep -f 'java\|python\|node')—— 显示指定应用的所有线程,按 CPU 排序 - 记下高占用线程的 TID(十进制),转为十六进制:
printf "%x\n" 12345 - Java 应用:用
jstack <pid> | grep -A 20 "nid=0x<hex>"定位具体方法栈 - 通用分析:用
strace -p <tod> -c统计系统调用频次,高频epoll_wait或nanosleep可能暗示轮询或死循环
第三步:检查资源节流与底层行为
CPU 高不等于“忙”,可能是被系统强制压低了——这时实际是性能受损而非过载:
- 查节流:运行
cat /sys/fs/cgroup/cpu,cpuacct/docker/<container_id>/cpu.stat | grep throttled,若nr_throttled > 0,说明容器已反复被 cgroups 限频 - 看上下文切换:
pidstat -w 1,每秒切换超 10000 次,大概率存在锁竞争或线程频繁唤醒 - 查内存压力:
cat /sys/fs/cgroup/memory/docker/<container_id>/memory.stat | grep -E "(pgmajfault|pgpgin)",大量缺页或换入,可能触发 GC 或间接拖慢 CPU
第四步:排除外部干扰与恶意行为
别默认是代码问题,有些飙升来得悄无声息:
- 查容器日志:
docker logs --since 24h <container_id> | grep -i -E "(error|exception|fail|exec|sh|bash)",留意异常命令执行痕迹 - 检查挂载目录是否被注入脚本,特别是
/hooks、/etc/cron.d或应用可写路径下的 shell 文件 - 运行
docker exec <id> find / -name "*.sh" -size -100k -mmin -1440 2>/dev/null找近24小时新建的小型脚本 - 用
docker events --filter event=start --since 24h看是否有非预期重启,配合docker inspect查启动参数是否被篡改


















