GitOps с Argo CD: практический проект для портфолио

Не очередная установка Argo CD ради скриншота интерфейса. Собираем нормальный цикл: CI публикует образ, Git хранит желаемое состояние, Argo CD сравнивает его с кластером, синхронизирует и показывает дрейф.

Автор — Дмитрий Тыльный · опыт Senior DevOps · 7 сентября 2026 · 9 мин

Коротко. GitOps — модель, в которой Git хранит декларативное желаемое состояние, а контроллер внутри кластера приводит реальность к этому состоянию. CI не должен ходить в Kubernetes с вечным admin-токеном: он собирает образ и меняет версию в репозитории конфигурации. Argo CD видит commit, показывает diff и синхронизирует приложение.

Зачем GitOps, если уже есть CI/CD

Обычный pipeline часто заканчивается командой kubectl apply. После неё история деплоя размазана между логами CI, кластером и ручными изменениями. GitOps возвращает одну точку правды: что лежит в main конфигурационного репозитория, то должно работать в кластере. Любое отличие видно как OutOfSync.

Это не магия безопасности. Если дать Argo CD cluster-admin, включить автоматическое удаление и принимать любой pull request без ревью, получится очень быстрый способ разнести кластер. Модель сильна разделением ответственности: CI отвечает за проверенный артефакт, Git — за историю желаемого состояния, контроллер — за применение.

Структура учебного проекта

app-repo/ → src, Dockerfile, CI
config-repo/ → base, overlays/dev, argocd/Application

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

Application как контракт

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata: {name: demo, namespace: argocd}
spec:
  source: {repoURL: https://github.com/example/config.git, targetRevision: main, path: apps/demo/dev}
  destination: {server: https://kubernetes.default.svc, namespace: demo}
  syncPolicy:
    automated: {enabled: true, selfHeal: true, prune: false}
    syncOptions: [CreateNamespace=true]

selfHeal возвращает ресурс к состоянию из Git после ручного изменения. prune удаляет ресурсы, исчезнувшие из репозитория; для первого проекта оставьте его выключенным, проверьте поведение вручную и только потом решайте, нужен ли автоматический prune. allowEmpty без понимания вообще не включайте.

Цепочка изменения

  1. Разработчик делает commit в app-repo.
  2. CI запускает тесты, собирает image и публикует immutable tag, лучше связанный с commit SHA.
  3. Отдельный шаг или бот обновляет tag в config-repo и создаёт pull request.
  4. После ревью commit попадает в main.
  5. Argo CD видит расхождение и применяет manifests.
  6. Readiness показывает техническое здоровье, а метрики — реальный результат выкладки.

Не используйте latest: Git тогда перестаёт хранить точную версию. Откат становится гаданием, а один и тот же commit описывает разные образы.

Откат и важная ловушка

В GitOps правильный откат — новый commit, который возвращает предыдущий image tag или конфигурацию. История остаётся линейной и объяснимой. Кнопка rollback в интерфейсе может временно вернуть ресурс, но при включённой автоматической синхронизации Git снова победит. Поэтому источник правды откатывают в источнике правды.

Проверьте сценарий руками: задеплойте v1, поменяйте на v2, убедитесь в синхронизации, внесите ручной drift через kubectl и посмотрите self-heal, затем верните v1 отдельным revert commit. Снимки интерфейса ничего не доказывают; история commits и наблюдаемое поведение — доказывают.

Доступы и секреты

  • ограничьте Argo CD AppProject разрешёнными репозиториями, namespace и типами ресурсов;
  • не храните секреты открытым YAML в Git;
  • разведите доступ на чтение репозитория и управление кластером;
  • закройте интерфейс SSO/RBAC, а не общим паролем;
  • включите ревью для production overlay;
  • не давайте pipeline прямой cluster-admin, если деплой делает контроллер.

Что положить в портфолио

README должен показывать схему потока, структуру двух репозиториев, команды запуска, сценарий drift/self-heal, способ отката и границы безопасности. Добавьте скрин истории синхронизации, но не делайте его единственным доказательством. Сильный рассказ: «убрал прямой доступ CI к кластеру, сделал image по SHA, конфигурацию провожу через PR, drift виден и исправляется, rollback — revert commit».

Перед этим нужны основы Kubernetes и рабочий CI. После — попробуйте превратить проект в golden path из статьи про Platform Engineering.

Частые вопросы

GitOps — это только Argo CD?
Нет. Argo CD — популярная реализация модели, но важны декларативное состояние в Git, pull-механизм и сверка реальности с желаемым состоянием.

Нужны два репозитория?
Не всегда. Для учебного проекта допустим один, но разделение показывает разные циклы и права приложения и конфигурации.

Включать auto-sync сразу?
В dev — можно после ручной проверки. Для production сначала определите ревью, health checks и способ остановить неудачную раскатку.

GitOps надо сломать руками

Создайте drift, верните состояние и откатите версию — только тогда проект становится опытом.

Повторить Kubernetes