Healthcheck FastAPI: почему живой процесс ещё не готов к запросам
У сервиса есть /health, который всегда возвращает 200. Мониторинг зелёный, но пользователи не могут открыть заказы: соединение с базой не устанавливается. Тогда в /health добавляют запрос к базе. Теперь краткий сбой PostgreSQL приводит к перезапуску всех экземпляров API. Получилось два разных вопроса, спрятанных за одним адресом.
Первый вопрос: способен ли процесс продолжать работу или он завис? Второй: стоит ли сейчас направлять ему пользовательские запросы? Для них удобно иметь разные проверки.
Два адреса с разным смыслом
Этот маленький пример демонстрирует разделение. Установка — python -m pip install fastapi uvicorn, запуск main.py — python -m uvicorn main:app.
from contextlib import asynccontextmanager
from fastapi import FastAPI, HTTPException, Request
@asynccontextmanager
async def lifespan(app: FastAPI):
app.state.ready = True
try:
yield
finally:
app.state.ready = False
app = FastAPI(lifespan=lifespan)
@app.get("/live")
async def live():
return {"status": "alive"}
@app.get("/ready")
async def ready(request: Request):
if not request.app.state.ready:
raise HTTPException(503, "Not ready")
return {"status": "ready"}
Флаг здесь показывает механизм ответа 503, а не полноценную диагностику PostgreSQL. В рабочем приложении критерий ready выбирают по реальным обязательным ресурсам. Проверка базы должна быть короткой, ограниченной по времени и дешёвой.
Какие последствия у отказа
В Kubernetes неуспешная readiness-проверка убирает Pod из готовых адресов сервиса. Неуспешная liveness-проверка после заданного порога приводит к перезапуску контейнера. Поэтому временная недоступность общей базы не всегда должна становиться причиной liveness-отказа всех API.
Для долгой инициализации существует startup-проверка. Она позволяет отдельно описать время старта, не ослабляя рабочие проверки уже запущенного приложения. Конкретные интервалы и пороги выбирайте по времени прогрева своего сервиса.
Что сломать на учебном стенде
Проверьте три сценария: приложение нормально работает; обязательная зависимость недоступна; процесс приложения остановлен. Для второго случая ожидайте отсутствие нового трафика к неготовому экземпляру, если так настроен балансировщик. Для третьего — обнаружение остановки и восстановление процесса системой запуска.
Проверяйте также восстановление зависимости. Готовность должна возвращаться, когда сервис снова способен обрабатывать запросы, без ручного изменения флага в коде.
Не помещайте в ответ healthcheck пароли, строки подключения и подробный traceback. Мониторингу достаточно статуса и короткого безопасного кода причины. И помните: Docker healthcheck сам по себе не означает автоматический перезапуск — это разобрано в статье про unhealthy и restart always.
Собрать следующий этап проекта
После первого запуска появляются задачи администратора: служба должна стартовать после перезагрузки, логи — помогать искать сбои, обновление — быть воспроизводимым. На курсе DevOps с нуля эти части соединяются в учебный стенд с Linux, Docker, CI/CD и мониторингом.
Посмотреть программу: DevOps-инженер с нуля: полный курс
Проверить детали: Kubernetes: типы probes, FastAPI lifespan.
Продолжить на практике
- DevOps-инженер с нуля: полный курс ↗
Практический курс по DevOps для начинающих: от настройки Linux и сетей до сборки контейнеров, автоматизации в GitLab CI/CD, развёртывания в Kubernetes, мониторинга и восстановления данных на собственном компьютере.
- FastAPI для начинающих: API с базой данных и тестами ↗
Соберёте свой первый полноценный backend на FastAPI: с базой данных, регистрацией, JWT-авторизацией и автотестами. 34 коротких урока и 140 заданий с проверкой — бесплатно.
