Einen komplexen Workflow mit parallelen Stufen und Abhängigkeiten zwischen den Stufen modellieren.
→Verwenden Sie YAML-Multi-Stage-Pipelines. Nutzen Sie das `dependsOn`-Schlüsselwort für Stufenabhängigkeiten und konfigurieren Sie parallele Jobs innerhalb der Stufen.
Warum: YAML bietet den flexibelsten, codebasierten Ansatz für komplexe Orchestrierung, überlegen gegenüber klassischen Pipelines oder der Verknüpfung separater Pipelines.
Implementieren Sie eine Bereitstellung ohne Ausfallzeiten und mit geringem Risiko für eine Web-App mit sofortiger Rollback-Fähigkeit.
→Verwenden Sie Azure App Service Bereitstellungsslots. Stellen Sie in einem Staging-Slot (grün) bereit, validieren Sie und führen Sie dann einen Slot-Swap mit der Produktion (blau) durch.
Warum: Ein Slot-Swap ist ein atomarer, nahezu sofortiger Vorgang, der den Traffic umleitet. Ein Rollback ist so einfach wie das Zurückswappen.
Referenz↗
Minimieren Sie die Pipeline-Duplizierung für zahlreiche Microservices, die gemeinsame Build-/Bereitstellungsschritte verwenden, aber spezifische Anpassungen erfordern.
→Erstellen Sie YAML-Vorlagen in einem zentralen Repository. Verwenden Sie in jeder dienstspezifischen Pipeline das `extends`-Schlüsselwort und übergeben Sie Parameter zur Anpassung.
Warum: `extends` fördert DRY-Prinzipien und erzwingt Standards, während es Flexibilität durch Parameter ermöglicht. Leistungsfähiger als Aufgabengruppen für ganze Pipeline-Strukturen.
Beschränken Sie eine Pipeline-Phase (z.B. Produktionsbereitstellung) darauf, nur bei Merges in einen bestimmten Branch (z.B. main) ausgeführt zu werden.
→Verwenden Sie eine `condition` für die Phase oder den Job. Z.B., `condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))`.
Warum: PR-Validierungs-Builds verwenden eine andere Quellbranch-Referenz (z.B. `refs/pull/...`), daher verhindert diese Bedingung die Bereitstellung während des PR-Lebenszyklus korrekt.
Anwendungen von Azure DevOps auf lokale Server hinter einer Unternehmensfirewall bereitstellen.
→Installieren Sie selbstgehostete Agents auf den lokalen Servern. Registrieren Sie sie in einem Agent-Pool in Azure DevOps.
Warum: Selbstgehostete Agents initiieren ausgehende Kommunikation zu Azure DevOps, sodass keine eingehenden Firewall-Regeln erforderlich sind. Sie können auf lokale Netzwerkressourcen für die Bereitstellung zugreifen.
Mehrere Genehmigungen für Produktionsbereitstellungen anfordern und diese auf bestimmte Wartungsfenster beschränken.
→Definieren Sie eine Azure DevOps Umgebung für die Produktion. Konfigurieren Sie Genehmigungen mit erforderlichen Genehmigern. Fügen Sie eine "Geschäftszeiten"-Prüfung als Gate hinzu, um das Zeitfenster durchzusetzen.
Warum: Umgebungen zentralisieren die Bereitstellungssteuerungen. Genehmigungen und Gates bieten eine robuste, automatisierte Richtliniendurchsetzung, bevor eine Phase ausgeführt wird.
Die Freigabe von Features für Benutzer steuern, ohne die Anwendung neu bereitzustellen, mit nahezu Echtzeit-Updates.
→Verwenden Sie Azure App Configuration für das Feature-Management. Instrumentieren Sie die Anwendung, um Flags zu lesen und ihre dynamischen Aktualisierungsfunktionen zu aktivieren.
Warum: Entkoppelt Feature-Releases von Bereitstellungen. App Configuration bietet eine zentralisierte Benutzeroberfläche und SDKs für dynamische Updates, wodurch Anwendungsneustarts vermieden werden.
Den Kubernetes-Clusterzustand deklarativ verwalten, wobei Git die einzige Quelle der Wahrheit ist und Änderungen automatisch angewendet werden.
→Stellen Sie einen GitOps-Agenten wie Flux oder ArgoCD auf dem AKS-Cluster bereit. Konfigurieren Sie den Agenten so, dass er ein Git-Repository mit Kubernetes-Manifesten überwacht und den Clusterzustand automatisch synchronisiert.
Warum: Dieses Pull-basierte Modell ermöglicht kontinuierliche Abstimmung und Drift-Erkennung, was der Kern von GitOps ist. Es ist robuster als Push-basierte `kubectl`-Pipelines.
Terraform-Zustand für die Teamzusammenarbeit verwalten, um Sicherheit zu gewährleisten und gleichzeitige Änderungen zu verhindern.
→Konfigurieren Sie das Terraform-Backend zur Verwendung eines Azure Storage Accounts. Dies bietet eine Remote-Zustandsspeicherung, wobei die Zustandssperrung über Azure Blob Lease erfolgt.
Warum: Verhindert die Beschädigung von Zustandsdateien durch gleichzeitige `apply`-Operationen und hält sensible Zustandsdaten außerhalb der Quellcodeverwaltung.
Referenz↗
In einem Monorepo eine CI-Pipeline einer Anwendung nur dann auslösen, wenn Dateien in ihrem spezifischen Verzeichnis (oder einem gemeinsamen Verzeichnis) geändert werden.
→Verwenden Sie in der YAML-Datei der Pipeline den Filter `trigger.paths.include`, um die relevanten Verzeichnisse anzugeben, z.B. `include: ['/apps/frontend/**', '/apps/shared/**']`.
Warum: Dies vermeidet unnötige Builds bei nicht zusammenhängenden Codeänderungen und spart CI-Zeit und Rechenressourcen.
Eine Testphase mit schnellen (Unit-) und langsamen (Integrations-)Tests optimieren, um schnelleres Feedback zu erhalten.
→Führen Sie Unit-Tests und Integrationstests in parallelen Jobs innerhalb derselben Phase aus.
Warum: Die parallele Ausführung liefert Unit-Testergebnisse viel schneller, während langsamere Tests gleichzeitig ausgeführt werden. Die Gesamtdauer der Phase wird durch den längsten Job bestimmt, nicht durch die Summe.
Ein Bibliothekspaket automatisch basierend auf der Commit-Historie versionieren, um die Auswirkungen von Änderungen (Breaking Change, Feature, Fix) klar zu kommunizieren.
→Integrieren Sie ein Tool wie GitVersion in die CI-Pipeline. Es analysiert Commit-Nachrichten, Branches und Tags, um automatisch eine SemVer-Version (Major.Minor.Patch) zu berechnen.
Warum: SemVer bietet eine aussagekräftige Versionierung, auf die sich Konsumenten für das Abhängigkeitsmanagement verlassen können, im Gegensatz zu Build-Nummern oder Commit-Hashes.
Eine Anwendung nacheinander in mehreren geografischen Regionen bereitstellen, mit Validierung nach jeder regionalen Bereitstellung.
→Verwenden Sie eine YAML-Pipeline mit mehreren sequenziellen Phasen, eine für jede Region, wobei `dependsOn` die Reihenfolge erzwingt. Verwenden Sie Umgebungs-Gates zwischen den Phasen zur Validierung.
Warum: Dieses ringbasierte Bereitstellungsmodell begrenzt den Schadensbereich einer fehlerhaften Bereitstellung auf eine einzelne Region und ermöglicht ein Rollback, bevor alle Benutzer betroffen sind.
Eine Pipeline zur Unterstützung eines Trunk-Based Development-Modells konfigurieren, um sicherzustellen, dass der Main-Branch immer bereitstellbar ist.
→Konfigurieren Sie einen CI-Trigger auf dem `main`-Branch. Erzwingen Sie PRs mit einer Build-Validierungsrichtlinie, die schnelle, umfassende Tests ausführt. Integrieren Sie schnelle Benachrichtigungen (z.B. an Teams/Slack) bei Build-Fehlern.
Warum: Sofortiges Feedback ist beim Trunk-Based Development entscheidend. Diese Kombination verhindert das Mergen von fehlerhaftem Code und sorgt für schnelle Behebung von Problemen.
Große Artefakte (z.B. ML-Modelle, >5GB) effizient zwischen Pipeline-Phasen übergeben.
→Laden Sie das große Artefakt in der Produzentenphase in Azure Blob Storage hoch. Übergeben Sie den Blob-URI als Ausgabevariable an die Konsumentenphase.
Warum: Azure Blob Storage ist kostengünstiger und leistungsfähiger als eingebaute Pipeline-Artefakte für Multi-Gigabyte-Dateien.
Build-Zeiten reduzieren, indem das erneute Herunterladen von Abhängigkeiten (z.B. NuGet, npm) bei jedem Lauf vermieden wird.
→Verwenden Sie die Aufgabe `Cache@2`. Definieren Sie einen Schlüssel basierend auf der Paket-Lock-Datei (z.B. `packages.lock.json`). Die Aufgabe speichert und stellt den Abhängigkeitsordner wieder her.
Warum: Kann mehrere Minuten pro Build sparen, indem aus einem schnellen, lokalen Cache wiederhergestellt wird, anstatt von externen Repositories abzurufen.
Denselben Code parallel für mehrere Ziele (z.B. verschiedene Betriebssysteme, Regionen) bauen oder bereitstellen.
→Verwenden Sie eine `strategy: matrix` im YAML-Pipeline-Job. Definieren Sie Variablen für jede Kombination, die für jeden Matrixeintrag einen Job generieren.
Warum: Eine Matrix-Strategie hält die Pipeline-Definition DRY, erstellt mehrere Job-Variationen aus einer einzigen Definition und führt sie parallel aus.
Eine Canary-Bereitstellung auf AKS implementieren, die den Traffic automatisch verschiebt und basierend auf Echtzeit-Metriken hochstuft oder zurückrollt.
→Verwenden Sie einen Progressive-Delivery-Controller wie Flagger, integriert mit einem Service Mesh (z.B. Istio) und einem Metriken-Anbieter (z.B. Prometheus).
Warum: Flagger automatisiert den gesamten Canary-Analyseprozess und bietet eine sicherere und zuverlässigere progressive Bereitstellung als manuelle Skripte.
Eine Anwendungspipeline muss ausgelöst werden, wenn sich Code in ihrem eigenen Repository ODER in einem separaten, gemeinsam genutzten Bibliotheks-Repository ändert.
→Definieren Sie in der YAML-Datei der Anwendung die gemeinsam genutzte Bibliothek unter `resources.repositories` und konfigurieren Sie einen `trigger`-Block für diese Ressource.
Warum: Erstellt eine deklarative Abhängigkeit zwischen Repositories, wodurch sichergestellt wird, dass die Anwendung immer mit den neuesten freigegebenen Komponenten neu erstellt wird.
Eine Pipeline muss temporäre Infrastruktur für Tests erstellen und sicherstellen, dass diese danach wieder zerstört wird, auch wenn Tests fehlschlagen.
→Verwenden Sie eine Multi-Stage-Pipeline mit separaten Apply- und Destroy-Phasen für IaC (Terraform/Bicep). Konfigurieren Sie die Destroy-Phase mit `condition: always()`.
Warum: Die `always()`-Bedingung garantiert, dass die Bereinigungsphase unabhängig vom Erfolg oder Misserfolg früherer Phasen ausgeführt wird, wodurch verwaiste Ressourcen verhindert werden.
Eine Produktionsbereitstellung verhindern, es sei denn, es liegt eine genehmigte Änderungsanforderung in einem ITSM-Tool wie ServiceNow vor.
→Konfigurieren Sie ein Umgebungs-Gate, das das "Query ServiceNow"-Gate aufruft, um den Status der Änderungsanforderung zu überprüfen.
Warum: Automatisiert die Integration in Unternehmens-Change-Management-Prozesse, gewährleistet Compliance ohne manuelle Übergaben.
Einen Pool selbstgehosteter Build-Agents bereitstellen, der dynamisch mit der Nachfrage skaliert, um Warteschlangenzeiten zu reduzieren und Kosten zu kontrollieren.
→Konfigurieren Sie einen Azure DevOps Agent-Pool mit einer Azure Virtual Machine Scale Set (VMSS), die automatisch basierend auf der Anzahl der ausstehenden Jobs skaliert.
Warum: VMSS-Agents kombinieren die Anpassung selbstgehosteter Agents mit der Elastizität Cloud-gehosteter Agents, wodurch Leistung und Kosten optimiert werden.
Datenbankschemaänderungen so bereitstellen, dass Datenverlust verhindert und Rollbacks unterstützt werden.
→Verwenden Sie ein Migrationstool (z.B. Flyway, DbUp). Implementieren Sie das Expand/Contract-Muster für Schemaänderungen, um die Abwärtskompatibilität zu gewährleisten.
Warum: Migrationstools bieten Versionierung und Kontrolle. Das Expand/Contract-Muster entkoppelt Anwendungs- und Datenbank-Rollbacks und ermöglicht so sicherere Bereitstellungen.
Selbstgehostete Agents laufen aufgrund angesammelter Build-Artefakte der Festplattenspeicher aus.
→Konfigurieren Sie in der Pipeline-YAML-Datei auf Job-Ebene `workspace: clean: all`.
Warum: Diese präventive Pipeline-Konfiguration löst die Grundursache, ohne manuelles Eingreifen oder kontinuierliche Infrastrukturänderungen zu erfordern.
Integrationstests erfordern für jeden Pipeline-Lauf eine isolierte Datenbankinstanz.
→Definieren Sie eine Container-Ressource (z.B. SQL Server, Postgres) als Dienst in der Pipeline-YAML-Datei. Der Test-Job kann dann eine Verbindung zu diesem ephemeren Dienst herstellen.
Warum: Bietet schnelle, isolierte und automatisch bereinigte Abhängigkeiten für Tests, verhindert Testinterferenzen und vereinfacht die Einrichtung.
Zuverlässigkeit und Leistung der Paketwiederherstellung aus öffentlichen Repositories (z.B. npmjs, nuget.org) verbessern.
→Erstellen Sie in Azure Artifacts einen Feed und konfigurieren Sie Upstream-Quellen, die auf die öffentlichen Repositories verweisen. Lassen Sie Clients Pakete aus dem Azure Artifacts-Feed konsumieren.
Warum: Der Feed speichert Pakete aus Upstream-Quellen im Cache, schützt vor Ausfällen öffentlicher Repositories und beschleunigt die Wiederherstellung häufig verwendeter Pakete.
Ein Helm-Chart in mehreren Umgebungen (Dev, Prod) mit unterschiedlichen Konfigurationswerten bereitstellen.
→Verwenden Sie separate `values-<env>.yaml`-Dateien für jede Umgebung. Verwenden Sie in der `HelmDeploy`-Aufgabe den `valueFile`-Input, um die entsprechende Datei anzugeben, und `overrideValues`, um dynamische Werte wie Image-Tags einzufügen.
Warum: Dieses Muster trennt statische Umgebungskonfiguration von dynamischen Pipeline-Variablen und hält Bereitstellungen sauber und wartbar.