FluxCD: GitOps-доставка в Kubernetes без Jenkins

Jenkins CI/CD → GitOps: зачем менять

Компания «ДеплойПро» — 30 микросервисов в Kubernetes. CI/CD: Jenkins с 45 pipeline-ами. Проблемы:

  • Jenkins — единая точка отказа: обновление Jenkins → все деплои стоят
  • Credentials sprawl: kubeconfig в Jenkins для доступа к кластеру
  • Push-модель: Jenkins пушит в кластер. Нет гарантии, что состояние кластера = Git
  • Drift: kubectl apply вручную + Jenkins = непонятно что реально в кластере

GitOps — pull-модель: агент в кластере следит за Git-репозиторием и автоматически приводит кластер в соответствие с Git. Git = single source of truth.

Push (Jenkins)Pull (FluxCD/ArgoCD)
Jenkins → kubectl applyFlux agent ← git pull → apply
Credentials вне кластераCredentials внутри кластера
Нет гарантии consistencyReconciliation loop (30 сек)
Drift возможенAuto-remediation (drift fix)

Установка FluxCD и bootstrap

# Установка flux CLI
curl -s https://fluxcd.io/install.sh | bash
flux --version

# Bootstrap: FluxCD + Git репозиторий
flux bootstrap github \
  --owner=deploypro \
  --repository=k8s-gitops \
  --branch=main \
  --path=clusters/production \
  --personal

# Flux создаст в репозитории:
# clusters/production/flux-system/
#   gotk-components.yaml  — Flux controllers
#   gotk-sync.yaml        — GitRepository + Kustomization
#   kustomization.yaml

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

k8s-gitops/
├── clusters/
│   └── production/
│       ├── flux-system/       # Flux bootstrap (auto-generated)
│       ├── infrastructure.yaml # HelmRelease: nginx, cert-manager
│       └── apps.yaml          # Kustomization: приложения
├── infrastructure/
│   ├── nginx/
│   │   └── helmrelease.yaml
│   └── cert-manager/
│       └── helmrelease.yaml
└── apps/
    ├── orders-service/
    │   ├── deployment.yaml
    │   ├── service.yaml
    │   └── kustomization.yaml
    └── payments-service/
        ├── deployment.yaml
        ├── service.yaml
        └── kustomization.yaml

Деплой приложений: Kustomize и Helm

# apps/orders-service/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: orders-service
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: orders-service
  template:
    metadata:
      labels:
        app: orders-service
    spec:
      containers:
      - name: app
        image: registry.deploypro.ru/orders:v1.5.0
        ports:
        - containerPort: 8080
        resources:
          requests: { memory: 256Mi, cpu: 200m }
          limits: { memory: 512Mi, cpu: 500m }
# clusters/production/apps.yaml — Flux Kustomization
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: apps
  namespace: flux-system
spec:
  interval: 5m
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./apps
  prune: true          # Удалять ресурсы, которых нет в Git
  healthChecks:
  - apiVersion: apps/v1
    kind: Deployment
    name: orders-service
    namespace: production

Деплой = git push:

# Обновление версии образа
sed -i 's/orders:v1.5.0/orders:v1.6.0/' apps/orders-service/deployment.yaml
git add . && git commit -m "Bump orders-service to v1.6.0"
git push

# Flux обнаружит изменение через 30 сек (interval: 5m максимум)
# Применит новый deployment
# Проверит health check
flux get kustomizations
# NAME  REVISION    READY  MESSAGE
# apps  main@sha1   True   Applied revision: main@sha1

Image Automation: автоматическое обновление образов

Flux может автоматически обновлять image tag в Git при появлении нового образа в registry:

# ImageRepository — следит за registry
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
metadata:
  name: orders-service
  namespace: flux-system
spec:
  image: registry.deploypro.ru/orders
  interval: 5m

# ImagePolicy — правило выбора тега
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImagePolicy
metadata:
  name: orders-service
  namespace: flux-system
spec:
  imageRepositoryRef:
    name: orders-service
  policy:
    semver:
      range: ">=1.0.0"  # Берёт последний semver-тег

# ImageUpdateAutomation — коммитит изменения в Git
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageUpdateAutomation
metadata:
  name: image-updater
  namespace: flux-system
spec:
  interval: 30m
  sourceRef:
    kind: GitRepository
    name: flux-system
  git:
    checkout:
      ref: { branch: main }
    commit:
      author: { name: FluxCD, email: flux@deploypro.ru }
      messageTemplate: "chore: update images {{range .Changed.Changes}}{{.OldValue}} → {{.NewValue}}{{end}}"
    push:
      branch: main
  update:
    path: ./apps
    strategy: Setters

Итог: CI собирает образ → пушит в registry → Flux замечает → коммитит новый тег в Git → применяет в кластере. Полностью автоматически.

Результаты «ДеплойПро»

МетрикаJenkinsFluxCD
Время деплоя (commit → production)8-15 мин1-3 мин
Единая точка отказаJenkins serverНет (Flux в кластере)
Drift detectionНетАвто-исправление за 30 сек
ОткатПовторный запуск pipelinegit revert + push
Инфраструктура для CI/CDJenkins server (8 CPU, 16 GB)~200 MB в кластере
Credentials вне кластераkubeconfig в JenkinsНет (pull-модель)
FluxCD vs ArgoCD: Flux — CLI-first, GitOps-native, лучше для автоматизации. ArgoCD — UI-first, отличная визуализация, удобнее для команд с много ручного управления. Оба — отличный выбор. Для полной автоматизации — Flux. Для visibility — ArgoCD.

Часто задаваемые вопросы

FluxCD заменяет CD (Continuous Delivery) часть. CI (сборка, тесты, образы) остаётся: GitHub Actions, GitLab CI, Jenkins. Типичный pipeline: CI (GitHub Actions) → build image → push to registry → Flux (CD) → deploy to K8s.

Flux обнаружит drift при следующей reconciliation (по умолчанию каждые 5 минут) и откатит изменения к состоянию из Git. Это гарантирует, что Git = единственный источник правды. Для экстренных случаев можно временно приостановить Flux: flux suspend kustomization apps.

Flux интегрируется с Flagger — progressive delivery tool. Flagger автоматически: создаёт canary, направляет 5% трафика, мониторит метрики, постепенно увеличивает до 100% или откатывает при ошибках. Поддерживает Istio, Linkerd, Nginx Ingress.

Нет, plain-text секреты в Git — недопустимо. Решения: 1) Mozilla SOPS — шифрование секретов в Git, Flux расшифрует при apply. 2) External Secrets Operator — секреты в Vault/AWS SM, ESO синхронизирует в K8s. 3) Sealed Secrets — шифрование публичным ключом кластера.

Да, один GitOps-репозиторий может управлять несколькими кластерами. Структура: clusters/production/, clusters/staging/, clusters/dev/. Каждый кластер bootstrap-ится на свой path. Общие компоненты выносятся в infrastructure/ и переиспользуются через Kustomize overlays.

Нужна помощь с внедрением?

Настроим, оптимизируем и возьмём на поддержку вашу инфраструктуру. 15+ лет опыта, 8 серверов Dell Xeon в дата-центре МТС.

📞 Связаться с нами

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

Оставить комментарий

9 + 2 =