Использование Supervisor в докере
Я не спрашиваю об использовании супервизора с докерами, я просто хочу подтвердить мое понимание.
Я понимаю, что при запуске Docker запускает один процесс. Кроме того, супервизор используется, когда нам нужно запустить несколько процессов внутри контейнера.
Я видел несколько примеров, когда контейнер запускается из базового образа, и несколько служб устанавливаются, и контейнер стремится сформировать новый образ, и все это без супервизора.
Итак, мое основное сомнение заключалось в том, в чем разница между обоими подходами.
Насколько я понимаю, когда докер-контейнер останавливается, он отправляет сигнал уничтожения процессу с PID 1, PID 1 управляет дочерним процессом и останавливает весь дочерний процесс, что в точности и делается супервизором, в то время как мы можем установить несколько процессов без супервизора только один Процесс может быть запущен при запуске Docker, и когда контейнер остановлен, будут отправлены только сигналы PID 1, а другой запущенный процесс не будет остановлен изящно.
Пожалуйста, подтвердите правильность моего понимания использования супервизора.
Спасибо
2 ответа
в то время как мы можем установить несколько процессов без супервизора, только один процесс может быть запущен при запуске Docker, а когда контейнер остановлен, будут отправлены только сигналы PID 1, а другой запущенный процесс не будет остановлен изящно.
Да, хотя это зависит от того, как работает ваш основной процесс (передний план или фон), и как он собирает дочерние процессы.
Это то, что подробно описано в разделе" Улавливание сигналов в контейнерах Docker ".
docker stop
останавливает работающий контейнер, отправляя егоSIGTERM
сигнал, пусть основной процесс обрабатывает его, и после льготного периода используетSIGKILL
прекратить заявку.Сигнал, отправляемый в контейнер, обрабатывается основным процессом, который выполняется (PID 1).
Если приложение находится на переднем плане, то есть приложение является основным процессом в контейнере (PID1), оно может обрабатывать сигналы напрямую.
Но:
Процесс, который должен быть сигнализирован, может быть фоновым, и вы не можете отправлять какие-либо сигналы напрямую. В этом случае одно из решений состоит в том, чтобы установить сценарий оболочки в качестве точки входа и организовать всю обработку сигналов в этом сценарии.
Эта проблема более подробно описана в " Докер и проблема пожатия зомби PID 1 "
Unix спроектирован таким образом, что родительские процессы должны явно "ждать" завершения дочернего процесса, чтобы получить статус выхода. Процесс зомби существует, пока родительский процесс не выполнил это действие, используя
waitpid()
семейство системных вызовов.Действие вызова waitpid() для дочернего процесса с целью устранения его зомби называется "пожинанием".
init
У процесса - PID 1 - есть специальная задача. Его задача - "усыновить" осиротевшие дочерние процессы.
Операционная система ожидает, что процесс init тоже получит приемных детей.
Проблема с докером:
Мы видим, что многие люди запускают только один процесс в своем контейнере, и они думают, что когда они запускают этот единственный процесс, они закончили.
Но, скорее всего, этот процесс не написан так, чтобы вести себя как правильный процесс инициализации.
То есть вместо того, чтобы должным образом пожинать принятые процессы, он, вероятно, ожидает другогоinit
процесс, чтобы сделать эту работу, и это правильно.
Используя изображение какphusion/baseimage-docker
помочь в управлении одним (или несколькими) процессами, в то же время поддерживая основной процесс инициализированным.
Оно использует runit
вместоsupervisord
для многопроцессного управления:
Runit не существует, чтобы решить проблему пожатия. Скорее, это для поддержки нескольких процессов. Для обеспечения безопасности рекомендуется использовать несколько процессов (посредством изоляции процессов и пользователей).
Runit использует меньше памяти, чем http://supervisord.org/, потому что Runit написан на C, а Supervisord на Python.
А в некоторых случаях перезапуски процесса в контейнере предпочтительнее, чем перезапуск всего контейнера.
Это изображение включает в себя my_init
скрипт, который решает проблему "пожинания".
В baseimage-docker мы рекомендуем запускать несколько процессов в одном контейнере. Не обязательно несколько услуг, хотя.
Логическая служба может состоять из нескольких процессов ОС, и мы предоставляем средства, позволяющие легко это сделать.
Обновление в сентябре 2016 года для докера 1.12 (4 квартал 2016 года / первый квартал 2017 года)
Арно Портери только что прокричал:
[] Просто слил: с
docker run --init
Рик Граймс позаботится обо всех ваших зомби.
См. PR 26061: "Добавить процесс инициализации для борьбы с зомби и обработки сигналов" (и PR 26736).
Это добавляет небольшой двоичный файл C для борьбы с зомби. Он монтируется в /dev/init и добавляется к аргументам, указанным пользователем. Вы включаете его с помощью флага демона, dockerd --init, так как он отключен по умолчанию для обратного сжатия.
Вы также можете переопределить параметр демона или указать его для каждого контейнера с помощью
docker run --init=true|false
,Вы можете проверить это, запустив такой процесс как pid 1 в контейнере и увидев дополнительного зомби, который появляется в контейнере во время его работы.
int main(int argc, char ** argv) {
pid_t pid = fork();
if (pid == 0) {
pid = fork();
if (pid == 0) {
exit(0);
}
sleep(3);
exit(0);
}
printf("got pid %d and exited\n", pid);
sleep(20);
}
Демон Docker теперь имеет опцию
--init
Запустите init внутри контейнеров для пересылки сигналов и запуска процессов
В этой статье в документации Docker показан пример запуска нескольких процессов, а также использования supervisord.
https://docs.docker.com/config/containers/multi-service_container/
У меня это работает нормально, но мы, скорее всего, просто перенесем наши рабочие процессы в другой контейнер и будем иметь дело только с одним процессом в каждом. На данный момент это кажется более простым подходом.