Python structlog: структурированное логирование для продакшена
GitOps меняет подход к деплою: вместо kubectl apply из CI-пайплайна вы коммитите манифесты в Git, а контроллер в кластере сам синхронизирует состояние. ArgoCD — самый популярный GitOps-контроллер для Kubernetes. Разберём его архитектуру, настройку и лучшие практики.
GitOps: pull-based vs push-based деплой
Push-based (традиционный): CI-пайплайн после сборки выполняет kubectl apply или helm upgrade. Проблемы — CI нужен доступ к кластеру (kubeconfig с правами), drift между Git и реальным состоянием не отслеживается, откат — ручной.
Pull-based (GitOps): контроллер внутри кластера следит за Git-репозиторием и автоматически применяет изменения. Преимущества:
- Git — единственный источник правды. Что в репо — то в кластере.
- CI не нужен доступ к кластеру — только push в Git.
- Автоматическое обнаружение drift (ручные изменения через kubectl).
- Откат =
git revert.
ArgoCD архитектура
ArgoCD состоит из трёх основных компонентов:
- API Server — UI, CLI, gRPC/REST API.
- Repo Server — клонирует Git-репозитории, рендерит Helm/Kustomize.
- Application Controller — следит за состоянием и выполняет sync.
Ключевые CRD:
- Application — описывает одно приложение: откуда брать манифесты и куда деплоить.
- AppProject — группа приложений с общими политиками доступа.
Установка и первое приложение
# Установка ArgoCD в кластер
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Получить пароль admin
argocd admin initial-password -n argocd
# Доступ к UI
kubectl port-forward svc/argocd-server -n argocd 8080:443
Создаём первое приложение через манифест:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: api-service
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/myorg/k8s-manifests.git
targetRevision: main
path: apps/api-service
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Или через Helm chart:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: redis
namespace: argocd
spec:
project: default
source:
repoURL: https://charts.bitnami.com/bitnami
chart: redis
targetRevision: "19.*"
helm:
values: |
architecture: standalone
auth:
enabled: true
password: ${REDIS_PASSWORD}
resources:
requests:
memory: 128Mi
cpu: 100m
destination:
server: https://kubernetes.default.svc
namespace: production
Auto-sync vs manual sync
Auto-sync — ArgoCD автоматически применяет изменения из Git:
syncPolicy:
automated:
prune: true # удалять ресурсы, которых нет в Git
selfHeal: true # откатывать ручные изменения в кластере
Manual sync — изменения применяются только по кнопке/команде:
argocd app sync api-service
Когда что использовать:
- Auto-sync + selfHeal — для staging/dev окружений. Коммит в main = мгновенный деплой.
- Manual sync — для production. Коммит создаёт diff в UI, деплой — осознанное действие после review.
- Auto-sync без prune — компромисс: новые ресурсы создаются автоматически, но удаление требует ручного подтверждения.
Sync waves и hooks: порядок деплоя
По умолчанию ArgoCD применяет все ресурсы одновременно. Sync waves задают порядок:
# Wave -1: миграции БД (выполняются первыми)
apiVersion: batch/v1
kind: Job
metadata:
name: db-migrate
annotations:
argocd.argoproj.io/sync-wave: "-1"
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
spec:
template:
spec:
restartPolicy: Never
containers:
- name: migrate
image: myapp:2.0
command: ["npm", "run", "migrate"]
---
# Wave 0: основное приложение (по умолчанию)
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
annotations:
argocd.argoproj.io/sync-wave: "0"
spec:
# ...
---
# Wave 1: после деплоя — smoke test
apiVersion: batch/v1
kind: Job
metadata:
name: smoke-test
annotations:
argocd.argoproj.io/sync-wave: "1"
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
spec:
template:
spec:
restartPolicy: Never
containers:
- name: test
image: myapp:2.0
command: ["npm", "run", "test:smoke"]
Порядок: PreSync hooks (wave -1) → основные ресурсы (wave 0) → PostSync hooks (wave 1). Если миграция упала — деплой останавливается.
Мониторинг: health checks, notifications, SSO
Health checks — ArgoCD автоматически определяет здоровье ресурсов (Deployment ready, Pod running, Ingress has address). Для кастомных CRD можно добавить свои health-скрипты в ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
data:
resource.customizations.health.mycrd.example.com_MyResource: |
hs = {}
if obj.status ~= nil then
if obj.status.phase == "Ready" then
hs.status = "Healthy"
else
hs.status = "Progressing"
end
end
return hs
Notifications — оповещения в Slack, Teams, email при sync/failure:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
annotations:
notifications.argoproj.io/subscribe.on-sync-succeeded.slack: deployments
notifications.argoproj.io/subscribe.on-sync-failed.slack: alerts
SSO через Dex — интеграция с GitHub, GitLab, OIDC для контроля доступа. AppProject ограничивает, какие команды могут деплоить в какие namespace:
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: team-backend
spec:
destinations:
- namespace: "backend-*"
server: https://kubernetes.default.svc
sourceRepos:
- "https://github.com/myorg/backend-*"
roles:
- name: deployer
policies:
- p, proj:team-backend:deployer, applications, sync, team-backend/*, allow
Вывод
ArgoCD превращает Git в единственный источник правды для Kubernetes-деплоя. Auto-sync для dev, manual для production, sync waves для порядка миграций, notifications для прозрачности. Начните с одного приложения в manual mode, убедитесь что workflow работает, затем включайте auto-sync и добавляйте остальные сервисы. GitOps — это не просто инструмент, это дисциплина: всё через PR, никаких kubectl apply руками.