Модуль 26. GitOps и CI/CD для Kubernetes
Цель: перевести все изменения кластера в pull-модель: состояние — в Git, кластер сам «подтягивает» и приводится к нему.
Итог:
- Единый репозиторий (или несколько — по доменам) с чартами/манифестами, окружениями Dev→Stage→Prod.
- Argo CD или FluxCD как «reconciler».
- GitLab CI: сборка образа, тесты/сканы, публикация в реестр, изменение манифестов коммитом (а не kubectl apply), PR-промо окружений.
- Стандартизованные шаблоны: Helm-чарт сервиса, Kustomize-оверлеи, hook’и миграций, политика секретов.
Принципы GitOps (коротко, но по сути)
- Единственный источник правды — Git.
- Pull-подход: агент в кластере читает Git и reconcile’ит состояние (дребезг=самоисцеление).
- Иммутабельность артефактов: образ — по неподвижному тегу/дижесту; запрет :latest.
- Промо через Git: Dev→Stage→Prod — PR/merge ценностей/версий, а не ручной «тык».
- Обратимость: rollback = revert коммита или «синхрон до предыдущего ревизии».
Структура репозиториев и окружений
Вариант А (рекомендуем для старта): mono-repo платформы
gitops/
apps/ # декларации приложений
<svc-A>/
helm/ # чарт или chart dependency
kustomize/ # base + overlays
base/
overlays/
dev/
stage/
prod/
clusters/
dev/ # ArgoCD/Flux корневые манифесты окружения
stage/
prod/
policies/ # Kyverno/Gatekeeper, PodSecurity и пр.
secrets/ # Sealed/ESO descriptors, без секретов в явном виде
Вариант B: multi-repo (по командам/сервисам) + единый «платформенный» repo, который подтягивает остальные (ArgoCD ApplicationSet / Flux GitRepository).
Правило: один ресурс управляется ровно из одного места (никаких «пересекающихся» HelmRelease/Kustomization).
Argo CD: как работает и что важно
Ключевые сущности:
- Application — связь «источник (Git/Helm) → целевой namespace/cluster».
- AppProject — границы и права (какие NS, какие источники, RBAC для команд).
- SyncPolicy: auto-sync (включая prune/self-heal), sync waves (PreSync/Sync/PostSync hook’и).
- ApplicationSet — генерация множества Application (мультикластер, множество сервисов/вендоров).
- Health/Status — видимость, уведомления (Argo CD Notifications).
Паттерны:
- App-of-Apps: одно «корневое» приложение разворачивает остальные (кластер описывается как дерево).
- Прядок CRD → CR: sync-waves/hook’и для правильного порядка (сначала CRD, потом CR).
- RBAC: команды маппим на AppProject, даём право только на свой NS/путь в Git.
Observability: включить события/метрики Argo CD, оповещения о OutOfSync/Degraded в Slack/почту.
FluxCD: эквивалентные кирпичики и отличия
Компоненты:
- Source Controller (GitRepository/HelmRepository), Kustomize Controller (Kustomization), Helm Controller (HelmRelease), Image Automation (авто-бамп тегов по политике).
Плюсы Flux: нативная image-автоматизация, декларативность через отдельные CRD, лёгкая разбивка по «папкам-Kustomization».
Плюсы Argo CD: удобная визуализация, «дерево приложений», mature UI/SSO, ApplicationSet.
Вывод: любой из них годится. Выбирайте по опыту команды/требованиям (часто — Argo CD для UI, Flux для «CLI-first»; совместное использование допустимо, но не на одни и те же ресурсы).
Helm и Kustomize — как сочетать
- Helm — шаблонизатор + пакетный менеджер (values, зависимости, hooks).
- Kustomize — «оверлеи поверх base» без шаблонов, декларативные патчи (patchesStrategicMerge, images, configMapGenerator).
Практично:
- Держим Helm-чарт приложения (универсальный), а окружения описываем Kustomize-оверлеями (dev/stage/prod values, ресурсы, аннотации, секрет-refs).
- Версии чартов пинним (semver), values — минимальны и понятны.
- Для групповых релизов используем HelmRelease (Flux) или Argo CD с helm: секцией.
GitLab CI/CD + Kubernetes executor (только «скелет»)
Pipeline стадии:
- build образа (Kaniko/BuildKit-in-Docker),
- test/scan (SAST/DAST/Trivy),
- push в реестр,
- update-manifests: меняем тег/дижест в Git (Kustomize images: или bump Helm values) → PR/merge → Argo/Flux «подтягивает».
- smoke (после синхронизации — автотесты против Dev/Stage).
Мини-эскизы (для ориентира, не копируйте «как есть»):
# .gitlab-ci.yml (фрагмент идей)
stages: [build, test, scan, push, update-manifests]
build:
image: gcr.io/kaniko-project/executor:latest
script:
- /kaniko/executor --context $CI_PROJECT_DIR --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
update-manifests:
image: bitnami/kubectl:latest
script:
- ./scripts/bump-image.sh $CI_REGISTRY_IMAGE $CI_COMMIT_SHA # правит kustomization.yaml / values.yaml
- git commit -am "bump $CI_COMMIT_SHA" && git push origin HEAD:feature/release-$CI_COMMIT_SHORT_SHA
Важно:
- НИКАКОГО kubectl apply из CI в prod-кластеры; только коммиты в Git.
- Kubernetes executor запускает job в кластере — следите за quotas/RBAC, не давайте пайплайну «кластер-админа».
Стратегии выката: blue-green и canary
Blue-green: две среды (blue и green), переключение трафика (Service/Ingress).
- Плюс: быстрый обратный переключатель.
- Минус: удвоенные ресурсы на время релиза, сложнее миграции БД.
Canary (progressive delivery): трафик по процентам, промо по метрикам/логам.
- Инструменты: Argo Rollouts (CRD: Rollout + AnalysisTemplate), Ingress-аннотации для canary (nginx/traefik) или сервис-меш.
- Метрики-гейты: p95 latency, 5xx rate, бизнес-ошибки.
- Авто-стоп/автопромо при соблюдении SLO.
Rollback:
- Argo: «синхрон на предыдущий commit/Revision», Helm — helm history/rollback.
- Canary: откатить на предыдущую стабильную реплику/Service.
- Миграции БД: expand/contract (совместимые схемы), pre-/post-hook проверенные на Stage. Никогда не завязывайте откат схемы на откат образа без план-B.
Секреты в GitOps (безопасно)
- Нельзя хранить секреты в Git в открытом виде и в ConfigMap.
-
Варианты:
- External Secrets Operator + Vault (источник правды во Vault; ESO синхронизирует в Secret или монтирует через Secret Store CSI).
- Sealed Secrets — шифротексты в Git, ключ у контроллера.
- Для облаков — Workload Identity / IRSA (выдача временных прав по SA).
- В CI — ни одного долговечного токена; только короткие, с минимумом прав.
Политики и контроль качества
-
Kyverno/Gatekeeper на входе:
- запрет :latest,
- разрешённые реестры,
- наличие requests/limits,
- runAsNonRoot, drop-caps, seccomp,
- подпись образов (cosign verify).
- CI-чеки: helm lint, kubeconform/kubeval, шаблоны ADR на архитектурные изменения.
- Drift-детект: Argo/Flux в self-heal. Реестр ручных правок в prod = 0.
Типовые ошибки и как их избегать
|
Ошибка |
Чем кончается |
Как правильно |
|---|---|---|
|
kubectl apply из CI в прод |
Обход GitOps, «потеря» истории/обратимости |
Меняем только Git, reconcile делает Argo/Flux |
|
Несогласованные чарт-версии между env |
«На Stage ок, на Prod — нет» |
Версионирование chart’ов/values, промо фиксированной версии PR’ом |
|
:latest и плавающие теги |
«Ездит» прод, не воспроизвести |
Только иммутабельные теги/дижесты, pin в манифестах |
|
Один и тот же ресурс управляют и Helm, и Kustomize |
Дерганья/конфликты |
Жёсткое разделение ownership |
|
Секреты в Git/ConfigMap |
Утечки |
ESO/Vault/Sealed Secrets/CSI, encryption-at-rest |
|
Hooks миграций «в лоб» |
даунтайм/невозможность отката |
Expand-contract, preflight проверки, ручной gate для Prod |
|
Отсутствие «входных» политик |
В прод просачиваются небезопасные манифесты |
Kyverno/Gatekeeper + CI-валидации |
|
Автосинк + неосторожный prune |
Снесли «чужие» ресурсы |
Scope по NS/label, dry-run, review, защитные правила |
Практика (лабораторка за 1–2 дня)
- Завести Git-скелет: чарт сервиса + kustomize base/overlays (dev/stage/prod).
- Поставить Argo CD (или Flux), завести AppProject и три Application (по окружениям).
- Собрать образ в GitLab CI, запушить в реестр, обновить тег в манифесте → PR в dev.
- Argo/Flux подтянул релиз → smoke-тест. Далее — PR промо в stage, потом в prod.
- Добавить Kyverno-политику «запрет latest» и проверить, что релиз с latest отклоняется.
- Подключить ESO+Vault: один секрет, потребляемый приложением.
- Canary через Argo Rollouts: 5%→25%→100% с гейтами по p95/5xx.
- Сымитировать откат: revert коммита, убедиться в корректности.
Чек-лист «готово к продакшену»
- Git — единственный источник правды. Никаких «ручных» изменений в кластере.
- Argo CD/Flux с авто-sync (self-heal), корректный scope, уведомления.
- Стандартизованный шаблон приложения (Helm + Kustomize overlays).
- CI: build → test/scan → push → bump manifests via PR. Никакого kubectl apply.
- Secrets: Vault/ESO или Sealed; Workload Identity, encryption-at-rest.
- Политики: Kyverno/Gatekeeper (no latest, registries, sec-context, verify image).
- Progressive delivery: blue-green/canary, метрики-гейты, rollback сценарий.
- Миграции БД: expand/contract, pre/post-hook’и, ручной gate для prod.
- Наблюдаемость релизов: дашборды/алерты, аннотации релизов, история.
- Док-пакет: runbook’и «rollback», «застрял sync», «провал health-check/analysis».
Вопрос-ответ
В: Что выбрать — Argo CD или FluxCD?
О: Оба зрелые. Нужен UI/«дерево приложений» и ApplicationSet — берите Argo CD. Нужна простая декларативность и image-автобампинг — Flux. Не управляйте одними и теми же ресурсами обоими.
В: Helm или Kustomize?
О: Часто — оба: Helm — как «пакет» сервиса, Kustomize — как «оверлеи окружений». Если команда не любит шаблоны — чистый Kustomize тоже работает.
В: Как промотировать версии между окружениями?
О: Через PR/merge из dev overlay в stage/prod (или через release-ветки). Никаких «ручных» правок в прод-папке.
В: Можно ли триггерить выкаты из GitLab?
О: Да, но триггер — коммит в Git манифестов. Никаких прямых kubectl из пайплайна в prod.
В: Как делать canary без сервис-меша?
О: Argo Rollouts + NGINX/Traefik (аннотации/трафик-сплит), метрики из Prometheus. При росте — рассмотрите mesh.
В: Где хранить секреты в GitOps?
О: В Git — только описатели (Sealed/ESO). Данные — во Vault/облачных Secret Manager’ах/CSI. Без «голых» Secret/ConfigMap.
В: Что с CRD-порядком?
О: Включайте sync-waves/hook’и (CRD → CR), держите CRD в отдельном слое/приложении.
В: Как избежать «несогласованности чартов и окружений»?
О: Версионируйте чарт, фиксируйте версии в overlays, промо — через PR с review и автотестами. Автопроверки helm template/lint и kubeconform.
В: Можно ли в закрытом контуре (без интернета)?
О: Да: локальные зеркала Git/реестров/Helm-реп, Argo/Flux смотрят внутрь, сканы/подписи — внутри периметра.
Рабочий GitOps-контур — это pull-модель (Argo/Flux), стандартизованные манифесты (Helm+Kustomize), CI, который меняет только Git, и жёсткие политики на входе. Добавьте progressive delivery и дисциплину миграций — и у вас получатся выкаты, которые предсказуемы, прозрачно отслеживаются и легко откатываются. Это ровно то, что нужно для BI/DWH-ландшафта, где релизы должны быть частыми, но безопасными.



