Корректная остановка контейнера
Вопрос
Почему контейнер может не завершаться корректно при docker stop или удалении пода, и как это исправить?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
`docker stop` шлёт SIGTERM главному процессу, ждёт таймаут (по умолчанию 10 с) и шлёт SIGKILL
Shell-форма CMD или скрипт-обёртка без `exec`: PID 1 это shell, сигнал не доходит до приложения
PID 1 не имеет действий по умолчанию для сигналов: без обработчика SIGTERM игнорируется
Исправление: exec-форма, `exec "$@"` в entrypoint-скрипте, обработчик SIGTERM в коде
`tini`/`--init` пересылает сигналы и забирает зомби
Приложение при SIGTERM перестаёт принимать запросы, доделывает текущие и выходит быстрее таймаута
Что могут спросить следом
- Что меняет
STOPSIGNAL? - Как это связано с
terminationGracePeriodSecondsв Kubernetes?
Разбор
docker stop отправляет главному процессу контейнера SIGTERM, ждёт 10 секунд и, если тот не вышел, отправляет SIGKILL. Kubernetes делает так же, только таймаут terminationGracePeriodSeconds по умолчанию 30 секунд. Проблемы бывают трёх видов. Первая: shell-форма CMD или entrypoint-скрипт, который запускает приложение без exec. Тогда PID 1 это shell, а приложение его потомок, и сигнал до него не доходит. Лечится exec-формой и exec "$@" в конце скрипта. Вторая: PID 1 в Linux особенный, ядро не применяет к нему действие сигнала по умолчанию, так что приложение без обработчика просто проигнорирует SIGTERM. Нужен явный обработчик. Третья: зомби от дочерних процессов, их прибирает tini или docker run --init. И сам обработчик должен быть правильным: перестать принимать новые запросы, дождаться текущих, закрыть соединения и выйти до таймаута. Если приложение ждёт другой сигнал, его задают через STOPSIGNAL.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.