2015-10-14 7 views
23

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

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

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

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

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

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

Благодаря

+0

Update сентября 2016: см [мой новый ответ ] (http://stackoverflow.com/a/39593409/6309) ниже: демон докеров может позаботиться об этих процессах зомби для вас в докере 1.12. – VonC

ответ

38

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

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

То есть то, что подробно описано в «Trapping signals in Docker containers»

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

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

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

Но:

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

Этот вопрос более подробно в «Docker and the PID 1 zombie reaping problem»

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

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

init процесс - PID 1 - есть специальная задача. Его задача - «принять» осиротевшие детские процессы.

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

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

Проблема с Докерами:

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

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

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

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

Это изображение содержит my_init script, который заботится о проблеме «пожинания».

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

+0

Спасибо за подробный ответ. Я пытаюсь создать изображение с использованием phusion, и, насколько я понимаю, всякий раз, когда запускается контейнер, он запускает все, что находится в /etc/init.d. Но у меня есть служба в init.d, которая не начинается с загрузки контейнера. Вы можете помочь. – user3275095

+0

Уверен: можете ли вы задать новый вопрос, с деталями вашей новой установки? Таким образом, я (и, возможно, другие) могу взглянуть. – VonC

+0

О, моя ошибка его /etc/my_init.d – user3275095

10

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

Arnaud Porterie просто twitted:

[] Только слиты: с docker run --init, Rick Grimes будет заботиться о всех ваших зомби.

(commit eabae09)

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

Это добавляет небольшой C двоичный файл для борьбы с зомби. Он монтируется под /dev/init и добавляется к аргументам, указанным пользователем. Вы используете с помощью флага daemon, 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); 
} 

The docker daemon теперь имеет возможность

--init 

запустить инициализации внутри контейнеров для пересылки сигналов и пожинать процессам

+0

Спасибо за обновление. – user3275095

Смежные вопросы