DevOps

GitOps в 2026 году: управление Kubernetes-инфраструктурой через Git с ArgoCD и автоматизированным CI/CD

Ruslan Ismailov Опубликовано 18 мин чтения
G

Введение: что такое GitOps и чем он отличается от классического CI/CD

GitOps — это операционная модель, при которой Git-репозиторий является единственным источником правды о состоянии инфраструктуры и приложений. Любое изменение в кластере Kubernetes происходит через pull request, а не через ручной kubectl apply или прямую команду из пайплайна.

Главное архитектурное отличие GitOps от классического CI/CD — это push-модель vs pull-модель. В классической схеме CI/CD пайплайн сам «толкает» изменения в кластер: получает доступ к Kubernetes API, аутентифицируется и применяет манифесты. В GitOps работает иначе:

  • Push-модель (классика): Jenkins/GitLab CI → kubectl apply → кластер. Пайплайн имеет прямой доступ к кластеру, секреты хранятся в CI-системе.
  • Pull-модель (GitOps): Git-репозиторий → ArgoCD внутри кластера → кластер. Оператор внутри кластера сам подтягивает желаемое состояние из Git.

Pull-модель имеет принципиальные преимущества: кластер не нужно «открывать» снаружи, внешний пайплайн не хранит kubeconfig с широкими правами, а каждое изменение проходит через code review в Git.

В 2026 году GitOps стал стандартом де-факто для команд, работающих с Kubernetes. ArgoCD и Flux — два самых распространённых инструмента. В этой статье мы подробно разберём ArgoCD-подход, построим полноценный CI/CD-пайплайн с GitHub Actions и покажем, как организовать GitOps-репозиторий для нескольких окружений.

Принципы GitOps

GitOps строится на четырёх фундаментальных принципах, сформулированных Weaveworks и закреплённых в OpenGitOps 1.0:

1. Декларативность

Всё желаемое состояние системы описывается декларативно — через Kubernetes-манифесты, Helm-чарты или Kustomize-конфигурации. Вы описываете что должно быть, а не как этого достичь.

2. Единый источник правды

Git-репозиторий — это единственное место, где хранится актуальное состояние инфраструктуры. Никаких «ручных патчей» напрямую в кластер, никаких изменений через kubectl без коммита в Git.

3. Автоматическая синхронизация

Оператор (ArgoCD) непрерывно сравнивает желаемое состояние (Git) с фактическим (кластер) и автоматически приводит кластер к желаемому состоянию.

4. Аудит через Git history

Каждое изменение инфраструктуры — это коммит с автором, временем и описанием. Полный audit trail бесплатно. Откат — это git revert.

ArgoCD: установка в кластер, концепции Application и AppProject

Установка ArgoCD

ArgoCD устанавливается в отдельный namespace кластера Kubernetes. Рекомендуется использовать официальный Helm-чарт для production-установки:

# Создаём namespace
kubectl create namespace argocd

# Устанавливаем через Helm
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update

helm install argocd argo/argo-cd \
  --namespace argocd \
  --set server.service.type=LoadBalancer \
  --set configs.params."server.insecure"=true \
  --version 6.7.0

# Получаем начальный пароль admin
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d

После установки ArgoCD предоставляет веб-интерфейс и CLI-инструмент argocd. CLI устанавливается отдельно и позволяет управлять приложениями, синхронизацией и проектами из терминала.

Концепция Application

Основная единица ArgoCD — это Application. Объект Application описывает, откуда брать манифесты (source) и куда их применять (destination):

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-service
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/gitops-repo.git
    targetRevision: HEAD
    path: apps/my-service/overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

Концепция AppProject

AppProject — это группировка приложений с ограничениями: какие репозитории разрешены как источник, в какие namespace и кластеры можно деплоить, какие ресурсы разрешены. Это важно для multi-tenant кластеров, где разные команды работают изолированно.

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: backend-team
  namespace: argocd
spec:
  description: Backend microservices team
  sourceRepos:
    - https://github.com/myorg/gitops-repo.git
  destinations:
    - namespace: production
      server: https://kubernetes.default.svc
    - namespace: staging
      server: https://kubernetes.default.svc
  clusterResourceWhitelist:
    - group: ''
      kind: Namespace

Структура GitOps-репозитория

Mono-repo vs Multi-repo

Существуют два основных подхода к организации GitOps-репозитория:

  • Mono-repo: все манифесты всех сервисов и окружений в одном репозитории. Проще начать, удобно для небольших команд, единый code review.
  • Multi-repo: отдельный репозиторий для каждого сервиса или каждого окружения. Лучше масштабируется, чёткие границы доступа, но сложнее управлять зависимостями между сервисами.

Для большинства команд, начинающих GitOps в 2026 году, рекомендуем mono-repo с чёткой структурой директорий. Вот рекомендуемая структура:

gitops-repo/
├── apps/
│   ├── api-service/
│   │   ├── base/
│   │   │   ├── deployment.yaml
│   │   │   ├── service.yaml
│   │   │   ├── configmap.yaml
│   │   │   └── kustomization.yaml
│   │   └── overlays/
│   │       ├── dev/
│   │       │   ├── kustomization.yaml
│   │       │   └── patch-replicas.yaml
│   │       ├── staging/
│   │       │   ├── kustomization.yaml
│   │       │   └── patch-resources.yaml
│   │       └── production/
│   │           ├── kustomization.yaml
│   │           └── patch-hpa.yaml
│   └── worker-service/
│       ├── base/
│       └── overlays/
├── infrastructure/
│   ├── cert-manager/
│   ├── ingress-nginx/
│   └── monitoring/
├── argocd/
│   ├── projects/
│   │   └── backend-team.yaml
│   └── applications/
│       ├── api-service-dev.yaml
│       ├── api-service-staging.yaml
│       └── api-service-production.yaml
└── helm-charts/
    └── base-service/
        ├── Chart.yaml
        ├── values.yaml
        └── templates/

Kustomize vs Helm в GitOps

Kustomize встроен в kubectl и ArgoCD поддерживает его нативно. Подход base/overlays позволяет иметь общую базовую конфигурацию и переопределять только то, что отличается между окружениями — например, количество реплик, лимиты ресурсов или имена образов.

Helm удобен для сложных чартов с большим количеством параметров. ArgoCD поддерживает Helm-чарты напрямую — вы указываете путь к чарту и values-файл в Application. В GitOps-подходе с Helm рекомендуется хранить в Git не сами темплейты, а values.yaml для каждого окружения.

Построение CI-пайплайна с GitHub Actions

В GitOps CI и CD разделены на два отдельных этапа. CI-пайплайн отвечает только за сборку и публикацию Docker-образа, а также за обновление тега образа в GitOps-репозитории. ArgoCD подхватывает изменение и выполняет деплой.

Вот полный пример GitHub Actions workflow для CI-части:

name: CI — Build and Update Manifest

on:
  push:
    branches: [main]
    paths:
      - 'src/**'
      - 'Dockerfile'

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: myorg/api-service
  GITOPS_REPO: myorg/gitops-repo

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=sha,prefix=,suffix=,format=short
            type=ref,event=branch

      - name: Build and push Docker image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Update image tag in GitOps repo
        env:
          IMAGE_TAG: ${{ github.sha }}
          GITOPS_TOKEN: ${{ secrets.GITOPS_PAT }}
        run: |
          SHORT_SHA=$(echo "$IMAGE_TAG" | cut -c1-7)
          
          git config --global user.email "ci-bot@myorg.com"
          git config --global user.name "CI Bot"
          
          git clone https://x-access-token:${GITOPS_TOKEN}@github.com/${GITOPS_REPO}.git gitops
          cd gitops
          
          # Обновляем тег образа через kustomize
          cd apps/api-service/overlays/dev
          kustomize edit set image api-service=${REGISTRY}/${IMAGE_NAME}:${SHORT_SHA}
          
          git add .
          git commit -m "chore: update api-service image to ${SHORT_SHA}"
          git push

Ключевые моменты этого пайплайна: CI не знает о кластере Kubernetes вообще. Он только обновляет манифест в GitOps-репозитории. Токен GITOPS_PAT — это Personal Access Token с правом на запись только в GitOps-репозиторий, а не в кластер.

Стратегии деплоя через ArgoCD

Автоматическая синхронизация для dev и staging

Для dev и staging окружений рекомендуется включить автоматическую синхронизацию. Как только в GitOps-репозитории появляется новый коммит, ArgoCD автоматически применяет изменения:

syncPolicy:
  automated:
    prune: true      # удалять ресурсы, которых нет в Git
    selfHeal: true   # восстанавливать ручные изменения в кластере
  syncOptions:
    - CreateNamespace=true
    - PrunePropagationPolicy=foreground

Ручное подтверждение для production

Для production окружения автоматическая синхронизация отключается. Деплой требует явного подтверждения через UI ArgoCD или CLI. Это позволяет провести финальный review перед применением изменений:

syncPolicy: {}  # нет автоматической синхронизации

# Деплой выполняется вручную:
# argocd app sync api-service-production

Также можно настроить sync windows — временны́е окна, в которые синхронизация разрешена. Например, запрет деплоев в production в пятницу вечером и выходные — стандартная практика.

Стратегии обновления

ArgoCD поддерживает нативные стратегии Kubernetes: RollingUpdate и Recreate. Для более сложных сценариев — canary и blue/green — используется Argo Rollouts, дополнение к ArgoCD, которое добавляет CRD Rollout вместо стандартного Deployment.

Управление секретами в GitOps

Главная проблема GitOps — секреты нельзя хранить в Git в открытом виде. Существует несколько подходов.

Sealed Secrets

Sealed Secrets от Bitnami позволяет зашифровать секрет публичным ключом кластера. Зашифрованный SealedSecret безопасно хранится в Git. Контроллер внутри кластера расшифровывает его приватным ключом и создаёт обычный Secret.

# Устанавливаем kubeseal CLI
brew install kubeseal

# Получаем публичный ключ кластера
kubeseal --fetch-cert \
  --controller-name=sealed-secrets-controller \
  --controller-namespace=kube-system \
  > pub-cert.pem

# Создаём обычный Secret и шифруем его
kubectl create secret generic db-credentials \
  --from-literal=password=supersecret \
  --dry-run=client -o yaml | \
  kubeseal --cert pub-cert.pem \
  --format yaml > db-credentials-sealed.yaml

# db-credentials-sealed.yaml можно безопасно коммитить в Git

Преимущество Sealed Secrets: полностью GitOps-native, всё хранится в репозитории. Недостаток: если приватный ключ кластера утерян — все секреты нужно пересоздавать.

External Secrets Operator

External Secrets Operator (ESO) интегрируется с внешними хранилищами секретов: AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager, Azure Key Vault. В Git хранится только ExternalSecret — ссылка на секрет во внешнем хранилище:

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: db-credentials
  namespace: production
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets-manager
    kind: ClusterSecretStore
  target:
    name: db-credentials
    creationPolicy: Owner
  data:
    - secretKey: password
      remoteRef:
        key: prod/api-service/db
        property: password

ESO — предпочтительный подход для production в 2026 году, особенно если организация уже использует централизованное хранилище секретов. В Git хранятся только метаданные, не данные.

Multi-environment: dev, staging, production

Существуют два популярных подхода к организации нескольких окружений в GitOps:

Подход через директории (рекомендуется)

Каждое окружение — отдельная поддиректория в репозитории. Все окружения на одной ветке main. Изменения проходят через PR. Промоция между окружениями — это коммит обновления тега образа в директорию следующего окружения:

  • apps/api-service/overlays/dev/ — автосинхронизация при каждом push в main
  • apps/api-service/overlays/staging/ — синхронизация после успешного тестирования dev
  • apps/api-service/overlays/production/ — ручная синхронизация после approval

Подход через ветки

Каждое окружение — отдельная ветка (dev, staging, main/production). ArgoCD наблюдает за конкретной веткой. Промоция — это merge между ветками. Этот подход сложнее в управлении и не рекомендуется для новых проектов, так как ветки расходятся и сложно отследить, что где задеплоено.

Для автоматической промоции между окружениями можно использовать GitHub Actions workflow, который после успешного деплоя в staging создаёт PR с обновлённым тегом образа в директорию production.

Drift Detection и Self-Healing

Одна из ключевых возможностей ArgoCD — обнаружение дрейфа конфигурации (configuration drift). Это ситуация, когда фактическое состояние кластера расходится с желаемым состоянием в Git.

Drift может возникнуть из-за:

  • Ручного kubectl edit или kubectl scale напрямую в кластере
  • Автоскейлинга (HPA изменяет количество реплик)
  • Операторов Kubernetes, изменяющих ресурсы
  • Сбоев при предыдущих синхронизациях

ArgoCD непрерывно (по умолчанию каждые 3 минуты) сравнивает желаемое и фактическое состояние. При обнаружении дрейфа приложение получает статус OutOfSync.

При включённом selfHeal: true ArgoCD автоматически приводит кластер к состоянию из Git. Это означает, что любое ручное изменение будет перезаписано — именно это и является целью GitOps: Git — единственный источник правды.

Важный нюанс: если HPA управляет количеством реплик, не стоит указывать replicas в Deployment-манифесте (или использовать аннотацию ArgoCD для игнорирования этого поля), иначе ArgoCD будет постоянно откатывать изменения HPA:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: api-service
spec:
  ignoreDifferences:
    - group: apps
      kind: Deployment
      jsonPointers:
        - /spec/replicas

Метрики успеха GitOps: DORA Metrics

Переход на GitOps должен измеряться через конкретные метрики. Индустриальный стандарт — DORA metrics (DevOps Research and Assessment):

  • Deployment Frequency (Частота деплоев): как часто команда деплоит в production. GitOps снижает барьер для деплоя — коммит в репозиторий автоматически запускает процесс. Элитные команды деплоят несколько раз в день.
  • Lead Time for Changes (Время от коммита до production): время от коммита кода до работающего деплоя. С GitOps и автоматизированным CI/CD это время сокращается до минут.
  • Change Failure Rate (Процент неудачных изменений): какой процент деплоев приводит к инцидентам. Декларативный деплой и code review через PR снижают этот показатель.
  • Mean Time to Recovery (Среднее время восстановления): как быстро команда восстанавливается после инцидента. В GitOps откат — это git revert + ArgoCD sync, что занимает минуты.

Для сбора этих метрик в Kubernetes-окружении используют связку Prometheus + Grafana. ArgoCD экспортирует метрики в формате Prometheus по умолчанию: количество синхронизаций, статусы приложений, время последнего деплоя.

# Пример PromQL-запроса для мониторинга ArgoCD
# Количество успешных синхронизаций за последние 24 часа
sum(increase(argocd_app_sync_total{phase="Succeeded"}[24h])) by (name)

# Приложения в статусе OutOfSync
argocd_app_info{sync_status="OutOfSync"}

Заключение: типичные ошибки при переходе на GitOps

Переход на GitOps — это изменение не только инструментов, но и процессов. Вот наиболее распространённые ошибки команд:

Ошибка 1: Хранение секретов в Git в открытом виде

Самая критичная ошибка. Используйте Sealed Secrets или External Secrets Operator с первого дня. Никогда не коммитьте kind: Secret с незашифрованными данными.

Ошибка 2: Ручные изменения в кластере наряду с GitOps

Если часть команды продолжает использовать kubectl apply напрямую, GitOps теряет смысл. Необходимо ввести организационный запрет на прямые изменения и настроить RBAC так, чтобы у разработчиков не было прав на edit в production namespace.

Ошибка 3: Один монолитный GitOps-репозиторий без структуры

Без чёткой структуры директорий репозиторий быстро становится неуправляемым. Сразу закладывайте структуру base/overlays и разделение по командам через AppProject.

Ошибка 4: Автоматическая синхронизация включена для production с первого дня

Начните с ручной синхронизации для production. Команда должна привыкнуть к процессу и понять, что ArgoCD делает, прежде чем давать ему автономность в критичном окружении.

Ошибка 5: Игнорирование drift detection

Если ArgoCD показывает приложение в статусе OutOfSync, это сигнал для расследования. Не нажимайте «Sync» не разобравшись, почему возник дрейф.

Ошибка 6: Отсутствие тестирования манифестов в CI

Добавьте в CI-пайплайн GitOps-репозитория проверку манифестов: kustomize build | kubeval или helm lint. Это поймает синтаксические ошибки до того, как ArgoCD попытается применить их в кластер.

GitOps в 2026 году — это не просто инструмент, это культура работы с инфраструктурой. Успешный переход требует как технической настройки ArgoCD и CI/CD-пайплайнов, так и изменения процессов в команде: всё через PR, всё через Git, никаких ручных изменений.

Начните с малого: задеплойте один некритичный сервис через ArgoCD в dev-окружение. Убедитесь, что команда понимает цикл «коммит → CI → обновление манифеста → ArgoCD sync». Затем постепенно переводите остальные сервисы и окружения. GitOps с ArgoCD — это инвестиция, которая окупается через снижение DORA-метрик и повышение надёжности деплоев.

Технологии

Теги

Руслан Исмаилов

Senior Web / Backend разработчик. Senior web/backend разработчик с 9-летним опытом. Стек: PHP, Laravel, PostgreSQL, Redis, Docker, Kubernetes, REST, микросервисы, CI/CD. Подробнее обо мне →