Подтвердить что ты не робот

Использование Супервизора в докере

Я не спрашиваю об использовании супервизора с докерами, я просто хочу подтвердить мое понимание.

Я понимаю, что при запуске Docker запускает один процесс. Кроме того, супервизор используется, когда нам нужно запустить несколько процессов внутри контейнера.

Я видел несколько примеров, когда контейнер запускается из базового образа, и несколько служб устанавливаются, и контейнер стремится сформировать новый образ, и все это без супервизора.

Итак, мое основное сомнение заключалось в том, в чем разница между обоими подходами.

Насколько я понимаю, когда докер-контейнер останавливается, он отправляет сигнал уничтожения процессу с PID 1, PID 1 управляет дочерним процессом и останавливает весь дочерний процесс, что в точности и делается супервизором, в то время как мы можем установить несколько процессов без супервизора только один Процесс может быть запущен при запуске docker run и когда контейнер остановлен, будут отправлены только сигналы PID 1, а другой запущенный процесс не будет остановлен изящно.

Пожалуйста, подтвердите правильность моего понимания использования supervisord.

4b9b3361

Ответ 1

в то время как мы можем установить несколько процессов без супервизора, только один процесс может быть запущен, когда запускается прогон докеров, и когда контейнер остановлен, только PID 1 будет отправлен, а другой текущий процесс не будет прекращен изящно.

Да, хотя это зависит от того, как выполняется ваш основной процесс (переднего плана или фона) и как он собирает дочерние процессы.

Это то, что подробно описано в разделе Треппинг сигналов в контейнерах Docker

docker stop останавливает запущенный контейнер, отправив ему сигнал SIGTERM, пусть основной процесс обработает его, а после периода отсрочки использует SIGKILL для завершения приложения.

Сигнал, отправленный в контейнер, обрабатывается основным процессом, который выполняется (PID 1).

Если приложение находится на переднем плане, то есть приложение является основным процессом в контейнере (PID1), оно может обрабатывать сигналы напрямую.

Но:

Сигнал, который должен сигнализироваться, может быть фоновым, и вы не можете посылать какие-либо сигналы напрямую. В этом случае одним из решений является установка shell- script в качестве точки входа и организация всей обработки сигнала в script.

Более подробная информация приведена в разделе Docker и проблема PID 1 по сбору зомби"

Unix разработан таким образом, что родительские процессы должны явно "ждать" для завершения дочернего процесса, чтобы получить статус выхода. Процесс зомби существует до тех пор, пока родительский процесс не выполнит это действие, используя семейство системных вызовов waitpid().

Действие вызова waitpid() для дочернего процесса, чтобы исключить его зомби, называется "пожинать".

Процесс init - PID 1 - имеет специальную задачу. Его задача - "принять" осиротевшие дочерние процессы.

https://blog.phusion.nl/wp-content/uploads/2015/01/adoption.png

Операционная система ожидает, что процесс init также получит усыновленных детей.

Проблема с Docker:

Мы видим, что многие люди запускают только один процесс в своем контейнере, и они думают, что когда они запускают этот единственный процесс, они сделаны.
Но, скорее всего, этот процесс не написан, чтобы вести себя как правильный процесс инициализации.
То есть вместо того, чтобы правильно использовать принятые процессы, он, вероятно, ожидает, что другой init процесс выполнит эту работу, и это правильно.

Использование изображения типа phusion/baseimage-docker помогает управлять одним (или несколькими) процессами, сохраняя при этом основной процесс, совместимый с процессом.

Он использует runit вместо supervisord для управления несколькими процессами:

Runit не существует, чтобы решить проблему пожинания. Скорее, он поддерживает несколько процессов. Множество процессов рекомендуется для обеспечения безопасности (посредством изоляции процессов и пользователей).
Runit использует меньше памяти, чем Supervisord, потому что Runit написан на C и Supervisord в Python.
И в некоторых случаях использование перезапуска процесса в контейнере предпочтительнее перезапуска всех контейнеров.

Это изображение включает my_init script, который заботится о проблеме "пожинания".

В baseimage-docker мы рекомендуем запускать несколько процессов в одном контейнере. Не обязательно несколько сервисов. Логическая услуга может состоять из нескольких процессов ОС, и мы предоставляем возможности для этого.

Ответ 2

Обновление от 2016 года для докеров 1.12 (Q4 2016/Q1 2017)

Arnaud Porterie просто twitted:

[🐳] Просто слито: с docker run --init, Рик Граймс позаботится обо всех ваших зомби.

(commit eabae09)

См. PR 26061: " Добавить процесс инициализации для борьбы с зомби и обработки сигналов" (и PR 26736)

Это добавляет небольшой C-бит для борьбы с зомби. Он монтируется под /dev/init и добавляется к аргументам, указанным пользователем. Вы включите его через флаг daemon, dockerd --init, поскольку он отключен по умолчанию для обратной совместимости.

Вы также можете переопределить параметр daemon или указать это на контейнер с 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

Запустите инициализацию внутри контейнеров, чтобы пересылать сигналы и обрабатывать процессы