🚑 HEALTHCHECK: Спасательный круг или выстрел в ногу?
Продолжаем тему стабильности. Сегодня про Healthchecks (в Docker) и Probes (в K8s).
Казалось бы, что сложного? Написал
Разберем две крайности и как делать правильно.
❌ Ошибка №1: "Зомби-апокалипсис" (Слишком слабый чек)
Вы проверяете только то, что процесс веб-сервера запущен и порт слушается.
🔘 Сценарий: У приложения отвалился коннект к БД (pool exhaustion), или случился дедлок внутри кода.
🔘 Итог: Хелсчек проходит (порт-то открыт!), балансировщик продолжает лить трафик на под, а пользователи получают 500-ки.
🔘 Лечение: Чек должен проверять работоспособность логики, а не просто наличие процесса.
❌ Ошибка №2: "Эффект Домино" (Слишком жадный чек)
Вы решили быть умными и в
🔘 Сценарий: База данных немного приуныла (медленные запросы).
🔘 Итог: Хелсчеки всех 50 подов начинают тайм-аутить. Kubernetes думает: "Ага, поды сдохли!" и начинает их перезагружать.
🔘 Финал: Все поды рестартуют одновременно, ломятся устанавливать соединения к и так лежащей базе и добивают её окончательно. Congratulations, you played yourself.
✅ Как делать правильно: Liveness vs Readiness
В Kubernetes (да и в грамотном Docker Compose) эти понятия разделены. Это фундамент.
1. Liveness Probe (Я жив?)
🔘 Цель: Понять, не завис ли процесс намертво.
🔘 Действие при сбое: РЕСТАРТ контейнера.
🔘 Что проверять: Очень легкий запрос. "Я могу отвечать на HTTP?". Не трогайте тут базу данных! Если база лежит, рестарт бэкенда не поможет ей подняться.
2. Readiness Probe (Я готов работать?)
🔘 Цель: Понять, можно ли пускать на меня трафик.
🔘 Действие при сбое: УБРАТЬ из балансировки (не убивать!).
🔘 Что проверять: Вот тут проверяем зависимости. Есть коннект к БД? Прогрелся кэш? Если нет, просто временно не шлите на меня юзеров.
📝 Пример (K8s Manifest):
💡 Главный совет
Никогда не делайте зависимость Liveness-пробы от внешних сервисов. Если у вас упал сторонний API, ваш сервис не должен уходить в циклическую перезагрузку. Он должен просто перестать говорить, что он
#k8s #devops #fails #stability #bestpractices
Подпишись 👉@devopslib
Продолжаем тему стабильности. Сегодня про Healthchecks (в Docker) и Probes (в K8s).
Казалось бы, что сложного? Написал
curl -f http://localhost/ || exit 1 и пошел пить кофе. Но именно такие "простые" решения часто становятся причиной того, что ваш прод лежит, хотя нагрузка детская.Разберем две крайности и как делать правильно.
❌ Ошибка №1: "Зомби-апокалипсис" (Слишком слабый чек)
Вы проверяете только то, что процесс веб-сервера запущен и порт слушается.
❌ Ошибка №2: "Эффект Домино" (Слишком жадный чек)
Вы решили быть умными и в
/health эндпоинт засунули проверку коннекта к Базе, Редису и S3.✅ Как делать правильно: Liveness vs Readiness
В Kubernetes (да и в грамотном Docker Compose) эти понятия разделены. Это фундамент.
1. Liveness Probe (Я жив?)
2. Readiness Probe (Я готов работать?)
📝 Пример (K8s Manifest):
livenessProbe:
httpGet:
path: /health/live # Максимально тупой ответ 200 OK
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /health/ready # Проверка БД, очередей и т.д.
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
failureThreshold: 3
💡 Главный совет
Никогда не делайте зависимость Liveness-пробы от внешних сервисов. Если у вас упал сторонний API, ваш сервис не должен уходить в циклическую перезагрузку. Он должен просто перестать говорить, что он
Ready, или отдавать ошибку юзеру, оставаясь "живым".#k8s #devops #fails #stability #bestpractices
Подпишись 👉@devopslib
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥1👏1
🛑 Не убивай меня сразу! Настраиваем Graceful Shutdown
Коллеги, бывало такое? Вы делаете
Проблема часто не в балансировщике, а в том, что ваше приложение не умеет "красиво уходить" (Graceful Shutdown).
Когда Kubernetes хочет остановить под, происходит следующий танец:
1. K8s посылает процессу сигнал SIGTERM.
2. K8s ждет
3. Если процесс еще жив -прилетает SIGKILL (выстрел в голову).
❌ Как делают новички
Приложение получает
🔘 Результат: Все запросы, которые обрабатывались в эту миллисекунду (транзакция в БД, загрузка файла), обрываются. Клиент получает ошибку.
✅ Как надо (Уровень Code)
Приложение должно перехватывать
Получив сигнал, оно должно:
1. Перестать принимать новые соединения.
2. Дождаться завершения текущих запросов.
3. Закрыть коннекты к БД/очередям.
4. Выйти (
💀 Скрытая проблема Kubernetes (Race Condition)
Даже если ваш код идеален, вы все равно можете словить 502.
Почему?
В тот момент, когда K8s посылает
Это асинхронный процесс. Может случиться так, что Ingress Controller все еще шлет трафик на под, а приложение уже получило SIGTERM и закрыло порт.
💊 Решение: "The Sleep Hack"
Как бы глупо это ни звучало, но best practice в мире K8s - это вставить небольшую паузу перед остановкой.
Мы используем
Что это дает?
1. K8s запускает хук:
2. Под помечается как
3. За эти 5 секунд Ingress/Service успевают обновить свои таблицы маршрутизации и перестают слать новый трафик на этот под.
4.
⚙️ Чек-лист для идеального деплоя:
1. В коде обработан
2. В K8s добавлен
3.
Уважайте своих пользователей, не сбрасывайте их сессии посередине оплаты! 😉
#k8s #devops #architecture #go #python #bestpractices
Подпишись 👉@devopslib
Коллеги, бывало такое? Вы делаете
kubectl rollout restart, Kubernetes обещает бесшовное обновление, но в момент переключения подов пару юзеров все равно ловят 502 Bad Gateway или обрывы соединений.Проблема часто не в балансировщике, а в том, что ваше приложение не умеет "красиво уходить" (Graceful Shutdown).
Когда Kubernetes хочет остановить под, происходит следующий танец:
1. K8s посылает процессу сигнал SIGTERM.
2. K8s ждет
terminationGracePeriodSeconds (по дефолту 30 сек).3. Если процесс еще жив -прилетает SIGKILL (выстрел в голову).
❌ Как делают новички
Приложение получает
SIGTERM и... мгновенно закрывается.✅ Как надо (Уровень Code)
Приложение должно перехватывать
SIGTERM.Получив сигнал, оно должно:
1. Перестать принимать новые соединения.
2. Дождаться завершения текущих запросов.
3. Закрыть коннекты к БД/очередям.
4. Выйти (
exit 0).💀 Скрытая проблема Kubernetes (Race Condition)
Даже если ваш код идеален, вы все равно можете словить 502.
Почему?
В тот момент, когда K8s посылает
SIGTERM, он параллельно начинает удалять IP пода из Endpoints (Service).Это асинхронный процесс. Может случиться так, что Ingress Controller все еще шлет трафик на под, а приложение уже получило SIGTERM и закрыло порт.
💊 Решение: "The Sleep Hack"
Как бы глупо это ни звучало, но best practice в мире K8s - это вставить небольшую паузу перед остановкой.
Мы используем
preStop хук. Он выполняется ДО отправки SIGTERM.
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 5"]
Что это дает?
1. K8s запускает хук:
sleep 5.2. Под помечается как
Terminating.3. За эти 5 секунд Ingress/Service успевают обновить свои таблицы маршрутизации и перестают слать новый трафик на этот под.
4.
sleep заканчивается -> летит SIGTERM -> приложение спокойно доделывает старые запросы -> Profit! 🚀⚙️ Чек-лист для идеального деплоя:
1. В коде обработан
SIGTERM.2. В K8s добавлен
preStop хук со слипом (5-10 сек).3.
terminationGracePeriodSeconds выставлен с запасом (напр. 60 сек, если у вас долгие запросы), чтобы SIGKILL не прилетел слишком рано.Уважайте своих пользователей, не сбрасывайте их сессии посередине оплаты! 😉
#k8s #devops #architecture #go #python #bestpractices
Подпишись 👉@devopslib
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🤩1