Zum Inhalt

Zusammenfassung der Entscheidungen der Template-Bibliothek

Die Bibliothek hält ihre Design-Entscheidungen als Decision Records im Markdown-Format MADR fest. Diese Seite fasst sie zusammen: das Problem, die Wahl und die Konsequenzen. Die vollständigen Records mit allen Optionen und Argumenten liegen im Repository der Bibliothek. Die Entscheidungen sind nummeriert; der Status ist Accepted, sofern nichts anderes steht. Wo das aktuelle Repository zeigt, wie sich eine Entscheidung auswirkt, nennt eine Zeile Im Repository das.

# Entscheidung Status
0000 Entscheidungen in MADR festhalten Accepted
0001 Repository-Struktur Accepted
0002 Gemeinsame Ressourcen bei Tests Accepted
0003 Compliance-Tests mit Azure Policy Accepted
0004 Bicep-Test-Tool: Pester Accepted
0005 Terraform-Test-Tool: Terratest Accepted
0006 Versionierung: pro Modul Accepted
0007 Forks von Upstream-Modulen für dringende Fixes Proposed (in der Praxis getestet)
0008 Parametrisierte Policies Accepted

0000: Entscheidungen in MADR festhalten

Problem. Entscheidungen zu Architektur, Code und anderen Themen brauchen ein Format und eine Struktur. Optionen. MADR 3.0.0, das Template von Michael Nygard, die Y-Statements der Sustainable Architectural Decisions, andere Templates, keine Konvention. Wahl. MADR 3.0.0. Es macht implizite Annahmen explizit, hält jede Entscheidung strukturiert fest, ist schlank, leicht zu lesen und zu pflegen, und das Projekt lebt. Konsequenz. Jede Entscheidung hat dieselbe Form (Kontext, Treiber, Optionen, Ergebnis, Konsequenzen), sodass ein späterer Leser die Argumentation nachvollziehen kann.

0001: Repository-Struktur

Problem. Die Bibliothek braucht eine vorhersehbare Struktur, auf die sich Automatisierung verlassen kann. Treiber. Einfache Struktur, die Automatisierung unterstützt. Gruppierung nach Technologie (Bicep und Terraform). Wahl. Die Terraform-Modulstruktur, angepasst: Ordner für examples, modules, pipelines und tests, jeweils nach Technologie und nach Modul unterteilt. Konsequenz. Klare Aufteilung nach Funktionalität, Technologie und Modul. Die Struktur lässt sich früh leicht ändern. Eine ähnliche Konvention nutzt das Projekt Azure Verified Modules. Siehe Repository-Struktur. Im Repository: Die Struktur ist neben den vier Ordnern der Entscheidung um scripts/, iac_accelerator/ und utils/ gewachsen.

0002: Gemeinsame Ressourcen bei Tests

Problem. Die meisten Module brauchen dieselben Abhängigkeiten (Netzwerk, Workspace, Key Vault, Storage). Sie in jedem Test zu deployen, macht die Tests langsam. Optionen. Gemeinsame Ressourcen nutzen oder alle Abhängigkeiten pro Test deployen. Wahl. Gemeinsame Ressourcen, einmal aus einem Ordner dependencies erstellt, mit ihren Daten als JSON an die Tests übergeben. Konsequenzen. Kurze Tests, ein zentraler Ort für Änderungen an den Abhängigkeiten, Wiederverwendung durch Terraform- und Bicep-Tests, und die Abhängigkeiten sind nicht Teil dessen, was die Tests prüfen. Der Preis ist mehr Komplexität und keine Editor-Autovervollständigung für die gemeinsamen Werte. Siehe Tests.

0003: Compliance-Tests mit Azure Policy

Problem. Die Templates müssen die Baselines der Plattform erfüllen (CIS, Microsoft Cloud Security Benchmark, ISO 27001), und die Bibliothek braucht eine Möglichkeit, das zu testen. Optionen. Statische Analyse des Codes (Checkov, Tfsec, Trivy, Open Policy Agent, Terrascan) oder Test der Compliance der deployten Ressourcen mit Azure Policy. Wahl. Azure Policy. Sie hängt nicht von der Sprache ab, ist einfach, und die Policies sind die einzige Quelle der Wahrheit. Konsequenzen. Die Bibliothek muss keine eigenen Regeln pflegen, und der Test ließ sich schnell bauen. Das Testen dauert länger, weil Ressourcen deployt und bewertet werden. Statische Analyse hatte False Positives (zum Beispiel bei verschachtelten Modulen und Schleifen), fehlende Checks und schwache Bicep-Unterstützung und kann später ergänzt werden, falls die Testzeit zum Problem wird. Siehe Tests. Im Repository: Jeder Test ruft dasselbe Skript für die Policy-Prüfung auf. Eine kurze Liste von Policies wird pro Modul ignoriert, jeweils mit einer Begründung (Ignorierte Policies, Bekannte Findings).

0004: Bicep-Test-Tool

Problem. Jedes Template muss deployt und die Ressourcen danach entfernt werden, mit möglichst kurzer Testzeit und wenig Implementierungsaufwand. Optionen. Pester oder eine eigene PowerShell-Schleife mit parallelen Deployments. Wahl. Pester, mit einem Skript für parallele Läufe. Es braucht wenig Aufwand, um die Ausgabe zu erfassen und einen Report für die pipeline zu erzeugen, und es liefert einen Standard für die Tests neuer Module. Konsequenzen. Die Gesamttestzeit im Report stimmt nicht, und das Log zeigt die Ausgabe erst, wenn alle Tests fertig sind. Im Repository: Ein Runner-Skript startet pro Testdatei einen Thread-Job und führt die Ergebnisse in einem JUnit-Report zusammen.

0005: Terraform-Test-Tool

Problem. Dasselbe wie bei Bicep, für Terraform. Optionen. Terratest oder das native terraform test. Wahl. Terratest. Bewährt und ausgereift, flexibel, und es führt Tests parallel aus. Konsequenzen. Parallele Tests (die CI-pipeline führt bis zu zehn gleichzeitig aus), und das Tool lässt sich später für andere Testarten nutzen. Es braucht etwas Go-Kenntnisse, um die erste Struktur aufzusetzen. terraform test war einfach und nativ, hat aber keine Parallelität, weniger Flexibilität und weniger Reife.

0006: Versionierungsstrategie

Problem. Nutzer müssen bewusst entscheiden können, wann sie upgraden, statt immer den neuesten Code zu verwenden. Optionen. Eine Version für die gesamte Lösung, eine pro Technologie oder eine pro Modul. Wahl. Pro Modul, mit Semantic Versioning und git tags wie bicep/storage_account/1.0.1, weil die anderen beiden irreführende Nummern liefern. Konsequenzen. Versionsnummern, die die Wahrheit sagen, zum Preis eines komplexeren Release-Prozesses. Eine Umfrage unter anderen Repositorys mit gemeinsamen Modulen ergab, dass Monorepos meist eine Version pro Repository verwenden und dass niemand Terraform- und Bicep-Module in einem Produkt kombiniert hat. Das Team versteht die Wahl als Experiment und erwartet, daraus zu lernen. Siehe Versionierung. Im Repository: Tags haben die Form terraform/<module>/<version> und bicep/<module>/<version>, und die Patch-Nummer setzt das Release-Skript (Tags).

0007: Forks von Upstream-Modulen für dringende Fixes

Status. Proposed. Problem. Die Module rufen Azure Verified Modules auf, die kleine Bugs haben. Fixes warten upstream oft monatelang im Review, und ein Workaround ist nicht immer möglich. Die Bibliothek will außerdem ähnliche Terraform- und Provider-Versionen über Module hinweg, was Beiträge zu vielen Modulen mit verschiedenen Ownern erfordern würde. Optionen. AVM nur als Referenz nutzen und den Code kopieren. Zu AVM beitragen und warten. AVM-Repositorys forken und pflegen. Zu AVM beitragen und in der Bibliothek Forks verwenden, wenn das Review zu lange dauert (ein Mix). Wahl. Der Mix: upstream beitragen und einen Fork des Moduls aus der Bibliothek aufrufen, wenn das Review zu lange dauert oder ein dringender Incident es braucht. Das Team will nah an AVM bleiben und etwas zurückgeben, statt die Module komplett zu pflegen. Konsequenzen. Die Bibliothek nutzt weiter AVM, gibt etwas zurück und kann einen schnellen Fix ausliefern. Eine vollständige Änderung braucht mehr Zeit und Aufwand, und das Aktualisieren der aufgerufenen AVM-Version macht weiterhin Arbeit. Das Team testet, ob das in der Praxis funktioniert. Siehe Bugs in Upstream-Modulen. Im Repository: Das Terraform-Modul für Container Instances ruft einen Fork des AVM-Moduls auf, und das Terraform-Modul für Container Apps ist davon abgerückt, ein anderes Modul zu wrappen, und besitzt jetzt seine Ressourcenlogik selbst (Modulkatalog).

0008: Parametrisierte Policies

Problem. Die Module legen die Werte fest, die eine Policy prüft, damit Nutzer keine nicht konformen Ressourcen deployen können. Manche Policies haben Parameter, die jede Plattform anders setzt, und manche haben keinen Default-Wert. Optionen. Den Default als Konstante verwenden und eine Input-Variable, wenn es keinen Default gibt. Immer eine Input-Variable verwenden. Nur die Fälle dokumentieren, die sich nicht festlegen lassen. Oder die erste Option plus Dokumentation der Fälle, in denen eine Konstante nötig ist. Wahl. Der Default-Parameterwert als Konstante im Modul. Wenn die Policy keinen Default hat, eine Input-Variable. Alle Fälle, in denen der Wert nicht durchgesetzt werden kann, werden dokumentiert. Konsequenzen. Die Module sind so sicher, wie die Standards es verlangen. Sie passen zu weniger Situationen, sodass ein Team für einen Sonderfall eventuell eine Kopie eines Moduls anlegen muss, mit Mehraufwand. Siehe Parametrisierte Policies. Im Repository: Die festen Werte stehen in der locals.tf eines Moduls (Policy-Compliance).