Миграция базы перед приложением в Argo CD: hooks и sync waves

Новая версия API читает столбец external_id, которого ещё нет в PostgreSQL. Если одновременно обновить Deployment и запустить миграцию, часть новых Pod успеет получить запрос раньше изменения схемы. Argo CD позволяет поставить миграцию перед основной синхронизацией. Но последовательность запуска нужна вместе с правилами повторного выполнения и совместимости: во время миграции старая версия приложения продолжает работать.

Сначала проектируем изменение схемы

Для такого релиза обычно удобен расширяющий шаг: добавить nullable-столбец, обновить приложение с поддержкой старых и новых строк, заполнить данные, а обязательность и удаление старых полей вынести в отдельный этап. Если первая миграция удаляет столбец, необходимый текущим Pod, правильный порядок Argo CD всё равно оставит работающую версию без нужной схемы. Откат Deployment тоже не восстановит удалённые данные.

Миграционный инструмент должен хранить версии применённых изменений и координировать параллельные запуски. GitOps-контроллер может повторить операцию, а несколько приложений способны обращаться к одной базе. Идемпотентность одной SQL-команды и блокировка всего процесса миграции решают разные задачи. Здесь используем заранее подготовленный образ приложения, в котором есть команда /app/migrate up: её контракт нужно реализовать вашим инструментом.

PreSync останавливает релиз при неуспешной миграции

Следующий Job входит в то же Application, что и Deployment. PostgreSQL и Secret app-db с ключом url уже должны существовать. Адрес образа — заполнитель для миграционного образа конкретного релиза; копировать его без замены нельзя.

apiVersion: batch/v1
kind: Job
metadata:
  name: api-schema-migrate
  namespace: demo
  annotations:
    argocd.argoproj.io/hook: PreSync
    argocd.argoproj.io/sync-wave: "-1"
    argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
spec:
  backoffLimit: 0
  activeDeadlineSeconds: 300
  template:
    spec:
      restartPolicy: Never
      containers:
        - name: migrate
          image: registry.example.com/team/api:2026-10-29
          command: ["/app/migrate", "up"]
          env:
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: app-db
                  key: url

Аннотация hook: PreSync помещает Job в фазу до применения обычных ресурсов. Неуспех этой фазы останавливает синхронизацию. Job должен действительно завершаться ненулевым кодом при ошибке: подавленный exit code превращает сломанную миграцию в разрешение продолжать релиз. backoffLimit: 0 не позволяет Job автоматически создавать повторные попытки после неуспеха; повторный запуск операции остаётся отдельным решением. Deadline ограничивает длительность работы Job, но тайм-аут не означает автоматический откат уже выполненного SQL.

Waves уточняют порядок внутри фазы

Argo CD сначала учитывает фазу, затем номер волны, затем остальные правила сортировки. Отрицательная wave позволяет расположить один PreSync раньше другого. Обычный Deployment без аннотаций относится к Sync и wave 0. Даже wave -10 у обычного ресурса не помещает его перед фазой PreSync. Поэтому новый Secret, добавленный как обычный ресурс в том же релизе, не станет автоматически доступен миграционному Job.

В примере доступ к базе подготовлен заранее. Для первого развёртывания окружения продумайте отдельный этап создания инфраструктуры или осознанный порядок ресурсов одной фазы. Двухсекундная задержка между waves, используемая Argo CD по умолчанию, даёт контроллерам время обработать изменения, но не заменяет проверку готовности PostgreSQL. Условия здоровья ресурсов и завершение Job всё равно должны соответствовать реальной задаче.

Повторный Sync и сохранение диагностики

У Job постоянное имя, а BeforeHookCreation удаляет предыдущий hook перед новым созданием. Это обеспечивает повторный запуск при новой операции Sync. Политика не откатывает миграцию и не очищает её историю в базе. Успешный Job оставлен для просмотра до следующего запуска; журналы, нужные для расследования, стоит отправлять в централизованное хранилище до пересоздания.

argocd app get demo-api --refresh
kubectl -n demo get job api-schema-migrate
kubectl -n demo logs job/api-schema-migrate
kubectl -n demo describe job api-schema-migrate

Если миграция упала, сравните версию схемы в базе и список выполненных шагов, затем исправьте причину. Не запускайте бесконечный повтор той же команды при частично применённом DDL. Для PostgreSQL многие изменения поддерживают транзакции, но конкретные операции и блокировки нужно проверить заранее на копии базы подходящего размера. На время релиза полезно заранее определить, кто принимает решение продолжать или восстанавливать данные.

Релиз проверяем целиком

Selective sync отдельных ресурсов не выполняет hooks. Поэтому обновление только Deployment через выборочный Sync обходит показанный барьер миграции. Процедура релиза должна требовать полную синхронизацию Application для такого изменения. Аналогично успешная миграция ещё не означает работоспособность API: после Sync проверяются готовность Pod и запрос, использующий новое поле.

Отдельно решите, какие права получает миграционный Job. Приложению может быть достаточно читать и изменять строки, тогда как изменение схемы требует более широких полномочий. Раздельные учётные записи позволяют не оставлять DDL-права обычному API после релиза. Secret с миграционным подключением в таком случае должен быть подготовлен до PreSync, а доступ к журналам — настроен так, чтобы строка подключения в них не попадала.

Для контроля завершения миграционная команда должна дождаться окончания работы, а не отправить её в фон и завершиться успешно. Проверяйте фактическую версию схемы после Job. Иначе Argo CD увидит успешный контейнер и продолжит релиз, пока база всё ещё меняется.

Сохраните для релиза три результата: версию миграции, завершение Job и проверку нового поведения приложения. При этом старое приложение должно оставаться совместимым со схемой в течение перехода. Совместимость данных остаётся частью проектирования самого релиза.

Ещё по теме

Продолжить изучение

Хотите выстроить доставку изменений из Git в кластер? Синхронизация, окружения и восстановление после неудачного релиза — темы программы «Argo CD и GitOps: деплой в Kubernetes».

Продолжить на практике

  • Argo CD и GitOps: деплой в Kubernetes ↗

    Превратите Git в источник правды для Kubernetes. Настройте Argo CD, управляемую синхронизацию и окружения, научитесь находить drift и откатывать изменения через Git. Итог — воспроизводимый GitOps-процесс для приложения.