GitOps на отечественных рельсах: Argo CD с GitFlic Registry без GitHub
Переносим GitOps-пайплайн Argo CD на GitFlic Registry в изолированном контуре: настраиваем image updater и webhook-интеграцию без привязки к внешним сервисам.
GitFlic и Сфера Репозиторий наращивают функциональность CI/CD для изолированных контуров в 2025
GitFlic в этом году добавил container registry как полноценную составляющую платформы, а не просто прикрученный сбоку сервис. Сфера Репозиторий движется в похожем направлении - оба продукта наращивают CI/CD-функциональность для контуров без выхода в интернет. У нас как раз был повод проверить это в деле: клиент с кластером Kubernetes в изолированном сегменте захотел построить нормальный GitOps-пайплайн через Argo CD, не завязанный на GitHub или Docker Hub.
Задача звучала просто: сборка образа в GitFlic CI, пуш в GitFlic Registry, автоматическое обновление манифестов Argo CD и деплой в кластер. Без единого обращения во внешний интернет. На практике - несколько неожиданностей, о которых ниже.
Как вообще устроен image updater в Argo CD
Argo CD Image Updater - отдельный контроллер, который следит за новыми тегами образов в реестре и автоматически обновляет манифесты в Git (или прямо в кластере, если работать без Git-write-back). Классическая схема: пайплайн собрал и запушил новый образ, image updater это заметил, обновил values.yaml или аннотацию в ArgoCD Application, Argo CD синхронизировал кластер.
Штука рабочая, когда реестр - Docker Hub или GHCR. С отечественными реестрами надо чуть больше поковыряться.
Настройка GitFlic Registry как источника образов
GitFlic Registry поддерживает Docker Registry HTTP API v2 - это хорошая новость, потому что image updater работает именно с этим протоколом. Достаточно добавить реестр в конфигурацию контроллера:
registries:
- name: gitflic-registry
prefix: registry.gitflic.space
api_url: https://registry.gitflic.space
credentials: pullsecret:argocd/gitflic-registry-creds
defaultns: your-org
insecure: false
Credentials - это обычный Kubernetes Secret с .dockerconfigjson. GitFlic использует стандартные токены доступа (deploy tokens или personal access tokens), механика та же что у GitLab.
Первый сюрприз: image updater по умолчанию использует latest-стратегию или semver. Если тег формируется по схеме branch-commitsha (а GitFlic CI так делает из коробки), нужно прописать явную стратегию в аннотациях Application:
annotations:
argocd-image-updater.argoproj.io/image-list: app=registry.gitflic.space/your-org/your-app
argocd-image-updater.argoproj.io/app.update-strategy: newest-build
argocd-image-updater.argoproj.io/app.tag-match: ^main-[a-f0-9]{8}$
newest-build смотрит на дату создания тега, tag-match фильтрует по регулярке. Без фильтра image updater может подхватить тег из другой ветки.
Webhook вместо polling
По умолчанию image updater ходит в реестр каждые 2 минуты и проверяет новые теги. Для изолированного контура это нормально, но задержка в 2 минуты может раздражать. GitFlic Registry поддерживает webhook при пуше образа - можно сделать почти мгновенное обновление.
Webhook в GitFlic настраивается через настройки репозитория (не организации), что немного неочевидно. Endpoint у image updater стандартный: /api/v1/webhook. Нужен соответствующий Ingress или Service типа LoadBalancer - в изолированном контуре обычно достаточно ClusterIP с проксированием через ingress внутри кластера.
# argocd-image-updater-config ConfigMap
data:
webhook.enable: "true"
# argocd-image-updater-secret Secret
stringData:
webhook.gitflic-secret: "<random-token>"
Webhook-секрет генерируем случайно, прописываем и в GitFlic, и в секрет. Проверка подписи работает стандартно через HMAC-SHA256.
Второй сюрприз: GitFlic отправляет webhook-payload в формате, близком к GitLab, но не идентичном ему. Image updater умеет парсить Docker Hub и GHCR webhook-форматы, а для GitFlic пришлось посмотреть в логи и убедиться, что payload всё-таки разбирается корректно. В нашем случае разобрался - image updater увидел repository.full_name и правильно сопоставил с конфигом. Но без проверки логов мы бы не были уверены.
Write-back: обновление манифестов в GitFlic
Image updater умеет писать изменения обратно в Git (write-back mode). Это означает, что при появлении нового тега он создаёт коммит в репозитории манифестов с обновлённым тегом образа. Argo CD затем видит коммит и синхронизирует.
Для write-back нужен SSH-ключ или токен с правом на push в репозиторий манифестов в GitFlic. Мы использовали deploy token с правом write_repository:
apiVersion: v1
kind: Secret
metadata:
name: argocd-image-updater-gitcreds
namespace: argocd
stringData:
username: "image-updater-bot"
password: "<gitflic-deploy-token>"
Аннотация в Application:
argocd-image-updater.argoproj.io/write-back-method: git:secret:argocd/argocd-image-updater-gitcreds
argocd-image-updater.argoproj.io/git-branch: main
Write-back работает через .argocd-source-<appname>.yaml - image updater создаёт или обновляет этот файл рядом с основным Application-манифестом. Argo CD подхватывает его автоматически. Подход немного магический с первого взгляда, но логичный: все изменения трекаются в Git, история образов не теряется.
Что в итоге получилось
Схема полностью работает в изолированном контуре:
- GitFlic CI собирает образ и пушит в GitFlic Registry с тегом
main-{sha8} - Webhook уведомляет image updater в течение нескольких секунд
- Image updater обновляет манифест в репозитории GitFlic и делает коммит
- Argo CD видит новый коммит, синхронизирует кластер
Полный цикл от пуша кода до обновления в кластере - около 2-3 минут, из которых большую часть занимает сама сборка. Это нормально.
Что не заработало сразу: image updater иногда теряет связь с webhook-эндпоинтом при рестарте пода и не переподписывается автоматически. Пришлось добавить liveness-проверку с принудительным рестартом, если webhook-соединение не восстанавливается за 5 минут. Это похоже на известный issue в upstream, который ещё не закрыт.
Сфера Репозиторий мы в этом проекте не трогали - клиент уже сидит на GitFlic и менять реестр смысла нет. Но по документации Сферы webhook-интеграция устроена похоже, и проблем с Docker Registry v2 совместимостью там тоже не должно быть.
Весь этот пайплайн живёт в рамках managed-сопровождения инфраструктуры - там же разбираемся с обновлением самого Argo CD и image updater между версиями, что тоже иногда требует внимания при смене API аннотаций.