通过入门点启动时,Docker容器的100%CPU

100% CPU for Docker Container when started via entrypoint

本文关键字:Docker 100%CPU 启动      更新时间:2023-10-16

我们编写了一个小的C 应用程序,该应用程序主要通过Zeromq对其他过程进行一些监督。因此,大多数情况下,应用程序闲置和周期会发送并收到一些请求。

我们基于ubuntu构建了一个Docker映像,该图像仅包含此应用程序,一些依赖项和entrypoint.sh。入口点基本上以/bin/bash运行,根据环境变量操纵某些配置文件,然后通过exec启动应用程序。

现在这是奇怪的部分。当我们在没有Docker的情况下手动启动应用程序时,我们将获得近0%的CPU使用情况。当我们启动与Docker Image相同的应用程序时,CPU使用率最高为100%,并且恰好阻止一个CPU核心。

要找出发生了什么事,我们将图像的入口点设置为/bin/yes(只是为了确保容器保持运行(,然后在运行的容器内启动bash。从那里我们手动启动entrypoint.sh,CPU再次处于0%。

所以我们想知道,什么可能导致这种情况。我们需要添加到dockerfile中以防止这种情况吗?


这是用strace生成的一些输出。我使用strace -p <pid> -f -c并等待五分钟来收集一些见解。

1。使用docker run(100%CPU(

运行
strace: Process 12621 attached with 9 threads
strace: [ Process PID=12621 runs in x32 mode. ]
[...]
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 71.26   17.866443         144    124127           nanosleep
 14.40    3.610578       55547        65        31 futex
 14.07    3.528224        1209      2918           epoll_wait
  0.10    0.024760        4127         6         1 restart_syscall
  0.10    0.024700           0     66479           poll
  0.05    0.011339           4      2902         3 recvfrom
  0.02    0.005517           2      2919           write
  0.01    0.001685           1      2909           read
  0.00    0.000070          70         1         1 connect
  0.00    0.000020          20         1           socket
  0.00    0.000010           1        18           epoll_ctl
  0.00    0.000004           1         6           sendto
  0.00    0.000004           1         4           fcntl
  0.00    0.000000           0         1           close
  0.00    0.000000           0         1           getpeername
  0.00    0.000000           0         1           setsockopt
  0.00    0.000000           0         1           getsockopt
------ ----------- ----------- --------- --------- ----------------
100.00   25.073354                202359        36 total

2。使用虚拟入门点和docker exec(0%CPU(

运行
strace: Process 31394 attached with 9 threads
[...]
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 67.32   12.544007         102    123355           nanosleep
 14.94    2.784310       39216        71        33 futex
 14.01    2.611210         869      3005           epoll_wait
  2.01    0.373797           6     66234           poll
  1.15    0.213487          71      2999           recvfrom
  0.41    0.076113       15223         5         1 restart_syscall
  0.09    0.016295           5      3004           write
  0.08    0.014458           5      3004           read
------ ----------- ----------- --------- --------- ----------------
100.00   18.633677                201677        34 total

请注意,在第一种情况下,我稍早启动strace,因此有一些不同的调用可以追溯到初始化代码。

使用docker run时,我唯一可以找到的是线Process PID=12621 runs in x32 mode.。这可能是一个问题吗?

还要注意,在这两个测量值中,总运行时间约为20秒,而过程运行五分钟。


对100%CPU病例的进一步研究。我使用top -H -p <pid>检查了该过程,只有父进程使用100%CPU,而子螺纹都大部分都是空转的。但是,当我可以在父进程上调用strace -p <pid>时,我可以验证该过程没有做任何事情(没有产生输出(。

所以我确实有一个使用CPU的整个核心的过程。

,因为事实证明该软件的某些遗留部分正在等待游戏机输入一段时间:

while (!finished) {
  std::cin >> command;
  processCommand(command)
}

因此,在本地运行和使用docker exec运行时,这正常工作。但是,由于可执行文件是作为Docker服务开始的,因此没有控制台。因此,std::cin是非障碍物并立即返回的。这样,我们创建了一个无尽的循环,而无需任何睡眠,这自然会导致100%CPU使用。

感谢@botje指导我们完成调试过程。