Přestaňte bourat dům kvůli výměně nábytku: Proč je GitOps lepší než push-based deployment

Chcete nasadit novou verzi API. Změna jednoho řádku: posunout image tag z v1.4.2 na v1.4.3. S GitOps setupem pushnete do Gitu a za 30 sekund je cluster srovnaný. S push-based přístupem, který stále vidím v produkci — Helm charty publikované Terraformem — spustíte pipeline, která naplánuje celou infrastrukturu, vyhodnotí každý resource, čeká na schválení a pak aplikuje změnu. To je jako bourat dům kvůli výměně nábytku.
A přesto push-based deployment přes Terraform zůstává pozoruhodně populární. Manažeři ho mají rádi, protože vidí tlačítko “Deploy” v CI/CD rozhraní. Inženýři ho používají ze setrvačnosti, protože Terraform už spravuje cluster. Ale cena je reálná — v délce pipeline, v blast radius, v provázanosti a v operační odolnosti.
Jak funguje push-based deployment
Typický push-based setup vypadá takto:
VPC, DNS, databáze,
Helm releasy, secrety... TF->>TF: Plan: 1 ke změně CI->>CI: Čekání na manuální schválení CI->>TF: terraform apply TF->>K8s: helm upgrade my-api Note over K8s: Image aktualizován na v1.4.3
Terraform vlastní všechno — GKE cluster, VPC, Cloud SQL instanci, DNS záznamy a Helm releasy. Pro jakoukoli změnu musíte spustit celou pipeline. I když se změnil jen image tag, Terraform musí:
- Inicializovat — stáhnout providery, moduly a state soubor
- Naplánovat — vyhodnotit každý resource ve statu oproti reálnému světu
- Čekat — někdo klikne na “Approve” (protože infrastrukturní změny přeci neaplikujete automaticky, že?)
- Aplikovat — provést změnu
Pro středně velkou infrastrukturu to trvá 5-15 minut. Pro velké setupy se stovkami resources to může být 30+. To všechno kvůli aktualizaci jednoho container tagu.
Jak funguje GitOps (pull-based)
S Flux CD cluster sleduje váš Git repozitář a průběžně srovnává skutečný stav s požadovaným:
(polling nebo webhook) Flux->>Git: Pull nejnovějších manifestů Flux->>K8s: Aplikuje diff: aktualizace image tagu Note over K8s: Image aktualizován na v1.4.3 Flux->>Flux: Reconciliace dokončena ✓
Žádná spuštěná pipeline. Žádné přehodnocování infrastruktury. Žádné manuální schvalování pro už zrevidovaný Git commit. Flux viděl změnu v Gitu, spočítal diff oproti clusteru a aplikoval jen to, co se změnilo. Celý cyklus trvá 30 sekund až 2 minuty.
Skutečná cena push-based deploymentu
1. Všechno je provázané
Když Terraform spravuje infrastrukturu i deployment aplikací, sdílejí state soubor, pipeline a blast radius. Bug v Helm chart šabloně může zablokovat kritickou změnu VPC. Timeout databázové migrace může zabránit nesouvisejícímu deploymentu aplikace. Všechno jde přes jedno úzké hrdlo.
S GitOps Terraform spravuje infrastrukturu, která se mění zřídka (sítě, clustery, databáze), a Flux spravuje workloady, které se mění často (aplikace, konfigurace). Každý má svůj vlastní životní cyklus, svou kadenci, svou failure doménu.
2. Žádné self-healing
Push-based deployment je typu vystřel a zapomeň. Terraform aplikuje změnu a odejde. Pokud někdo spustí kubectl delete deployment my-api nebo výpadek nodu způsobí přeplánování podů se zastaralou konfigurací, Terraform to neví a je mu to jedno — stav kontroluje jen když ho spustíte znovu.
Flux průběžně reconciluje. Každých pár minut porovnává stav clusteru s Git repozitářem a opravuje jakýkoli drift. Někdo ručně zmenšil váš deployment na 1 repliku? Flux to vrátí. Někdo aplikoval hotfix přímo přes kubectl? Flux to přepíše tím, co je v Gitu. Git repozitář je jediný zdroj pravdy a cluster je jeho odrazem.
Tohle není teoretický benefit. V produkci jsme viděli:
- Vývojáře, který přes
kubectl applynasadil debug konfiguraci, která se nikdy nevrátila — Flux ji zachytil v příštím reconciliačním cyklu - Chybnou CI/CD konfiguraci, která nasadila starý image tag — Flux se vrátil k verzi deklarované v Gitu během minut
- Výměnu nodu, která nastartovala pody s cachovanou starou konfigurací — Flux znovu aplikoval správné manifesty
3. Pomalá zpětná vazba
S push-based deploymentem vypadá zpětnovazební smyčka takto:
- Merge PR → 2. CI buildí image → 3. CI spustí Terraform → 4. Terraform plánuje (5 min) → 5. Schválení (?) → 6. Terraform aplikuje (3 min) → 7. Deployment hotový
Celkem: 10-20 minut, za předpokladu žádné fronty a žádného schvalovacího bottlenecku.
S GitOps:
- Merge PR → 2. CI buildí image → 3. CI aktualizuje Git manifest → 4. Flux reconciluje (30 sek)
Celkem: čas CI buildu plus 30 sekund. Samotný deployment je prakticky okamžitý.
4. Iluze “klikni pro deploy”
Manažeři často preferují push-based deployment, protože nabízí viditelný kontrolní bod: tlačítko v Jenkinsu, manuální schválení v GitHub Actions, “Run Pipeline” v GitLabu. Cítí se jako kontrola.
Ale co to tlačítko vlastně kontroluje? Kontroluje kdy se změna aplikuje — ne co se aplikuje. To “co” už bylo rozhodnuto, když byl PR mergnutý. Schvalovací krok je kontrola Terraform plánu, který říká “1 resource ke změně: helm_release.my_api” — což vám neřekne nic o tom, jestli je nový image tag bezpečný k nasazení. Skutečná kontrola proběhla během PR.
GitOps nahrazuje tuto divadelní kontrolu skutečnou kontrolou: Git historií. Každá změna je commit. Každý commit je kontrolovatelný, vratitelný a auditovatelný. Chcete vrátit zpět? git revert. Chcete vědět, kdo co nasadil a kdy? git log. Chcete schvalovací bránu? Použijte branch protection a povinné reviewery na GitOps repozitáři.
Tlačítko “Deploy” je bezpečnostní deka. Git log je záchranná síť.
5. State soubor: zamčený bucket, na který vývojáři nemají přístup
Terraform state soubory jsou pro deployment aplikací přítěží. Obsahují kompletní stav každého spravovaného resource — VPC ID, databázová hesla, IAM bindingy — takže přirozeně je state bucket zamčený. Vývojáři k němu nemají přístup. A neměli by mít. Ten state soubor obsahuje produkční secrets celé infrastruktury.
Ale když Helm releasy žijí ve stejném state souboru, právě jste udělali z deploymentu aplikací privilegovanou infrastrukturní operaci. Vývojář, který chce nasadit svou službu, nemůže lokálně spustit terraform plan pro ladění neúspěšného deploymentu. Nemůže inspektovat state, aby pochopil, proč si Terraform myslí, že Helm release je v určitém stavu. Je odříznut od vlastní deployment pipeline bezpečnostní hranicí, která byla navržena pro infrastrukturu, ne pro aplikace.
Výsledek: vývojáři zakládají tikety s žádostí, aby platformní tým “spustil pipeline” nebo “zkontroloval, proč je deployment zaseknutý.” Platformní tým se stává deployment bottleneckem — ne proto, že by chtěl, ale protože ho k tomu architektura nutí.
A když se něco pokazí, pokazí se to způsoby, které je těžké odladit zvenčí:
- Terraform “ví”, že Helm release je na verzi X, ale cluster má verzi Y, protože někdo ručně spustil
helm upgrade. Příštíterraform planukáže matoucí diff — nebo tiše naplánuje návrat release do zastaralého stavu. - State soubor je zamčený, protože předchozí běh pipeline vypršel. Nikdo nemůže nasadit nic, dokud někdo s přístupem k bucketu nespustí
terraform force-unlock— což samo vyžaduje infrastrukturní credentials. - Helm release je ve statu Terraformu označený jako “failed” po timeoutu, ale pody ve skutečnosti běží v pořádku. Terraform chce release vytvořit znovu od nuly. To je to bourání domu znovu.
Flux nemá žádný state soubor. Jeho stav je Git repozitář. Vývojáři mají plný přístup. Není co zamknout, není co poškodit, není co force-unlockovat ve 2 ráno.
6. Helm releasy zaseknuté v očistci
Tohle si zaslouží vlastní sekci, protože je to nejčastější hašení požárů v push-based setupech. Helm udržuje svůj vlastní release state jako Kubernetes Secrety v clusteru. Terraform udržuje samostatný pohled na tento stav ve svém state souboru. Když se tyto dva pohledy rozejdou — a rozejdou se — vstupujete do Helm očistce.
Vypadá to takto:
Error: UPGRADE FAILED: another operation (install/upgrade/rollback)
is in progressPředchozí helm upgrade vypršel (třeba readiness proba trvala příliš dlouho, třeba cluster byl pod zátěží). Helm označil release jako pending-upgrade. Terraform s tím neumí pracovat. Pipeline selže. Každý následující běh pipeline selže se stejnou chybou.
Oprava? Někdo s přístupem ke clusteru musí ručně spustit:
# Varianta A: Vrátit se na poslední úspěšný release
helm rollback my-api -n production
# Varianta B: Pokud i rollback selže, nukleární varianta
kubectl delete secret -n production -l name=my-api,owner=helm
# Pak znovu spustit pipeline a doufatTohle je hašení infrastrukturních požárů kvůli tomu, co měl být rutinní deployment aplikace. A vyžaduje to kubectl přístup k produkčnímu clusteru — přesně to, od čeho měl push-based deployment abstrahovat.
S Flux je zaseknutý HelmRelease samo-opravitelný. Flux opakuje s exponenciálním backoffem, a pokud je release skutečně rozbitý, opravíte manifest v Gitu a Flux opravu aplikuje. Žádný ruční helm rollback, žádné mazání secretů, žádná panika “kdo má kubectl přístup do produkce?” Pokud potřebujete zasáhnout, flux suspend a flux resume vám dají čistou kontrolu bez toho, abyste se dotýkali interního stavu Helmu.
7. Helm je pro operátory, ne pro vaše aplikace
Tady je nepopulární názor: většina týmů by neměla psát Helm charty pro vlastní aplikace.
Helm je package manager. Existuje proto, aby třetí strany mohly distribuovat komplexní, konfigurovatelný software — Nginx ingress controller s 200 konfiguračními možnostmi, Prometheus stack s desítkami vzájemně závislých komponent, databázový operátor s vlastními CRD. Helmův šablonovací engine ({{ .Values.replicaCount }}) dává smysl, když neznáte cílové prostředí.
Ale vy své prostředí znáte. Aplikaci jste napsali vy. Víte, kolik replik potřebuje, jaké porty vystavuje, jaké proměnné prostředí čte. Zabalit jednoduchý Deployment + Service + Ingress do Helm chartu přidává šablonovací vrstvu, která:
- Zakrývá, co se skutečně nasazuje. Výstup
helm templateje to, co dorazí do clusteru, ale nikdo ho nečte. Vývojáři editujívalues.yamla doufají, že šablony udělají správnou věc. - Vytváří indirection bez benefitu. Vaše
templates/deployment.yamlje Go šablona, která se vykreslí do… Deploymentu. Mohli jste rovnou napsat Deployment přímo. - Dělá diffy nečitelné. PR, který mění Helm hodnotu, ukáže jednořádkový diff ve
values.yaml. Revieweři nevidí skutečnou změnu manifestu bez lokálního spuštěníhelm template. - Přidává ceremonii balíčkování a verzování. Chart.yaml, verze chartů, chart repozitáře nebo OCI registry — samá ceremonie pro software, který má přesně jednoho spotřebitele: váš vlastní cluster.
Porovnejte to s plain Kustomize, který Flux používá nativně:
# kustomization.yaml — co vidíte, to se aplikuje
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
- ingress.yaml
images:
- name: my-api
newTag: v1.4.3# deployment.yaml — plain Kubernetes, žádné šablonování
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-api
spec:
replicas: 3
selector:
matchLabels:
app: my-api
template:
metadata:
labels:
app: my-api
spec:
containers:
- name: my-api
image: my-api # tag nastavený v kustomization.yaml
ports:
- containerPort: 8080
resources:
requests:
cpu: 100m
memory: 128MiŽádné šablony. Žádné values soubory. Žádné {{ if .Values.ingress.enabled }}. Manifesty jsou reálné Kubernetes YAML, které můžete přímo kubectl apply pro ladění. Kustomize řeší environment-specifické overlaye (dev/staging/prod) přes patche, ne přes šablonovací jazyk.
Použijte Helm pro: ingress controllery, cert-manager, monitoring stacky, databázové operátory — software třetích stran s komplexními konfiguračními maticemi.
Použijte Kustomize pro: vaše vlastní aplikace — kde kontrolujete zdrojový kód, konfiguraci i cílové prostředí.
Když Terraform spravuje helm_release resources pro vaše aplikace, platíte daň složitosti Helmu a Terraformu a jejich synchronizace stavu. S Flux + Kustomize píšete plain YAML a pushujete do Gitu.
8. Canary deploymenty a progressive delivery
Tady push-based model úplně selhává. Zkuste implementovat canary deployment s Terraformem a Helmem. Museli byste:
- Nasadit canary verzi vedle stabilní verze (druhý
helm_release?) - Přesměrovat procento trafficu na canary (modifikovat Istio/Linkerd VirtualService… přes Terraform?)
- Monitorovat chybovost a latenci canary (jak? Terraform nesleduje metriky)
- Postupně zvyšovat traffic pokud je zdravý, rollbacknout pokud ne (Terraform nemá tento koncept)
- Promovat canary na stabilní verzi a odstranit starou
Nic z toho není práce Terraformu. Terraform aplikuje požadovaný stav a odejde. Nemá zpětnovazební smyčku, nemá analýzu metrik, nemá progressive rollout. Skončili byste stavbou custom pipeline s desítkami kroků, sleep timery a curl příkazy na Prometheus — křehký Rube Goldbergův stroj.
Flagger — součást ekosystému Flux — byl pro tohle přímo stvořen. Je to Kubernetes operátor, který automatizuje progressive delivery: canary releasy, A/B testování a blue/green deploymenty. Integruje se s Istio, Linkerd, Contour, Nginx a dalšími service meshi a ingress controllery.
Takhle vypadá canary deployment s Flaggerem:
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: my-api
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: my-api
service:
port: 8080
analysis:
# Spustit canary analýzu každých 60 sekund
interval: 60s
# Maximální počet neúspěšných kontrol před rollbackem
threshold: 5
# Kroky canary traffic weight: 5% → 10% → 20% → 50% → 100%
maxWeight: 50
stepWeight: 10
metrics:
- name: request-success-rate
thresholdRange:
min: 99
interval: 60s
- name: request-duration
thresholdRange:
max: 500
interval: 60sKdyž pushnete nový image tag do Gitu:
Flagger sleduje reálné traffic metriky z Promethea. Pokud má canary verze vyšší chybovost nebo pomalejší odezvy, automaticky rollbackne — bez lidského zásahu, bez “kdo hlídá dashboard.” Pokud je canary zdravý přes všechny váhové kroky, promuje ho a stará verze se odstraní.
Tohle je typ deployment sofistikace, kterou Kubernetes ekosystém umožňuje nativně. Není to přilepené — je to součástí reconciliačního modelu. Flux detekuje změnu v Gitu, Flagger řídí progressive rollout, service mesh přesměrovává traffic, Prometheus poskytuje zpětnovazební signál. Každá komponenta dělá to, pro co byla navržena.
Zkuste to nacpat do terraform apply.
Kdy push-based dává smysl
Abychom byli féroví, push-based deployment není špatný ve všech kontextech:
- Non-Kubernetes cíle — deployment na VM, Lambda funkce nebo managed služby, které nemají pull-based reconciler
- Jednorázové provisioning — počáteční nastavení clusteru, vytvoření databáze, konfigurace sítě (Terraform je na tohle výborný)
- Prostředí bez perzistentních agentů — efemérní testovací prostředí, která CI vytváří a ničí
Problém není v používání Terraformu — je v používání Terraformu pro průběžný deployment aplikací do Kubernetes. Terraform je nástroj pro provisioning infrastruktury. Flux je deployment reconciler. Řeší různé problémy.
Správné rozdělení
Architektura, která funguje:
Terraform staví dům. Sítě, clustery, databáze, IAM a samotný Flux Operátor. Tyhle věci se mění zřídka — třeba měsíčně. 15minutový Terraform plan je přijatelný, když upravujete VPC peering nebo měníte velikost databáze.
Flux přestavuje nábytek. Deploymenty aplikací, aktualizace konfigurace, rotace secretů, změny škálování. Tyhle věci se mění denně. 30sekundová reconciliační smyčka není jen přijatelná — je očekávaná.
Terraform nainstaluje Flux. Flux přebírá od toho bodu. Předání je čisté: Terraform vytvoří FluxInstance CRD (jak je popsáno v našem článku o Flux Operátoru), a Flux začne reconcilovat cluster z GitOps repozitáře.
Časté námitky
“Ale my už všechno spravujeme Terraformem”
To je důvod ke změně, ne důvod zůstat. Terraform resource helm_release byl navržen pro instalaci cluster add-onů (ingress controllery, cert-manager), ne pro správu životního cyklu aplikací. Používat ho pro denní deploymenty znamená, že jste z infrastrukturního nástroje udělali deployment pipeline — a dostali to nejhorší z obou světů.
“GitOps znamená, že ztratíme přehled”
Právě naopak. terraform plan vám dává přehled když ho spustíte. Flux vám dává přehled průběžně. Vestavěné webové rozhraní Flux Operátoru ukazuje real-time stav synchronizace, historii reconciliací a zdraví resources. V kombinaci se Slack notifikacemi při selhání synchronizace získáte lepší observabilitu než CI/CD dashboard.
“A co schvalovací brány?”
Git má schvalovací brány už desítky let — říká se jim pull request reviews. Vyžadujte dva schvalovatele na vašem GitOps repozitáři. Přidejte branch protection. Použijte CODEOWNERS. Je to granulárnější než brána “klikni pro schválení Terraform plánu”, protože revieweři vidí skutečný diff manifestu, ne výstup Terraform plánu.
“Vývojáři musí rozumět Kubernetes manifestům”
Už rozumí — nebo by měli. Ať manifesty aplikuje Terraform nebo Flux, někdo je píše. Rozdíl je v tom, že s GitOps vývojáři vlastní celý životní cyklus: napsat manifest, odeslat PR, nechat ho zrevidovat, mergnout a sledovat deployment. Žádné čekání, až platformní tým “spustí pipeline.”
Jak začít
Pokud aktuálně používáte Terraform + Helm pro deployment aplikací a chcete migrovat na GitOps:
- Ponechte Terraform pro infrastrukturu. VPC, clustery, databáze, DNS — Terraform je správný nástroj.
- Nainstalujte Flux přes Terraform. Použijte Flux Operátor, jak je popsáno v našem předchozím článku. To je most.
- Přesouvejte jednu aplikaci najednou. Odstraňte
helm_releasez Terraformu, přidejte ekvivalentníHelmReleasedo vašeho GitOps repozitáře. Ověřte, že Flux reconciluje. - Smažte Helm releasy ze statu Terraformu.
terraform state rm helm_release.my_api. Nespouštějteterraform destroy— to by smazalo skutečný release. - Opakujte, dokud Terraform nespravuje jen infrastrukturu a Flux všechny workloady.
Migrace je inkrementální. Nemusíte přesunout všechno najednou. Ale každá přesunutá aplikace je o jeden důvod méně spouštět 15minutovou Terraform pipeline kvůli jednořádkové změně image tagu.
Přestaňte bourat dům. Prostě přestavte nábytek.
Titulní foto: Tamas Szabo na Unsplash.


