Как реализовать деплой Python микросервисов?
DevOpsавтоматизациядеплойинфраструктурамикросервисы
Что проверяют
Есть ли у вас сквозная картина от коммита до работающего пода: сборка образа, конфигурация, выкатка без простоя, откат. Уточнение обычно про миграции базы при нескольких репликах или про то, как сервис корректно останавливается.
Как отвечать
Пройдите по конвейеру по порядку:
- образ: многоэтапный
Dockerfileна slim-образе актуальной поддерживаемой версии Python, зависимости из lock-файла (uvилиpipс зафиксированными версиями), запуск не от root. Команда в exec-форме,CMD ["gunicorn", ...], чтобы процесс получилSIGTERM; - сервер приложений: для FastAPI
uvicornилиgunicornс воркерами Uvicorn, для Django и Flaskgunicorn. Встроенный отладочный сервер фреймворка в прод не идёт; - CI: линтер, тесты, сборка, публикация образа в реестр с тегом по SHA коммита. Тег
latestдля деплоя не годится: по нему не понять, что запущено, и не откатиться; - конфигурация: всё через переменные окружения, секреты из Kubernetes Secrets или Vault, один образ на все окружения;
- Kubernetes:
Deploymentсо стратегиейRollingUpdate, заданныеrequestsиlimits,readinessProbeиlivenessProbe. Манифесты через Helm или Kustomize, выкатка через GitOps (Argo CD) или шаг пайплайна; - миграции: отдельный
Jobили шаг пайплайна до выкатки, а схема меняется обратно совместимо: сначала добавить колонку, потом переключить код, потом удалить старое; - остановка: обработать
SIGTERM, дождаться текущих запросов. По умолчанию у пода 30 секунд (terminationGracePeriodSeconds), потом придётSIGKILL; - наблюдаемость: логи в stdout в JSON, метрики для Prometheus, трассировка через OpenTelemetry. Откат через
kubectl rollout undoили откат коммита в GitOps-репозитории.
Где спотыкаются
Запускают миграции при старте приложения. Три реплики стартуют одновременно и гоняют одну миграцию наперегонки.
Не настраивают readinessProbe. Трафик идёт в под, который ещё грузит модели или не подключился к базе, и каждая выкатка даёт всплеск ошибок.
Пишут CMD в shell-форме: PID 1 становится оболочка, сигнал до Python не доходит, и под убивается по таймауту посреди запросов.