Стратегии деплоя: как мы пришли к использованию Argo CD
Обсудим переход от ручного процесса к автоматизации и сравним две модели деплоя: push и pull.

Привет! Меня зовут Егор Салиев, я DevOps-инженер в провайдере IT-решений Hilbert Team. Сегодня хочу затронуть тему, которая будет интересна инженерам, занимающимся настройкой CI/CD и деплоем. Рассмотрим, как со временем менялась практика развертывания приложений в Kubernetes.
В результате мы дойдем до современного подхода — GitOps с Argo CD. Такой метод помогает компаниям стандартизировать процессы, уменьшить количество ошибок и сбоев, ускорить вывод продукта на рынок, а также сократить расходы на инфраструктуру.

Итак, у нас есть Gitlab, но пока нет GitOps. Это означает, что хотя мы используем Git для управления версиями кода, у нас еще не внедрена система, в которой все изменения в конфигурации инфраструктурой осуществляются через коммиты в репозиторий. Кроме того, потребуется продумать и настроить конвейер CI/CD, который возьмет на себя автоматизацию процессов сборки, тестирования и развертывания.
Доставка приложения в Kubernetes (K8s) — и есть наша текущая основная задача. Существует несколько различных стратегий деплоя в K8s, каждая из которых имеет свои преимущества, недостатки, а также набор используемых инструментов.
Статья создана по мотивам доклада на Selectel Kuber Meetup.
GitLab и Push‑модель
В push‑модели сборка, тестирование и развертывание приложения в кластер происходит после каждого выполнения команды git push
. То есть разработчик, отправляя свой код в репозиторий, запускает цепочку действий, в результате которой обновленное приложение становится доступным для пользователей. Для этого GitLab предлагает несколько встроенных инструментов.
Когда разработчик вносит изменения в своей ветке кода или создает Merge Request (MR) в основной (main), это действие активирует триггер. Запускается заранее определенный пайплайн — последовательность автоматизированных процессов, которые обеспечивают сборку, тестирование и развертывание нового кода.
При этом выполняются различные build-процессы, которые обычно создают образы с помощью Docker или Kaniko. Может контролироваться как корректность работы нового кода, так и его совместимость с существующей системой.
После успешного прохождения всех этапов, новый образ приложения отправляется в реестр, который служит хранилищем для готовых к развертыванию артефактов. Деплой — заключительный этап, который представляет собой процесс размещения нового образа приложения на целевом окружении, таком как production, staging или development.
Рассмотрим некоторые из существующих инструментов деплоя:
- Kubectl — утилита командной строки для взаимодействия с кластером;
- Kustomize — средство для настройки оркестратора и управления его ресурсами;
- Helm — менеджер пакетов для Kubernetes, который позволяет упаковывать, доставлять и обновлять приложения;
- Helmfile — файл конфигурации, который определяет зависимости, параметры и команды для установки приложений в кластер.
Kubectl
Kubectl — это стандартный и основной инструмент для развертывания приложений в Kubernetes. Кроме того, с его помощью можно выполнять разнообразные операции, такие как масштабирование, обновление, мониторинг и отладка. Для этого необходимо подготовить набор манифестов, которые описывают желаемое состояние приложения в кластере и стандартные сущности K8s: Deployment, Pod, Service, Ingress, ConfigMap, Secret и другие.
Deployment отвечает за развертывание и управление репликами. Pod представляет собой экземпляр запущенного приложения, Service обеспечивает сетевой доступ, Ingress управляет внешним трафиком, ConfigMap и Secret хранят конфигурацию и секретные данные.
Ниже пример, где в корневом каталоге проекта создается файл .gitlab-ci.yml
, который определяет этапы пайплайна CI/CD. В нем описываются задания, которые необходимо выполнить — например, сборка образа Docker, тестирование и развертывание в Kubernetes:
.gitlab-ci.ymldeploy-kubectl: stage: deploy image: dtzar/helm-kubectl:3.15 before_script: - kubectl config use-context $GITLAB_AGENT script: - kubectl apply -f test-app/ rules: - if: $CI_COMMIT_BRANCH when: manual
Команда kubectl apply
применяет манифесты к кластеру — все сущности в нем приводятся к состоянию в соответствии с манифестами.
Преимущества
- универсальность — можно выполнять все основные операции с ресурсами Kubernetes: читать, писать, создавать, удалять, патчить;
- гибкость — благодаря своей универсальности kubectl можно использовать для сложных скриптов и пайплайнов, включая blue-green и Canary.
Недостатки
- нужно знать множество параметров выполнения команды и понимать, как создавать манифесты;
- необходимо вручную указывать все значения для выполнения команды в каждой операции, а также самостоятельно создавать все необходимые ресурсы;
- одна ошибка приводит к сбою всего процесса.
Kustomize
Kustomize — инструмент управления конфигурациями Kubernetes, который позволяет кастомизировать YAML-манифесты без необходимости использования шаблонов. Он работает, применяя набор патчей и трансформаций к базовому набору конфигураций, которые затем применяются с помощью kubectl.
Основные концепции Kustomize
- База (base) — директория, содержащая основные YAML-манифесты Kubernetes.
- Наложение (overlay) — директория с патчами и трансформациями, которые применяются к base.
- Файл
kustomization.yaml
— описывает конфигурацию Kustomize и хранит информацию о базе, наложениях, патчах. трансформациях и ресурсах. - Патчи (patches) — YAML-файлы, которые описывают слияние.
- Трансформации (transformations) — изменения, применяемые ко всем ресурсам в базе.
В примере ниже есть папка base, где хранятся базовые конфигурации для всех сред, и папки overlays, которые содержат специфические настройки для dev, staging, prod и других сред:
.gitlab-ci.ymldeploy-kustomize: stage: deploy image: dtzar/helm-kubectl:3.15 before_script: - kubectl config use-context $GITLAB_AGENT - cd deploy/base - kustomize edit set namespace $CI_ENVIRONMENT_NAME-test-app - kustomize edit set image test-app=$CI_REGISTRY_IMAGE/test-app:$CI_COMMIT_SHORT_SHA - kustomize build ../overlays/$CI_ENVIRONMENT_NAME > $CI_PROJECT_DIR/kustomized.yaml script: - kubectl create ns $CI_ENVIRONMENT_NAME-test-app || true - kubectl apply -f $CI_PROJECT_DIR/kustomized.yaml rules: - if: $CI_COMMIT_BRANCH when: manual
Для работы с ресурсами в Kustomize используется файл kustomization.yaml
, в котором указывается, что именно должно быть изменено и каким образом.
Преимущества Kustomize
- Наследование и переопределение позволяют повторно использовать созданные конфигурации, настраивая их для разных сред — development, staging, production — путем наложения патчей и трансформаций.
- Широкие возможности для настройки ресурсов, что позволяет адаптировать развертывание под конкретные требования проекта.
- Простой и понятный синтаксис.
- Конфигурации описываются в декларативном стиле, что делает их более читаемыми.
Однако у этого инструмента есть и недостатки: требуется время, чтобы исследовать его особенности и научиться эффективно использовать.
Helm
Helm — это менеджер пакетов для Kubernetes. Он использует концепцию чартов (charts), содержащих все необходимые ресурсы для развертывания приложения, такие как Deployment, Service, ConfigMap и другие. Helm использует шаблоны на языке Go для генерации манифестов Kubernetes на основе значений, предоставляемых пользователем. Чарты в Helm могут быть с вложенными сабчартами и храниться в любом реестре.
Деплой приложения в K8s с применением Helm-чарта выглядит действительно просто. При выполнении команды helm install
Helm берет на себя создание всех необходимых ресурсов Kubernetes, таких как Deployment, Service и ConfigMap.
Код в примере ниже описывает задачу для развертывания Helm-чарта:
.gitlab-ci.ymldeploy-helm: stage: deploy image: dtzar/helm-kubectl:3.15 before_script: - kubectl config use-context $GITLAB_AGENT script: - helm upgrade --install test-app ./chart -f values.yaml -n test-app --create-namespace rules: - if: $CI_COMMIT_BRANCH when: manual
В итоге при коммите приложение test-app развернется и обновится, используя чарт из директории ./chart
и файл значений values.yaml
.
Преимущества
- Упрощенное развертывание и установка без необходимости вручную создавать и применять множество манифестов.
- Возможность версионирования и отката.
- Повторное использование чартов и перенастройка их для различных сред.
- Управление зависимостями между чартами, что упрощает развертывание многокомпонентных приложений.
- Большое сообщество и множество готовых чартов для популярных приложений.
Недостатки
- Сложность создания чартов, особенно для начинающих пользователей — требуется знание шаблонов Go и структуры Kubernetes.
- Неправильно настроенные чарты могут представлять угрозу безопасности.
- Хранение секретов в чартах рисковано — лучше использовать Kubernetes Secrets или специальные внешние хранилища.
Helmfile
Helmfile — дополнительный уровень абстракции над Helm для декларативного описания чартов. Его в чем‑то можно сравнить с Docker Compose. С помощью Helmfile можно легко управлять несколькими чартами и их зависимостями.
В примере ниже задача синхронизирует релизы Helm, определенные в helmfile.yaml
:
.gitlab-ci.ymldeploy-helmfile: stage: deploy image: $CI_REGISTRY/tools/helmfile before_script: - kubectl config use-context $GITLAB_AGENT script: - helmfile --namespace $ENVIRONMENT_NAMESPACE sync rules: - if: $CI_COMMIT_BRANCH when: manual
Преимущества
- Упрощение управления несколькими Helm-чартами и их зависимостями.
- Декларативный подход — описание желаемого состояния системы в виде кода.
- Поддержка шаблонизации, что позволяет использовать переменные и условные конструкции для настройки конфигурации чартов в зависимости от окружения или других факторов.
Сравнение
Ниже сравнительная таблица по всем описанным инструментам:
Pull-модель, GitOps и Argo CD.
Предпосылки к использованию нового подхода
Когда мы разворачиваем приложения в Kubernetes, используя push-модель, то конфигурация ресурсов хранится в etcd — встроенной в K8s базе данных. Такой подход имеет свои нюансы — возникает проблема конфигурационного дрейфа (configuration drifting):
- Kubernetes постоянно сравнивает желаемое состояние, которое содержится в etcd, с текущим состоянием кластера и вносит необходимые изменения, что обеспечивает самовосстановление и масштабируемость.
- Если кто-то вручную модифицирует ресурс в кластере, то это может привести к неожиданным последствиям: Kubernetes будет поддерживать новое состояние, даже если оно не соответствует желаемой конфигурации.
- Удаление ресурса из кластера приведет к его потере, а для восстановления потребуется повторное развертывание.
Решить эту проблему можно с помощью GitOps и Argo CD.
Чаще всего под GitOps понимают именно Pull‑модель взаимодействия с Git. Так же, как и в Push‑модели, информация о кластере расположена в Git-репозитории. Отличие в том, что внесение изменений в кластер происходит не по срабатыванию триггера на команду git push
. Напротив — внешний агент следит за изменениями в репозитории, постоянно сравнивает данные в нем с состоянием Kubernetes и при необходимости меняет конфигурацию. Агент чаще всего расположен в том же кластере, где происходит развертывание.
Использование такого подхода позволяет избежать некоторых проблем. Например, если пользователь напрямую внесет изменения в кластер, внешний агент увидит это и вернет кластер в состояние, прописанное в Git. Подобная строгость мотивирует пользователей вместо прямого воздействия на кластер делать правки в единственном допустимом источнике истины — в репозитории.
Argo CD
Argo CD — декларативный GitOps-ориентированный популярный инструмент непрерывной доставки для Kubernetes.
Читайте также статью «Что такое GitOps? Краткий обзор методологии и знакомство с ArgoCD»
Основные компоненты Argo CD
- API Server — обеспечивает синхронизацию и аутентификацию пользователей, разграничивает права доступа, предоставляет API для взаимодействия с Argo CD.
- Application Controller — основной компонент, отвечающий за синхронизацию состояния кластера с Git-репозиторием.
- Repository Server — хранит кеш GitOps-репозитория, values Helm-чартов, текущую ревизию репозитория (commit, tag), а также содержит инструменты для обработки манифестов (Helm, Kustomize) — например, для рендеринга Helm-чартов и деплоя Argo CD использует Helm template.
Argo CD управляет не непосредственно манифестами и Helm-чартами, а Applications — абстракциями более высокого уровня, которые описывают желаемое состояние Kubernetes-ресурсов в Git-репозитории. Application может ссылаться на различные источники, такие как Helm-чарты, Kustomize-файлы, Jsonnet-манифесты или обычные Kubernetes-манифесты. Это позволяет выбирать подходящие инструменты для описания инфраструктуры, сохраняя единый механизм управления.
В примере ниже в локальном кластере создается приложение test-app и настраивается автоматическое отслеживание Git‑репозитория:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: test-app
namespace: Argo CD
spec:
source:
path: test-app
repoURL: https://gitlab.example.ru/gitops/prod-cluster.git
targetRevision: HEAD
destination:
namespace: test-app
server: https://kubernetes.default.svc
project: prod
Если приложение одно, то его несложно создавать вручную. Другое дело, когда количество сервисов и, соответственно, приложений, увеличивается, такой подход становится неэффективным и трудоемким. Argo CD предлагает решение этой проблемы — ApplicationSet, который позволяет динамически создавать приложения по определенным правилам (generators).
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: tenants
namespace: Argo CD
spec:
generators:
- git:
repoURL: https://gitlab.example.ru/gitops/prod-cluster.git
revision: HEAD
directories:
- path: tenants/*
Манифест выше создает ApplicationSet, который автоматически генерирует несколько приложений на основе структуры каталогов в Git. В этом примере git generator следит за изменениями в репозитории. Если в tenants появится новый каталог с конфигурацией (Helm-чарт или манифест), то Argo CD автоматически развернет приложение.
Argo CD оперирует двумя основными сущностями: приложениями (Applications) и проектами (Projects). Они играют ключевую роль в управлении конфигурацией, так как могут быть организованы для работы в разных средах (например, dev, staging, prod) и кластерах. Важно: именно ими управляет Argo CD, а не манифестами или чартами.
Приложение — это набор ресурсов Kubernetes и основная единица управления. Оно определяет источник манифестов, целевой кластер и синхронизацию между желаемым и фактическим состоянием кластера. Проекты позволяют организовывать приложения в логические группы для управления доступом (ограничение пользователей и групп), источниками и целями (манифесты и кластеры), а также применением общих политик (синхронизация, обновление).
Argo CD имеет удобный и понятный интерфейс для работы. Можно посмотреть текущее состояние синхронизации приложений, сравнить настоящую и прошлую ревизии (diff), изучить логи.
Унификация деплоя
В условиях современной разработки, где проекты могут быть сложными и разнообразными, а инфраструктура постоянно меняется, возникает необходимость в унификации процессов. Представьте, что нужно развернуть проект, который не обновлялся несколько лет, или перенести его в другой кластер, при этом не нарушив уникальный процесс развертывания. Еще частый источник путаницы и затрудненного управления — использование в каждом проекте собственного пайплайна.
В таких ситуациях выручает GitOps, который унифицирует процессы для всех проектов, независимо от особенностей сборки. Вместо настройки сложных пайплайнов используется простой и элегантный способ: достаточно доставить новый тег Docker-образа в GitOps-репозиторий — и приложение автоматически разворачивается в кластере.
В следующем примере клонируется репозиторий. Поле app.image_tag
в файле values.yaml
получает новое значение на основе короткой SHA‑суммы текущего коммита. В завершении изменения фиксируются в репозитории, а новый коммит получает информативное описание:
.deploy_template:
stage: deploy
image: $CI_REGISTRY/tools/yq:1.0.0
script:
- git clone "https://$USER:$TOKEN@$GITOPS_REPO_URL" gitops
- cd gitops
- yq -i ".app.image.tag = strenv(CI_COMMIT_SHORT_SHA)" ${GITOPS_CATALOG}/${GITOPS_NAME}/values.yaml
- git config --global user.email "deploy@example.ru"
- git config --global user.name "GitLab CI"
- git commit -am "CI Deploy ${CI_PROJECT_NAME} - ${CI_COMMIT_SHORT_SHA}"
- git push
Значение нового тега вставляется в values нашего Helm-чарта, после чего Argo CD синхронизирует изменения в репозитории, и ресурсы в Kubernetes обновляются.
Наш путь
Итак, подытожим, обобщив подход для управления инфраструктурой и развертывания приложений.
Мы сознательно отказались от использования монорепозитория. Вместо этого репозитории разделены. В одном хранится исключительно исходный код приложения, в другом — только конфигурационные файлы, описывающие желаемое состояние инфраструктуры.
Для управления множественными зависимостями мы используем Umbrella-чарты, которые хранятся в GitLab Package Registry.
Преимущества Argo CD
- Удобный веб-интерфейс.
- Непрерывная синхронизация приложений, поддержание целостности сущностей в кластере и их работоспособности.
- Единый источник верной конфигурации, что исключает configuration drift.
- Быстрое масштабирование и перенос приложений между кластерами — например, можно добавить проект с инфраструктурными сервисами, которые будут разворачиваться сразу во все кластеры.
Все недостатки связаны с необходимостью выделять время на настройку, оптимизацию пайплайнов, а также создание универсальных чатов в нашем случае.
Заключение
Внедрение GitOps-подхода и использование Argo CD позволили нам унифицировать пайплайны. Это значительно сократило время, затрачиваемое на поддержку и обновление наших проектов.
Мы успешно решили проблему configuration drifting, которая часто возникала при использовании традиционных методов развертывания. Конфигурация наших приложений всегда соответствует желаемому состоянию, описанному в репозитории. Новая архитектура и использование Kubernetes обеспечивают возможность масштабировать наши приложения на любое количество кластеров.
Argo CD — мощное средство. Однако его эффективное использование требует глубокого понимания особенностей управления Kubernetes. Здесь оказывается полезным Managed Kubernetes — специальный сервис, предоставляемый Selectel. Он снимает с разработчиков бремя управления инфраструктурой и позволяет сосредоточиться на реализации и развертывании приложений. Автомасштабирование, автовосстановление, обновление, мониторинг и обеспечение безопасности кластера в соответствии со 152‑ФЗ — все эти заботы берет на себя облачная платформа.
Сочетание Argo CD и Managed Kubernetes максимально упрощает и автоматизирует весь цикл жизни приложения от разработки до эксплуатации, что снижает операционные расходы. Подробнее о функциональности сервиса и его особенностях можно прочитать в онлайн‑документации Selectel.
Подписывайтесь на каналы Hilbert Team и Selectel, чтобы не пропустить выход новых материалов.