lenec ru

← все посты

ArgoCD vs Flux: миграция с одного на другой и где грабли

10K

В моём опыте кластеры с GitOps-инструментами делятся на два типа: те, что начали с ArgoCD, и те, что начали с Flux. И раз в пару лет в команду приходит человек с предыдущим опытом и предлагает мигрировать в другую сторону. Дважды я через это проходил, в обе стороны. Расскажу, чем они реально отличаются в 2026, как мигрировать без даунтайма и где обычно болит.

Версии — ArgoCD 2.13, Flux v2 (2.4). k8s 1.30.

Что общего

Оба — pull-based GitOps. Декларация в Git → контроллер в кластере следит за репо → применяет изменения. Оба умеют Helm, Kustomize, plain YAML. Оба ставят CRD и ходят к API-серверу.

Базовая модель identical. Различия — в архитектуре, UI и том, как они делают «синхронизацию».

ArgoCD: централизованный, с UI

Архитектура

Один контроллер на кластер, который мониторит N репозиториев. Все Application-объекты — в namespace argocd (или другом, но обычно одном). Есть отдельный Web UI с авторизацией через OIDC, RBAC, поиском по приложениям.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: api
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/manifests
    targetRevision: main
    path: apps/api/prod
  destination:
    server: https://kubernetes.default.svc
    namespace: prod
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Что хорошо

  • UI. Реально полезный. Видно дерево ресурсов, diff между Git и кластером, sync history, логи синков. Нормальные люди (не только DevOps) могут смотреть статус деплоя.
  • ApplicationSet — генератор приложений из шаблонов. Удобно, когда у тебя 50 микросервисов с одинаковой структурой.
  • Sync waves — порядок применения ресурсов. Сначала CRDs, потом RBAC, потом Deployments. Через annotations.
  • Multi-cluster из коробки. Один ArgoCD рулит десятком кластеров, через его API регистрируешь новые.

Что плохо

  • Монолит. Application-controller и repo-server — heavy-комоненты, на больших инсталляциях (1000+ Applications) приходится тюнить шарды и memory limits.
  • Один namespace для всех Applications. С RBAC можно разнести, но это дополнительный конфиг.
  • UI может пропадать (perception bug), пока всё на самом деле синхронизируется. Народ начинает паниковать раньше времени.

Flux: модульный, без UI

Архитектура

Не один контроллер, а несколько: source-controller (тянет Git), kustomize-controller, helm-controller, notification-controller. Каждый занимается своим.

apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: manifests
  namespace: flux-system
spec:
  url: https://github.com/myorg/manifests
  ref:
    branch: main
  interval: 1m
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: api
  namespace: flux-system
spec:
  interval: 5m
  path: ./apps/api/prod
  prune: true
  sourceRef:
    kind: GitRepository
    name: manifests
  targetNamespace: prod

Что хорошо

  • Cloud-native архитектура. Каждый контроллер scaling-ится отдельно, restart одного не валит остальные.
  • CRD-first. Никакого собственного API за CRD-объектами, всё через kubectl.
  • Multi-tenancy через namespace-isolation работает естественно: команда A держит свои Kustomization в своём namespace, контроллер за это пускает с её ServiceAccount.
  • Notifications через свой controller — Slack, Teams, GitHub status. ArgoCD это тоже умеет, но у Flux нативнее.

Что плохо

  • Нет UI. Есть Weave GitOps (бывший wego) и сторонние проекты, но это не родное. flux get all -A в терминале — основной способ смотреть статус.
  • Нет дерева ресурсов «что получилось из Application». Нужно kubectl get по namespace и руками сопоставлять.
  • Sync waves — менее зрелые, чем в ArgoCD. Через dependsOn между Kustomization, но менее гранулярно.
  • ImageUpdateAutomation — отдельный controller, и он делает PR в Git автоматически. Удобно, но настройка не тривиальна.

Когда что выбирать в новом кластере

Беру ArgoCD, если:

  • Команда не только DevOps. Девелоперам и QA нужно смотреть статус деплоя, и UI критичен.
  • Multi-cluster из одной точки управления.
  • Нужен ApplicationSet для генерации.
  • Команда более классическая ops-ориентированная, привыкла к admin-консолям.

Беру Flux, если:

  • Cloud-native команда, всё через kubectl и YAML.
  • Многотенантность важна с самого начала.
  • Не хочется поддерживать ещё один stateful-сервис с UI.
  • Делаем «всё через Git» строго — даже статус деплоя смотрят через Git PRs/issues, а не дашборд.

Миграция с одного на другой

Самая болезненная часть. Делал в обе стороны. Главное — миграция без даунтайма приложений. Сами приложения не должны заметить.

Шаг 1: Inventory

Собираешь список всех управляемых объектов. В ArgoCD:

argocd app list -o name > apps.txt
argocd app get <app> -o yaml > backup/<app>.yaml

В Flux:

flux get kustomizations -A > ks.txt
kubectl get kustomizations -A -o yaml > backup/all-ks.yaml

Это база, на которую ты потом сверяешься.

Шаг 2: Поднимаешь target-инструмент в read-only

Ставишь второй инструмент рядом, но без auto-sync. Например, мигрируем с Flux на ArgoCD: ставишь ArgoCD, создаёшь Applications с syncPolicy: manual. Они появятся в UI как OutOfSync, но ничего не делают.

spec:
  syncPolicy:
    syncOptions:
      - ApplyOutOfSyncOnly=true
      - PruneLast=true
    # без automated блока — ручной sync

В этот момент к одним и тем же ресурсам в кластере имеют отношение оба контроллера, но реально применяет только Flux.

Шаг 3: По одному приложению переключаешь

Берёшь некритичное приложение (тестовый сервис, dev-окружение). В Flux:

flux suspend kustomization test-app -n flux-system

В ArgoCD:

argocd app sync test-app
argocd app set test-app --auto-prune --self-heal

Проверяешь, что pod-ы на месте, ничего не дрогнуло. Если всё ок — переходишь к следующему.

Потом удаляешь Flux-объект, чтобы он его не «возрождал»:

kubectl delete kustomization test-app -n flux-system

Тут есть нюанс: Flux может triggernuть prune при удалении Kustomization. Чтобы этого не было, перед удалением:

spec:
  prune: false   # сначала меняешь это

Применяешь, потом удаляешь Kustomization. Тогда удаление CR не дёрнет prune ресурсов.

Шаг 4: Переключаешь критичные сервисы

Когда тренировался на тестах — переходишь к prod. Я всегда делаю это в часы низкой нагрузки и с включённым алёртингом.

Самое страшное — двойное управление: Flux откатывает то, что ArgoCD только что применил. Гарантия избежать — пошагово (suspend в одном → sync в другом → delete в первом), не пытаться двигать «батчем».

Шаг 5: Cleanup

После последнего приложения сносишь старый контроллер целиком:

flux uninstall --namespace=flux-system

Бэкап CRDs в стороне на случай отката. После недели работы можно удалять.

Грабли, на которые я наступал

  • Helm-релизы с разными именами. Flux HelmRelease создаёт Helm release с именем CR, ArgoCD — с именем Application. При переходе Helm release в кластере именуется иначе, и команды helm list показывают «два релиза». Лечится тем, что не миксуй: либо все через Helm-операторы (тогда совместимо), либо все через template-and-apply.
  • Sealed Secrets. Если у тебя их провизионирует Flux, и SealedSecret-controller сам, и ArgoCD начинает «видеть» их как drift — будут вопросы. Лечится argocd.argoproj.io/compare-options: IgnoreExtraneous и игнор-листами.
  • Webhooks. Если в Git был настроен webhook на Flux notification — забыл его перенаправить, потерял время на «почему мои PR-чеки не работают».

Что запомнить

ArgoCD — для команд, которым нужен UI и multi-cluster из одного места. Flux — для cloud-native подхода с CRD-first и multi-tenancy. Миграция возможна без даунтайма, но требует пошаговости: target в read-only, по одному приложению переключаешь, потом cleanup.

Куда копать: документация ArgoCD и Flux. И обязательно посмотри ApplicationSet (ArgoCD) и Flux ImageUpdateAutomation — это те фичи, ради которых иногда и переезжают.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.