分析Ubuntu虚拟机卡顿的问题,排查发现并非内存耗尽,而是 OpenWrt 编译导致 CPU 长时间高负载;为 Docker 容器限制内存并设置 6 核 CPU 配额,提升交互响应能力。

问题背景

当前开发环境如下:

Windows  
 └─ VMware Workstation  
     └─ Ubuntu 24.04  
         └─ Docker  
             └─ OpenWrt 编译环境

日常通过以下方式进行开发:

Windows Terminal  
    ↓  
SSH  
    ↓  
Ubuntu 虚拟机  
    ↓  
Docker 容器  
    ↓  
OpenWrt 编译

运行一段时间后发现:

  • Ubuntu 虚拟机内存占用持续升高;
  • 系统内存使用率经常达到 90% 以上;
  • SSH 登录及终端操作出现明显卡顿;
  • tmux、vim 等交互操作延迟增加;
  • OpenWrt 编译期间现象更加明显。

因此需要分析资源消耗来源,并对 Docker 编译容器进行资源限制。

问题排查过程

检查 Docker 容器配置

查看容器:

docker ps -a

目标容器:

ubuntu14.04_be400v1

查看内存配置:

docker inspect ubuntu14.04_be400v1 | grep -i -A5 -B5 memory

结果:

"Memory": 0,  
"MemoryReservation": 0,  
"MemorySwap": 0

说明:

Docker容器未设置任何内存限制

理论上容器可以使用宿主机全部可用内存。

尝试限制 Docker 内存

第一次执行:

docker update \  
    --memory 8g \  
    ubuntu14.04_be400v1

报错:

Memory limit should be smaller than already set memoryswap limit

原因:

设置 Memory 时必须同时设置 MemorySwap

Docker要求:

MemorySwap >= Memory

错误配置示例

docker update \  
    --memory 8g \  
    --memory-swap 2g \  
    ubuntu14.04_be400v1

报错:

Minimum memoryswap limit should be larger than memory limit

正确配置

docker update \
   –memory 8g \
   –memory-swap 8g \
  ubuntu14.04_be400v1

执行成功。

验证内存限制效果

查看:

docker stats --no-stream

输出:

CONTAINER ID   NAME                  CPU %      MEM USAGE / LIMIT  
...            ubuntu14.04_be400v1   4151.13%   644.1MiB / 8GiB

发现:

  • 内存实际占用仅 644MB;
  • 距离 8GB 限制还有很大空间;
  • 问题并非由 Docker 内存耗尽导致。

真正的问题定位

Ubuntu 虚拟机 CPU 数量:

nproc
8

OpenWrt 编译过程中会启动大量编译任务:

gcc  
g++  
ld  
nm  
strip  
objcopy  
cmake  
make

导致 CPU 长时间接近满载,从而出现:

  • SSH 卡顿
  • tmux 卡顿
  • vim 输入延迟
  • 终端响应变慢

最终判断:CPU资源才是真正瓶颈

可选解决方案分析

方案一:限制编译并发数

make -j4 或 make -j5

优点:

  • 实现简单
  • 可显著降低 CPU 压力

缺点:

  • 需要修改编译习惯
  • 可能影响编译速度

方案二:降低进程优先级

nice -n 10 make -j5 或者 ionice -c3 make -j5

优点:保证交互任务优先

缺点:效果有限

方案三:限制 Docker CPU

docker update \  
    --cpus 6 \  
    ubuntu14.04_be400v1

含义:

宿主机:8核心
容器:最多使用6核心
系统保留:2核心

优点:

  • 一次配置长期生效
  • 不依赖编译命令
  • 能保证系统响应能力

最终采用方案

经过分析后确认:

问题表象:内存占用率高
实际原因:OpenWrt 编译导致 CPU 长时间高负载

最终采用如下配置:

docker update \  
    --memory 8g \  
    --memory-swap 8g \  
    --cpus 6 \  
    ubuntu14.04_be400v1

参数说明:

参数含义
–memory 8g最大内存限制 8GB
–memory-swap 8g禁止额外使用 Swap
–cpus 6最多使用 6 个 CPU

配置效果

实施后达到以下目标:

内存控制

Docker 最大使用 8GB 内存

CPU控制

Docker 最多使用 6 个 CPU
Ubuntu 保留约 2 个 CPU

能够保证:

SSH
Tmux
Vim
Shell

在编译期间仍保持较好的响应速度。

最终结论

本次问题最初怀疑为 Docker 占用过多内存。

经过排查发现:

  • Docker 实际内存占用仅约 644MB;
  • 内存并非主要瓶颈;
  • OpenWrt 编译期间 CPU 被大量占用;
  • CPU 调度压力导致 SSH、tmux、vim 等交互操作卡顿。

最终采用如下配置:

docker update \  
    --memory 8g \  
    --memory-swap 8g \  
    --cpus 6 \  
    ubuntu14.04_be400v1

实现了对 Docker 编译容器的资源隔离,在保证编译效率的同时提升 Ubuntu 虚拟机的整体可用性和稳定性。