Мы написали небольшое приложение на C++, которое в основном контролирует другие процессы через ZeroMQ. Поэтому большую часть времени приложение бездействует и периодически отправляет и получает какие-то запросы.
Мы создали образ докера на основе ubuntu
, который содержит только это приложение, некоторые зависимости и файл entrypoint.sh
. Точка входа в основном работает как /bin/bash
, манипулирует некоторыми файлами конфигурации на основе переменных среды, а затем запускает приложение через exec
.
Теперь вот странная часть. Когда мы запускаем приложение вручную без докера, мы получаем загрузку ЦП почти 0%. Когда мы запускаем то же приложение, что и образ докера, загрузка ЦП достигает 100% и блокирует ровно одно ядро ЦП.
Чтобы выяснить, что происходит, мы установили точку входа нашего образа в /bin/yes
(просто чтобы убедиться, что контейнер продолжает работать), а затем запустили bash внутри работающего контейнера. Оттуда мы запустили entrypoint.sh
вручную, и ЦП снова был на 0%.
Поэтому нам интересно, что могло вызвать эту ситуацию. Есть ли что-нибудь, что нам нужно добавить в наш Dockerfile, чтобы предотвратить это?
Вот некоторые выходные данные, созданные с помощью strace
. Я использовал strace -p <pid> -f -c
и подождал пять минут, чтобы собрать информацию.
1. Запуск с docker run
(100% ЦП)
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% ЦП)
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
немного раньше, поэтому есть несколько разных вызовов, которые можно проследить до кода инициализации.
Единственное отличие, которое я смог найти, это строка Process PID=12621 runs in x32 mode.
при использовании docker run
. Может ли это быть проблемой?
Также обратите внимание, что в обоих измерениях общее время выполнения составляет около 20 секунд, в то время как процесс выполнялся в течение пяти минут.
Некоторые дальнейшие исследования в случае 100% CPU. Я проверил процесс с помощью top -H -p <pid>
, и только родительский процесс использовал 100% ЦП, в то время как все дочерние потоки в основном простаивали. Но при вызове strace -p <pid>
в родительском процессе я мог убедиться, что процесс ничего не сделал (вывод не был сгенерирован).
Итак, у меня есть процесс, который использует все ядро моего процессора и ничего не делает.
strace
к запущенной команде и посмотрите, какие системные вызовы она выполняет. Сравните с «родным» запуском. Возможно, где-то небольшое несоответствие. - person Botje   schedule 01.08.2019strace
входить в процессы docker. Я добавил свои результаты strace к исходному вопросу. - person Markus K   schedule 01.08.2019connect
. Это звучит как что-то для расследования. В качестве альтернативы вы можете попробовать подключить GDB к процессу внутри Docker, чтобы увидеть, где он тратит все процессорное время. - person Botje   schedule 01.08.2019