TL;DR
- AI agenti moduly nepotřebují. Nemají vyhodnocovací engine - hledají text. Modul mění doslovnou hodnotu na výpočet, který v repozitáři nelze najít.
- Změřeno: v modulární variantě vrátil
grepna hledanou hodnotu 0 výsledků, přestože plán ji vypočítá správně. Ve ploché variantě 1 výsledek. - Cena abstrakce je bimodální. Komunitní moduly jsou obří (VPC modul ~36 tisíc tokenů), "entity" moduly jsou drobné - ale generují tři vrstvy propojení na jeden resource.
- Nejhorší nález: 169 odkazů na git moduly napříč repozitáři, 0 připnutých na tag nebo SHA. Sdílené moduly měly zajišťovat konzistenci - místo toho ji znemožňují.
- Nula
terraform testsouborů v pěti produkčních repozitářích. Standard nebyl nikde vynutitelný, jen doporučený. - Řešení: konzistenci nevynucujte dědičností modulů, ale kontrakty nad výstupem plánu. Ty fungují bez ohledu na strukturu a přežijí i kód psaný AI.
Otázka, kterou je potřeba položit znovu
Pravidla pro strukturu Terraform kódu vznikla v době, kdy ho psali výhradně lidé. Moduly, rozdělení do souborů, vrstvy abstrakce - to všechno optimalizuje pro lidskou znovupoužitelnost a pro oddělení stavu.
Dnes významnou část infrastrukturního kódu píše a čte AI. Průzkum Sonar z roku 2026 uvádí, že 42 % commitovaného kódu je psáno nebo asistováno AI agentem. Otázka tedy zní: platí ta pravidla pořád, když hlavním čtenářem kódu přestává být člověk?
Neptali jsme se na to teoreticky. Postavili jsme kontrolovaný experiment a pak změřili pět reálných produkčních repozitářů napříč dvěma cloudy.
Metodika
Analyzovali jsme pět produkčních Terraform kódových bází ve správě jednoho týmu: statický web na AWS, AWS landing zone s organizacemi, aplikační platformu na AWS EKS, aplikační platformu na Azure AKS a globální síťovou infrastrukturu na Azure. Měření probíhalo staticky nad zdrojovým kódem a nad uloženými plány - žádné volání do cloudu, žádná změna infrastruktury.
Anonymizace: repozitáře označujeme A-E. Neuvádíme názvy organizací, domény, IP adresy, identifikátory předplatných ani účtů. Všechny ukázky kódu v článku jsou syntetické.
Jak AI agent doopravdy čte Terraform
Agent nemá jazykový server, nemá index symbolů a nedokáže spolehlivě vyhodnotit HCL výraz v hlavě. Má tři operace: najdi soubory podle vzoru, najdi řetězec v textu, přečti rozsah řádků.
To má jeden zásadní důsledek, který se v diskusích o struktuře kódu nikdy neobjevuje: hledaná hodnota často v repozitáři vůbec neexistuje jako text.
A u Terraformu je to horší než u jiných jazyků. Recenzované benchmarky se shodují:
- IaC-Eval (NeurIPS 2024): GPT-4 dosáhl 19,4 % úspěšnosti na 458 AWS Terraform úlohách oproti 86,6 % na srovnatelných Python úlohách - zhruba čtyřikrát horší výsledek.
- DPIaC-Eval (FSE 2026): šest špičkových modelů dosáhlo 20,8-30,2 % úspěšného nasazení na první pokus u 153 reálných úloh; po zapnutí compliance kontrol kleslo číslo na 8,4 %.
- TerraFormer (ICSE 2026, 17 modelů): příčinou je, že HCL je v trénovacích datech zastoupen podstatně méně než YAML a JSON z Kubernetes, CloudFormation a Ansible.
Poctivá poznámka k číslům
Údaj o GPT-4 pochází z roku 2024 a dnešní modely jsou v absolutních číslech lepší. Robustní zjištění není absolutní hodnota, ale relativní propast mezi infrastrukturním a aplikačním kódem. Ta je strukturální: méně trénovacích dat, žádný typový systém a nemožnost ověřit správnost spuštěním kódu.
Experiment: co stojí jedna vrstva abstrakce
Postavili jsme dvě konfigurace, které vytvářejí bajt po bajtu identickou
infrastrukturu. Jedna je plochá, druhá má dvě úrovně modulů s výchozími
hodnotami v variables.tf. Pak jsme položili otázku, kterou agent
v praxi dostává: "jaký CIDR dostane produkční privátní podsíť a je zapnutá
ochrana proti smazání databáze?"
| Metrika | Plochá konfigurace | Modulární (2 úrovně) |
|---|---|---|
grep na hledaný CIDR |
1 výsledek | 0 výsledků |
| Souborů k přečtení | 1 | 8 |
| Bajtů k přečtení | 557 | 2 265 |
| Jak se získá odpověď | přečtení literálu | výpočet přes 3 výchozí hodnoty |
Obě varianty vytvoří 10.20.16.0/20 a deletion_protection = true. Jen v jedné z nich to lze najít.
Modulární varianta je podle konvenčních měřítek lepší inženýrství. Je to zároveň
varianta, ve které agent hledající text nenajde nic a musí hodnotu dopočítat
přes cidrsubnet(), coalesce() a contains() -
tedy operací, ve které jsou jazykové modely nejméně spolehlivé.
Dvě konstrukce, které z abstrakce dělají past
1. Výchozí hodnoty v variables.tf modulu. Efektivní
hodnota leží v souboru, který u volání modulu nikdo nečte.
2. Počítaná jména a rozsahy (cidrsubnet,
format, skládané identifikátory). Výsledek není dohledatelný -
doslova nula výskytů, jak jsme naměřili.
Terénní měření: pět produkčních repozitářů
Experiment je jedna věc, realita druhá. Tady je pět skutečných kódových bází, které běží v produkci:
| Repozitář | Cloud | Velikost | Resources | Volání modulů | Volání / resource |
|---|---|---|---|---|---|
| A - statický web | AWS | ~8 tis. tokenů | 43 | 0 | 0,0 |
| B - landing zone | AWS | ~22 tis. | 52 | 26 | 0,5 |
| C - aplikační platforma | AWS | ~48 tis. | 113 | 11 | 0,1 |
| D - aplikační platforma | Azure | ~39 tis. | 44 | 73 | 1,7 |
| E - globální síť | Azure | ~38 tis. | 32 | 99 | 3,1 |
Velikost je odhad v tokenech (bajty ÷ 4). Resources = přímo deklarované resource bloky.
Nález 1: poměr propojení k obsahu
Sloupec "volání na resource" je nejužitečnější číslo v celé tabulce. Říká, kolik z konfigurace je instalatérství a kolik podstata.
Repozitář E má 99 volání modulů a 32 přímo deklarovaných resources - tedy tři vrstvy propojení na každý skutečný kus infrastruktury. Ne proto, že by to někdo pokazil; vznikl tak logickým dovedením myšlenky "všechno je znovupoužitelný modul" do důsledku. Přesně tohle lidé myslí, když mluví o špagetovém kódu v Terraformu - jenže obvyklá diagnóza ("málo modularizace") je tady přesně opačná.
Nález 2: cena modulu je bimodální
Tady nás data překvapila a stojí za to to říct nahlas, protože to vyvrací zjednodušené "moduly jsou drahé". Změřili jsme skutečnou velikost modulů, které se používají:
variables.tf, tedy rozhraníKomunitní moduly typu VPC nebo EKS jsou obří - rozhraní jednoho takového modulu je větší než celá infrastruktura menšího projektu. Naproti tomu drobné "entity" moduly v repozitáři E jsou dohromady jen 0,3násobek kořenové konfigurace; tam nebolí velikost, ale počet skoků.
Správná metrika tedy není "moduly ano/ne", ale kolik tokenů a kolik skoků stojí zodpovězení jedné otázky. Obě selhání - obří modul i les drobných modulů - vedou ke stejnému výsledku.
Nález 3: sdílené moduly bez neměnné verze
Tohle je nejzávažnější zjištění celé analýzy. Repozitáře D a E čerpají moduly ze sdílených git knihoven - přesně ten mechanismus, který má zajišťovat konzistenci mezi projekty a globální infrastrukturou.
Všechny reference měly tvar ?ref=master nebo mířily rovnou na
vývojovou větev. To znamená, že se infrastruktura může změnit,
aniž by se ve vašem repozitáři změnil jediný řádek. Dva plány spuštěné
v různý čas z identického commitu mohou vytvořit odlišnou infrastrukturu.
Pro AI agenta je to fatální: přečte volání modulu, přečte modul a odvodí závěr, který může být zítra neplatný. Ale problém není v agentovi - ani člověk nemá jak zjistit, co se skutečně nasadí.
Kontrast, který ukazuje řešení
Repozitář C používá komunitní moduly z registru s omezením verze
(version = "~> 5.0"). Není to neměnné připnutí, ale je to
o řád lepší než pohyblivá větev - a hlavně je to viditelné
v místě volání, takže agent i člověk vědí, s čím pracují.
Nález 4: nula vynutitelných kontraktů
Napříč všemi pěti repozitáři jsme našli nula souborů
.tftest.hcl. Nativní testovací framework je v Terraformu
od verze 1.6 a umí ověřit plán offline, bez cloudu a bez stavu.
Důsledek: standardy existují jako dohoda a jako code review, ne jako pravidlo. V týmu, kde kód píší lidé, to bolí pomalu. V týmu, kde významnou část kódu generuje AI, to přestává fungovat okamžitě - dokumentované chybové vzorce generovaného IaC jsou totiž přesně ty, které code review přehlíží: chybějící šifrování, příliš široká oprávnění, zastaralé atributy.
Rozhodovací pravidlo pro moduly
Z dat vyplývá pravidlo, které je použitelné a nezávislé na módě:
"Modul musí být ospravedlněný opakováním (použije se třikrát a víc) nebo hranicí stavu. Nikdy estetikou."
| Situace | Doporučení | Proč |
|---|---|---|
| Do ~30 resources v jednom stavu | Ploché soubory, literální hodnoty | Modul přidá skoky a nic nevrátí. Jeden soubor na téma. |
| Vzor se opakuje 3× a více | Modul, ale plochý strom | Alternativou je copy-paste drift, který je horší. |
| Odlišný životní cyklus nebo blast radius | Oddělený stav, ne modul | Hranice stavu je skutečná hranice, modul je jen syntaxe. |
| "Aby soubory nebyly dlouhé" | Nedělat | Přesně tak vzniká poměr 3 volání na resource. |
| Tenký obal nad jedním resource | Nedělat | Nezvyšuje úroveň abstrakce, jen přidává soubor navíc. |
Je to i oficiální doporučení HashiCorpu: držet strom modulů plochý, preferovat kompozici před hlubokým vnořováním a nepsat moduly, které jen obalují jediný typ resource.
Konzistence bez špagetového kódu
Tady je jádro věci. Většina týmů se snaží držet konzistenci dědičností zdrojového kódu: všechny projekty importují stejný modul. Data ukazují, kam to vede - 169 nepřipnutých odkazů a poměr 3 volání na resource.
Funkční model je jiný: sdílený modul určuje, jak je konfigurace napsaná. Kontrakt určuje, co z ní vznikne. Vynucujte to druhé.
Vrstva 1: kontrakty nad výstupem plánu
terraform test s command = plan běží offline,
bez přístupu do cloudu a bez stavu. Projekty pak mohou být strukturované různě,
ale nemohou se lišit v tom, na čem záleží:
# tests/guardrails.tftest.hcl
variables {
environment = "prod"
vpc_cidr = "10.20.0.0/16"
}
run "prod_database_is_hardened" {
command = plan
assert {
condition = output.db_settings.deletion_protection == true
error_message = "produkční databáze musí mít ochranu proti smazání"
}
assert {
condition = output.db_settings.backup_retention >= 30
error_message = "produkční databáze musí držet zálohy alespoň 30 dní"
}
assert {
condition = output.db_settings.storage_encrypted == true
error_message = "úložiště produkční databáze musí být šifrované"
}
}
run "dev_is_not_over_provisioned" {
command = plan
variables { environment = "dev" }
assert {
condition = output.db_settings.instance_class == "db.t4g.medium"
error_message = "dev má používat levnou instanci"
}
}
Ověřeno v praxi: oba testy proběhnou offline za sekundy, bez credentials.
Vrstva 2: policy nad JSON plánem napříč projekty
Jeden policy repozitář aplikovaný na plán každého projektu. Tohle je jediný mechanismus konzistence, který přežije rozdílné struktury, rozdílné verze modulů i kód generovaný AI - protože kontroluje výsledek, ne autorství:
terraform show -json tfplan > plan.json
# příklad kontroly nad rozbaleným plánem
conftest test --policy ./platform-policies plan.json
Ověřili jsme to na reálném plánu: kontrola prošla celou infrastrukturou,
aniž by přečetla jediný .tf soubor nebo věděla, jak je projekt
strukturovaný. Přesně to je potřeba, když má každý tým jiný layout.
Pokrývá to i zdokumentované chybové vzorce AI generovaného IaC, na které
terraform validate ani plan z principu neupozorní:
zástupné znaky v IAM politikách, chybějící šifrování, veřejné ACL,
0.0.0.0/0 a natvrdo zapsané hodnoty.
Vrstva 3: neměnné verze modulů
Nejlevnější oprava s nejvyšším dopadem. Sdílený modul bez neměnné reference není konzistence, ale sdílená nestabilita:
# ŠPATNĚ - infrastruktura se mění bez změny ve vašem repozitáři
module "role_assignment" {
source = "git::ssh://git@example.com/platform/modules.git//authorization/role_assignment?ref=master"
}
# ŠPATNĚ - odkaz na rozpracovanou větev v produkci
module "subnet" {
source = "git::ssh://git@example.com/platform/modules.git//network/subnet?ref=fix/symlinks"
}
# SPRÁVNĚ - neměnný tag, viditelný v místě volání
module "role_assignment" {
source = "git::ssh://git@example.com/platform/modules.git//authorization/role_assignment?ref=v2.4.0"
}
Pravidlo do CI: odmítni plán, pokud jakýkoli ref= není tag nebo SHA.
Vrstva 4: dejte agentům orákulum místo zdrojáku
Nenuťte agenta hodnoty odvozovat - nechte ho je zjistit. Tohle patří do
AGENTS.md nebo CLAUDE.md v každém infra repozitáři:
# Terraform: NIKDY neodvozuj hodnoty čtením modulů. Zjisti je.
terraform show -json tfplan | jq '.planned_values' # všechny rozbalené hodnoty
echo 'cidrsubnet("10.20.0.0/16", 4, 1)' | terraform console
terraform console -var-file=prod.tfvars # ověření výrazu
# NIKDY nesypej celý JSON plánu do kontextu - je 4,5× větší než HCL,
# ze kterého vznikl. Používej jq výřez.
| Výřez plánu | Velikost | Tokenů |
|---|---|---|
| Celý JSON plánu | 150 900 B | ~37 700 |
Jen resource_changes | 47 186 B | ~11 800 |
| Shrnutí změn (adresa + akce + typ) | 2 263 B | ~600 |
Naměřeno na reálném plánu o 20 resources. Rozdíl mezi celým plánem a shrnutím je 60násobný.
Co s tím udělat tento týden
Pořadí podle poměru přínos/práce
ref= ve sdílených modulech a připněte je na tagy. Přidejte CI kontrolu, která pohyblivé reference odmítne.
.tftest.hcl kontrakty na pravidla, na kterých vám opravdu záleží.
AGENTS.md instrukci, aby agent hodnoty zjišťoval přes plán a konzoli, ne odvozoval.
variables.tf modulů do místa volání, nebo je zveřejněte jako výstupy.
Často kladené otázky
Potřebují AI agenti Terraform moduly?
Ne. Moduly optimalizují znovupoužitelnost pro člověka a oddělení stavu, ne čitelnost pro agenta. Agent hledá text; modul mění doslovnou hodnotu na výpočet rozprostřený přes několik souborů. Vyplatí se při opakování (třikrát a víc) nebo při oddělení stavu - nikdy kvůli estetice.
Máme refaktorovat existující modulární kód?
Většinou ne - přepisování funkční infrastruktury nese vlastní riziko. Prioritou je připnout verze, doplnit kontrakty a policy a zveřejnit počítané hodnoty jako výstupy. Rozpouštění modulů má smysl jen tam, kde poměr volání na resource výrazně přesahuje jedna.
Znamená to, že máme psát jeden obří soubor?
Ne. Rozdělení do souborů podle tématu (network.tf, iam.tf,
storage.tf) je pro agenty ideální - dá se cíleně vyhledávat
a číst po částech. Problém není počet souborů, ale počet skoků
mezi nimi kvůli abstrakci.
Jak držet konzistenci mezi projekty a globální infrastrukturou?
Kontrakty nad výstupem plánu plus policy as code, ne dědičnost modulů. Sdílený modul určuje, jak je konfigurace napsaná; kontrakt určuje, co z ní vznikne. Jen to druhé je vynutitelné napříč týmy s různými layouty.
Nahradí AI potřebu platform týmu?
Naopak. Čím víc infrastrukturního kódu vzniká rychle, tím důležitější je někdo, kdo vlastní kontrakty, policy a verzování. Role se posouvá od psaní konfigurace k definování a vynucování pravidel.
Klíčové poznatky
- Agenti nepotřebují moduly, potřebují dohledatelné hodnoty. Naměřeno: 1 výsledek versus 0 při hledání téhož údaje.
- Poměr volání modulů na resource je nejlepší detektor špagetového kódu. Nad 1,0 je konfigurace převážně propojování.
- Cena abstrakce je bimodální - obří komunitní moduly i les drobných entit vedou ke stejnému problému, jen z opačné strany.
- Sdílený modul bez neměnné verze není konzistence. 169 odkazů, 0 připnutých - a přitom to měl být hlavní nástroj standardizace.
- Vynucujte výsledky, ne strukturu.
terraform testa policy nad JSON plánem fungují napříč layouty a přežijí AI generovaný kód. - Nula testů v pěti produkčních repozitářích je běžný stav, ne výjimka. To je příležitost, ne ostuda.
Související články
Zdroje a metodika
- Vlastní měření: pět produkčních Terraform kódových bází (AWS a Azure), statická analýza zdrojového kódu a uložených plánů, červenec 2026. Data anonymizována.
- IaC-Eval (NeurIPS 2024) - benchmark 458 AWS Terraform scénářů.
- DPIaC-Eval (FSE 2026) - 153 reálných úloh, šest špičkových modelů.
- TerraFormer (ICSE 2026) - vyhodnocení 17 modelů, analýza zastoupení HCL v trénovacích datech.
- Sonar, State of Code 2026 - podíl kódu psaného nebo asistovaného AI.
- Dokumentace HashiCorp: vývoj modulů a kompozice,
terraform test, JSON formát plánu.
Chcete vědět, jak na tom je vaše infrastruktura?
Děláme audity Terraform kódových bází - poměr abstrakce, verzování modulů, vynutitelnost standardů a připravenost na práci s AI agenty. Výstupem je konkrétní seznam kroků, ne prezentace.
Domluvit audit