Карта дня, май, перетяжка
Карта дня, май, перетяжка
Карта дня, май, перетяжка

Как не сломать прод? Топ 5 самых частых ошибок при деплое

Вы все сделали идеально, нажимаете кнопку Deploy, и наступает тот самый момент, когда сердце замирает. Прод горит, мониторинги упали, команда в ужасе. Что нужно сделать, чтобы такого не было — рассказываем в статье.

969 открытий8К показов
Как не сломать прод? Топ 5 самых частых ошибок при деплое

Когда вы деплоите, вы не просто заливаете код. Считайте, что это босс на последнем уровне, а значит — привет, ловушки и подводные камни. Ошибки на этом этапе могут стоить дорого: от недовольства техлида до потери клиентов. Мы собрали топ самых частых (и самых болезненных) багов при выкладке — рассказываем, как их избежать.

Неправильная настройка инфраструктуры в CI/CD пайплайне

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

Настройте окружение

Разные окружения (dev, staging, prod) часто имеют отличия в конфигурации (например, версии библиотек, лимиты ресурсов, настройки сетей). Например, переменные окружения, заданные для staging, перезаписываются в prod — зависимости ломаются.

  • Используйте Infrastructure as Code (IaC) инструменты, такие как Terraform или Pulumi, для создания идентичных окружений.
  • Храните конфигурации окружений в репозитории (например, в формате YAML или JSON) и применяйте их через CI/CD.
  • Настройте переменные окружения через секреты (например, HashiCorp Vault, AWS Secrets Manager) и убедитесь, что они не перезаписываются случайно.

Разворачивайте по стратегии

В Kubernetes, например, при неверной конфигурации стратегии возможны простои. Pods могут быть удалены до того, как новые успеют стартовать, или новые версии вообще не будут работать.

  • В Kubernetes используйте RollingUpdate с настройками maxSurge и maxUnavailable, чтобы новые поды стартовали постепенно, а старые были постоянно доступны.
  • Настройте readinessProbe и livenessProbe, чтобы Kubernetes не направлял трафик на неготовые поды.
  • Ответственно подходите к настройке стратегии и выбору количества реплик.
  • Для Helm-чартов фиксируйте версии (helm dependency update, helm package) и используйте helm upgrade --atomic для автоматического отката при сбое.

Например, в манифесте Deployment можно указать:

			strategy:
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 1
    maxUnavailable: 0
		

Избегайте race conditions

Параллельные процессы в CI/CD (например, одновременная сборка и деплой) могут вызывать состояния гонки.

  • Настройте блокировки (locks) в CI/CD, чтобы не было параллельных деплоев в одно окружение (например, через environments в GitLab CI).
  • Используйте атомарные операции в Helm и Server Side Apply в kubectl.

Обрабатывайте ошибки

Часто может быть такое, что нет нормальной обработки ошибок (логов, статусов). Например, доступ к сервису пропадает, но пайплайн все равно успешно завершается.

  • Регулярно тестируйте пайплайн на staging-окружении, симулируйте реальные сценарии деплоя.
  • Проверяйте доступность сервисов после деплоя с помощью health-check скриптов.

Новую проверку можно, например, добавить так:

curl --fail http://any-app.example.com/health

Нет изоляции переменных окружения и секретов

Представьте: в staging-окружении используются тестовые ключи, а в продакшене — боевые. Но из-за ошибки в CI/CD пайплайне или конфигурации staging берет продовые credentials. Как итог — тестовое удаление данных в песочнице стирает боевую базу. Или еще хуже: токены утекают из-за слабых прав доступа к Secret Manager, и вас могут спокойно взломать. Ниже рассказываем, как это пофиксить.

Разделяйте секреты по окружениям

Если переменные окружения или ключи не разделены между dev, staging и prod, они могут быть случайно использованы в неправильном контексте.

  • Храните секреты в Secret Manager (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, Kubernetes Secrets) с четким разделением по окружениям (например, пути secrets/staging/db, secrets/prod/db).
  • Используйте префиксы или теги для идентификации окружения (например, STAGING_API_KEY, PROD_API_KEY).
  • Настройте права доступа CD так, чтобы пайплайн мог подтягивать только секреты, которые относятся к текущему окружению.

Например, в Vault это настраивается так:

			path "secret/staging/*" {
  capabilities = ["read"]
}
path "secret/prod/*" {
  capabilities = ["deny"]
}
		

Не храните секреты в коде

Иначе утечка неизбежна.

  • Уберите секреты из репозиториев и .env-файлов и используйте Secret Manager.
  • Для Kubernetes используйте Secret-объекты или интеграцию с внешними менеджерами (например, External Secrets Operator).
  • Проверяйте репозитории на утечки с помощью инструментов типа truffleHog или gitleaks.

Вот пример Kubernetes Secret:

			apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
  namespace: staging
type: Opaque
data:
  API_KEY: 
		

Ограничивайте доступ

Это принцип Scoped Permissions — с помощью него можно снизить риски случайного или намеренного использования секретов.

  • Используйте IAM-роли в облаке (например, AWS IAM Roles for Service Accounts) с минимальными правами.
  • Ограничивайте доступ разработчиков к продовым секретам через RBAC или Vault-профили.

Вот AWS IAM-политика для staging:

			{
  "Effect": "Allow",
  "Action": "secretsmanager:GetSecretValue",
  "Resource": "arn:aws:secretsmanager:*:*:secret:staging/*"
}
		

Ротируйте ключи

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

  • Настройте автоматическую ротацию ключей в Secret Manager (например, AWS Secrets Manager поддерживает ротацию через Lambda).
  • После инцидента сразу же ротируйте скомпрометированные ключи и пересоздавайте секреты.
  • Логируйте доступ к секретам для аудита (например, через Vault Audit Logs).

Неправильная настройка health-checks в Kubernetes или других оркестраторах

Неправильная настройка readinessProbe и livenessProbe в Kubernetes — это, можно сказать, классика. Вы обновляете сервис, поды запускаются, но сразу же помечаются как unhealthy. Причина — неправильный readinessProbe или livenessProbe. Например, путь /healthz больше не существует, или проверка уходит в таймаут из-за долгой инициализации. В результате: контейнеры бесконечно рестартуются, сервис недоступен, кластер в панике.

Разделяйте назначение проб

readinessProbe проверяет, готов ли под принимать трафик, а livenessProbe — не завис ли он. Если их смешать, можно ждать сбой, например, трафик пойдет на не до конца инициализированный сервис.

  • Используйте разные endpoints для проб. Например, /health для readinessProbe (готовность сервиса) и /alive для livenessProbe (проверка зависаний).
  • Настройте readinessProbe так, чтобы она возвращала 200 только после полной инициализации (например, подключения к базе).
  • Для livenessProbe проверяйте минимальную работоспособность (например, ответ сервера без проверки внешних зависимостей).

Учитывай время инициализации

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

  • Установите initialDelaySeconds с запасом, чтобы учитывать время прогрева (например, загрузку кэша или подключение к базе).
  • Настройте timeoutSeconds и periodSeconds так, чтобы проба не завершалась слишком быстро, но и не крутилась вечно.
  • Используйте failureThreshold для нескольких попыток перед пометкой пода как unhealthy.

Вот пример для сервиса с долгим стартом:

			readinessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 30
  timeoutSeconds: 5
  periodSeconds: 10
  failureThreshold: 3
		

Добавьте grace period

Он дает сервису время корректно завершиться перед рестартом.

  • Установите terminationGracePeriodSeconds в манифесте Deployment, чтобы под мог завершить запросы перед остановкой.
  • Настройте preStop хук, если нужно выполнить действия перед завершением.

Тестируйте на staging

Проблемы с пробами часто всплывают только в проде, если staging не идентичен.

  • Убедитесь, что staging-окружение повторяет прод по конфигурации и нагрузке.
  • Добавьте автоматические тесты в CI/CD для проверки endpoints (/health, /alive) перед деплоем.
  • Симулируйте реальные сценарии (например, медленный старт или сбой зависимостей) на staging.

В CI/CD можно добавить:

			curl --fail http://staging-app.example.com/health
curl --fail http://staging-app.example.com/alive
		

Неправильная работа с конфигурациями через Helm или Kustomize

Представьте: обновили Helm-чарт, но в values.yaml остались старые переменные, которые ломают новые настройки. Или Kustomize патчит не тот ресурс, и манифесты применяются с ошибками. В итоге: поды падают, сервисы недоступны, и никто не знает что делать. Рассказываем, что с этим делать.

Валидируйте Helm-чарты перед деплоем

Так можно найти ошибки до применения манифестов.

  • Используйте helm template или helm install –dry-run для рендеринга манифестов и их проверки.
  • Включите schema validation для values.yaml с помощью JSON Schema (поддерживается Helm v3.6+).
  • Проверяйте манифесты через kubeval или kubectl apply –dry-run=server для подтверждения соответствия Kubernetes API.

Тестируйте Kustomize-конфигурации

Kustomize может патчить не то, что вы ожидали, если селекторы или структура неправильные.

  • Прогоняйте kustomize build для генерации итоговых манифестов и проверяйте их перед деплоем.
  • Используйте kubectl apply –dry-run=server -k . для валидации в кластере.
  • Проверяйте селекторы патчей в kustomization.yaml на точность (например, name и namespace).

Управляйте версиями и структурой

Несогласованность версий чартов или манифестов приводит к неожиданным изменениям.

  • Фиксируйте версии Helm-чартов в Chart.yaml и используйте точные теги (например, 1.2.3, а не latest).
  • Храните values.yaml отдельно для каждого окружения (values-staging.yaml, values-prod.yaml).
  • Для Kustomize используйте базовые манифесты и патчи, разделённые по окружениям (например, overlays/staging, overlays/prod).

Документируйте и мониторьте

Без документации сложно понять, что изменилось, а без мониторинга — почему упало.

  • Ведите CHANGELOG.md для Helm-чартов и Kustomize патчей, описывая изменения в структуре и значениях.
  • Логируйте команды деплоя (helm upgrade –debug, kubectl apply -k .) для отладки.
  • Настройте мониторинг статуса подов через Prometheus, чтобы сразу видеть сбои из-за ошибок конфигурации.

Вот пример получения подробного лога helm:

			helm upgrade --install my-chart ./chart --values values-prod.yaml --debug --namespace production
		

Нет политики управления версиями артефактов

С этой штукой шутить нельзя. Каждый новый билд заливается с тегом latest, и через неделю никто не помнит, какая именно версия работает в проде. А если что-то сломалось, откатиться просто невозможно: старый образ либо затерт в registry, либо его никто не пометил. На выходе — паника и хаос.

Используйте семантическое версионирование (semver) или уникальные теги

Так банально будет однозначность и отслеживаемость версий.

  • Присваивайте образам теги по схеме semver (1.2.3), commit hash (abc1234) или временной метке (20250429-1345).
  • Избегайте latest в продакшене — это бомба замедленного действия.
  • В CI/CD автоматически генерируйте теги на основе версии приложения или Git commit.

Вот пример тег-образа:

docker build -t my-app:1.2.3 -t my-app:$(git rev-parse –short HEAD)

Фиксируйте версии в манифестах и пайплайнах

Immutable теги гарантируют, что деплой всегда использует ожидаемую версию.

  • В Kubernetes манифестах указывайте точные теги вместо latest.
  • Настройте CI/CD так, чтобы тег образа передавался в Helm или Kustomize как параметр.
  • Используйте инструменты вроде helm upgrade с фиксированными версиями чартов.

Настройте retention policy для артефактов

Хранение старых образов позволяет откатиться к стабильной версии.

  • В container registry (Docker Hub, AWS ECR, Harbor) настройте правила хранения, чтобы сохранять последние N версий или образы за последние X дней.
  • Регулярно очищайте устаревшие артефакты, но сохраняйте критические версии (например, те, что в проде).
  • Используйте теги для маркировки стабильных версий (например, prod-1.2.3).

Пример — AWS ECR lifecycle policу:

			{
  "rules": [
    {
      "rulePriority": 1,
      "description": "Keep last 10 images",
      "selection": {
        "tagStatus": "any",
        "countType": "imageCountMoreThan",
        "countNumber": 10
      },
      "action": {
        "type": "expire"
      }
    }
  ]
}
		

Автоматизируйте версионирование в CI/CD

  • В CI/CD пайплайне генерируйте теги на основе Git тегов, commit hash или переменных окружения.
  • Проверяйте, что образ с нужным тегом пушится в registry и используется в деплое.
  • Добавьте шаг валидации манифестов, чтобы убедиться, что теги фиксированы.
Ошибки при деплое могут вылиться в серьезные проблемы для проекта. DevOps-инженеры не просто запускают пайплайны, а следят за жизненным циклом продукта — от инфраструктуры до мониторинга. Документируйте ошибки, создавайте чек-листы, автоматизируйте каждый шаг и учитесь на инцидентах. И главное — никогда не деплойте в пятницу вечером.
Следите за новыми постами
Следите за новыми постами по любимым темам
969 открытий8К показов