Bekannte Probleme¶
Beim Schreiben dieses Leitfadens gefundene Einschränkungen, mit Workarounds. Wie du mit einem Incident umgehst, steht unter Incident-Management.
Verifizierungsstatus (15. Oktober 2026)
Die Punkte unter Behoben (Merge ausstehend) wurden auf einem Arbeits-Branch behoben, während der Leitfaden geschrieben wurde, sie sind aber
noch nicht in main oder release/v4.12 von xms-cloud-platform-code. Geprüft auf main (0426660) und release/v4.12
(534ff80):
dev/dev.ps1hat noch das alteValidateSet(Deploy,Unlock,DeploySpoke, …), während seine HandlerHubDeploy,HubUnlock,SpokeDeploy, … heißen.-Action HubDeploywird von der Parametervalidierung abgelehnt, und-Action Deployfindet keinen Handler. Die spoke-Handler sind fest aufpatrick/canvas_nonprod_dev_str.jsonverdrahtet. Bis der Fix gemergt ist, ruf die Funktionen direkt auf (siehe Einen einzelnen Layer lokal ausführen)..azure-devops/pipelines/spoke-destroy.yamlzerstört noch in der Reihenfolge dev → prd.- Das spoke-Schema
environmentist noch einenum(keinacc<n>-Muster).
Behandle jede Zeile unter Behoben (Merge ausstehend) als offen, bis du sie in der von dir gepinnten Version geprüft hast.
Behoben (Merge ausstehend)¶
| Problem | Fix |
|---|---|
Das spoke-Apply verwendete den Literal-String spoke_${stateKeyId}.tfstate als State-Key, weil einfache Anführungszeichen die Interpolation in PowerShell verhindern. |
Invoke-XebiaMcpSpokeApply.ps1 verwendet jetzt doppelte Anführungszeichen. Ein Unit-Test wurde ergänzt. |
Das spoke-Schema lehnte nummerierte Abnahme-Umgebungen (acc1, acc2, …) ab, obwohl die Pipeline sie unter acc gruppiert. |
spokeschema.json: environment akzeptiert jetzt dev, tst, test, acc, acc<n>, prd, prod, shrd und shared (Regex-Muster). |
dev/dev.ps1 listete Aktionsnamen (Deploy, Unlock, DeploySpoke, …) auf, für die es keinen Handler gab, sodass die hub-/spoke-Aktionen nicht laufen konnten. Die spoke-Datei war fest verdrahtet. |
Das ValidateSet passt jetzt zu den Handlern (HubDeploy, SpokeDeploy, …), und ein Parameter -SpokeFilePath wurde ergänzt. |
Azure-DevOps-hub-Stage: Die Bedingung des firewall-Jobs las job_deploy_1_connectivity_apply, was keine seiner Abhängigkeiten war. Die identity- und management-Jobs hatten dasselbe Problem in ihrem Single-Region-Fallback. |
stage-mcp-hub.yaml: Die drei Level-3-Jobs hängen jetzt von beiden connectivity-Apply-Jobs ab und verwenden dieselbe Bedingung, passend zum GitHub-Workflow. |
Azure DevOps spoke-destroy.yaml zerstörte in der Reihenfolge dev → prd, obwohl der Header (und der GitHub-Workflow) prd → dev angibt. |
Die Reihenfolge ist jetzt prd → acc → tst → dev. Konfigurations-Repositories haben eine eigene Kopie dieser Entry-Datei, prüfe also deine. |
Get-XebiaOrderedDeployments dokumentierte 3 Level und lehnte -Level 4 (postdeployment) ab. |
Hilfetext und ValidateSet aktualisiert. |
| hub-Genehmigungen: Der Analyse-Schritt behielt nur die Plan-Zusammenfassung der letzten Region, sodass Änderungen in anderen Regionen ohne Genehmigung durchgehen konnten. | Invoke-XebiaHubAnalyseAction.ps1 aggregiert jetzt alle Plan-Dateien. Ein Unit-Test wurde ergänzt. |
Der Azure-DevOps-hub-Analyse-Job lud <layer>_$(region)_<level>_json herunter, aber dieser Job ist nicht als Matrix definiert, sodass $(region) undefiniert war. |
job-mcp-hub.yaml lädt jetzt <layer>_*_<level>_json/** herunter und analysiert jede Region, passend zu GitHub. |
Offen: Pipelines¶
| Problem | Auswirkung | Workaround |
|---|---|---|
Entry Pipelines tragen mode und whatIf fest ein. Im Referenz-Konfigurations-Repository verwenden spoke.yaml / spoke-destroy.yaml whatIf: true und hub.yaml verwendet mode: Apply, whatIf: false. |
spokes werden nur geplant; der hub wendet ohne Genehmigung an. | Bearbeite die Entry-Dateien oder stelle die Parameter bereit (so geht's). |
Der spoke-subscription-Layer wird während Plan angewendet, auch mit whatIf: true. |
Ein reiner Plan-Lauf kann den subscription-Layer trotzdem ändern. Derzeit erstellt dieser Layer nur einen Subscription-Alias, wenn azureSubscriptionId leer ist. |
Setze immer azureSubscriptionId. |
Das Anlegen von Subscriptions braucht CSP-Abrechnungswerte (xmscsp_*), die die Pipeline als leere Strings übergibt. |
Die spoke Pipeline kann keine Subscriptions anlegen. | Lege die Subscriptions vorher an (Neuer spoke). |
| Spoke destroy kündigt die Subscription nie und setzt weder deren Tags noch Namen zurück. | Die Subscription läuft weiter. | Außerbetriebnahme von Hand (spoke löschen). |
Ein spoke, dessen environment nicht in der environments-Liste der Pipeline steht, lässt den Config-Test fehlschlagen, wenn der Glob ihn trifft (zum Beispiel shared mit den Standardwerten dev/tst/acc/prd). |
Ein breiter spokeGlob schlägt fehl. |
Verwende einen engen spokeGlob oder füge shared zu environments hinzu. |
Die Layer ghrunners und policy_exemptions sind nicht Teil der aktuellen hub-Orchestrierung. |
Ihre tfvars haben keine Wirkung. | Policy-Ausnahmen laufen über postdeployment (Policy-Zuweisungen). |
ADR-0009 sagt, der firewall-Plan bleibe nebenläufig, aber Invoke-XebiaHubPlanAction.ps1 plant die firewall ebenfalls mit -parallelism=1. |
Langsamere firewall-Pläne. | Keiner nötig. |
Offen: spokes¶
| Problem | Auswirkung | Workaround |
|---|---|---|
Das azurerm_management_group_subscription_association des spoke hat einen count, der von einer externen Prüfung abhängt: "Ist die Subscription bereits in der Gruppe?" (spoke-canvas/modules/subscription_managementgroup/main.tf). Nach dem ersten Apply liefert die Prüfung true, sodass der nächste Plan die Association zerstören will. Der Lauf danach erstellt sie neu. |
Routinemäßige spoke-Wiederholungsläufe können die Subscription aus ihrer management group heraus und wieder zurück verschieben. | Lies jeden spoke-Plan. Wende kein Destroy dieser Ressource an. Ein Code-Fix ist nötig: die Association einmal festlegen oder importieren, statt einen datengesteuerten count zu verwenden. |
Die spoke-Genehmigung (Approve*-Modi) wird pro spoke-Umgebungs-Stage über jede im Lauf heruntergeladene Plan-Zusammenfassung entschieden, einschließlich der Pläne des subscription-Layers und früherer Umgebungen. |
Genehmigungsabfragen sind breiter als ein einzelner spoke. | Führe einen spoke pro Lauf aus (spokeGlob = eine Datei). |
| hub-Config-Tests (firewall, App Gateway, WAF, DNS-Baseline) laufen auch im spoke-Prepare-Schritt. | Ein kaputtes hub-JSON blockiert spoke-Deployments. | Halte das hub-JSON auf dem Branch, von dem du deployst, gültig. |
| Keine Pipeline legt den spoke-State-Blob-Container an. | Der erste spoke-Lauf schlägt am Backend fehl. | Lege den Container von Hand an (Bootstrap). |
Ein mit Purge Protection zerstörter Key Vault wird beim erneuten Anlegen wiederhergestellt (recover_soft_deleted_key_vaults = true). |
Alte Secrets kommen zurück. | Beachte das, wenn du einen gelöschten spoke neu anlegst. |
Offen: Entry-Dateien des Referenz-Konfigurations-Repositorys¶
Diese wurden im Referenz-Konfigurations-Repository gefunden und können auch bei deinem zutreffen:
| Problem | Auswirkung | Workaround |
|---|---|---|
pipelines/hub-destroy.yaml und pipelines/spoke-destroy.yaml verwenden template: ./templates/stage-mcp-*.yaml@mcp-code und übergeben agentPoolMdp nicht. Die anderen Entries verwenden .azure-devops/pipelines/templates/…@mcp-code und übergeben es. |
Die destroy Pipelines lassen sich wahrscheinlich nicht kompilieren. | Verwende denselben Template-Pfad und dieselben Parameter wie hub.yaml / spoke.yaml. |
spoke.yaml zielt auf environments/prod/mcp.json; spoke-destroy.yaml (ADO und GitHub) zielt auf environments/canary/mcp.json. |
Ein mit spoke deployter spoke kann nicht mit spoke-destroy zerstört werden. |
Richte beide auf dieselbe mcp.json oder füge einen Umgebungsparameter hinzu. |
spoke-destroy.yaml läuft dev → prd. |
Die Destroy-Reihenfolge ist nicht die Umkehrung der Deploy-Reihenfolge. | Verwende prd → acc → tst → dev, wie es die Entry-Datei des Code-Repositorys jetzt tut. |
tfvars-Pfade sind ab dem Repository-Root geschrieben (zum Beispiel ip_group_json_file_relative_path = "environments/prod/gwc/ip_groups/"), aber Terraform hängt sie an config_path an, das bereits <repo>/environments/prod ist (wie Pfade aufgelöst werden). |
Im Code verifiziert: config_path ist der Ordner, der mcp.json enthält (Resolve-XebiaMcpConfiguration übergibt Split-Path -Parent des mcp.json-Pfads). environments/prod/gwc/ip_groups/ wird daher zu <repo>/environments/prod/environments/prod/gwc/ip_groups/ aufgelöst, den es nicht gibt, sodass die firewall-, Policy- und App-Gateway-Ordner keine Dateien finden. |
Mache die Pfade relativ zum Umgebungsordner, zum Beispiel gwc/ip_groups/ und policies/definitions, wie in config/Demo/canary des Code-Repositorys. Plane zuerst und bestätige, dass die erwarteten Ressourcen keine Änderungen zeigen. |
postdeployment.auto.tfvars setzt security_contacts = {…}. Der aktuelle Code deklariert security_contact_email (String, Standard CustomerSupport@Xebia.com). |
Die Einstellung wird nur mit einer Warnung ignoriert, und der Standardkontakt wird verwendet. | Setze security_contact_email. |
Offen: Konfiguration und Validierung¶
| Problem | Auswirkung | Workaround |
|---|---|---|
Ein falscher Ordnerpfad in tfvars lässt fileset() ohne Fehler nichts zurückgeben. |
Der Plan löscht alle Ressourcen aus diesem Ordner. | Lies die Plan-Zusammenfassung; siehe relative Pfade. |
| Keine Prüfungen auf IP-Überlappung oder -Enthaltensein bei spoke-Adressbereichen. | Überlappende spokes werden ohne Warnung deployt. | Pflege einen IP-Plan und prüfe ihn im pull request. |
Die Associations von management_group_structure.*.subscription_ids werden über die Listenposition indiziert, mit ignore_changes. |
Das Entfernen oder Umsortieren von Einträgen verschiebt die falsche Subscription. | Nur anhängen (Details). |
Spoke-Entra-ID-Gruppen ignorieren spätere Änderungen an owners / members. |
Das Bearbeiten von ad_*Members nach der Erstellung hat keine Wirkung. |
Siehe spoke ändern. |
Das spoke-Schema lehnt Keys ab, die das Terraform liest: extensions.github, extensions.integrations, extensions.apim.workspace, extensions.eventhub.eventhubs, die Service-Bus-Gruppenfelder und azdo: null. |
Diese Features können den Config-Test nicht bestehen. | Lass azdo weg, statt es auf null zu setzen. Die Extension-Features brauchen ein Schema-Update im Code-Repository. Was jede Extension tut: Spoke-Erweiterungen. |
App-Gateway-Config-Tests prüfen nur Dateien mit dem Namen application_gateway_hub.json. |
Andere Gateway-Dateien werden nicht validiert. | Verwende diesen Dateinamen. |
Es gibt zwei auseinandergelaufene Kopien der firewall-, App-Gateway- und WAF-Schemas: scripts/pr-validation/schemas/ und src/Xebia.Mcp/Files/json/. Die Pipelines verwenden die src-Kopie. Die Validatoren scripts/pr-validation/*.ps1 erwarten ein environments/{CANARY,PROD}-Layout und werden von keiner Pipeline aufgerufen. |
Validator-Ergebnisse weichen ab. | Vertraue den Config-Tests der Pipeline (src-Kopie). |
Der firewall-Config-Test für "sich gegenseitig ausschließende Ziele bei Application Rules" prüft Keys, die in Application Rules nicht existieren (fqdn_targets). |
Diese Prüfung schlägt nie fehl. | Prüfe Application Rules von Hand: Verwende destination_fqdns oder destination_fqdn_tags. |
Beispieldateien für Policy-Ausnahmen (*.jason) verwenden policy_definition_reference_ids. Das Modul liest policy_definition_ids. |
Eine Beispieldatei in .json umzubenennen funktioniert nicht wie erwartet. |
Verwende policy_definition_ids (Policy-Ausnahmen). |
| JSON-Zuweisungen an management groups müssen auf ein Policy-Set verweisen. | Eine einzelne Definition schlägt zur Plan-Zeit fehl. | Verpacke sie in eine initiative. |
Der Azure-Anzeigename einer benutzerdefinierten initiative ist ihr name (display_name = each.value.name). |
properties.displayName wird ignoriert. |
Wähle gut lesbare initiative-Namen. |
| Eine nicht deklarierte Variable in einer tfvars-Datei ist nur eine Terraform-Warnung, sodass Tippfehler und umbenannte Variablen stillschweigend ignoriert werden. | Die Einstellung hat keine Wirkung. | Prüfe Variablennamen gegen infra/deploy/<layer>/variables*.tf. |
Offen: Application Gateway und WAF¶
| Problem | Auswirkung | Workaround |
|---|---|---|
policy_settings von WAF policies steht in ignore_changes. |
Änderungen an Modus oder Limits nach der Erstellung werden nicht deployt. | Ändere sie im Portal und halte es fest, oder lege eine neue Policy an. |
create_application_gateway wird im Template auf true überschrieben. |
Nur use_application_gateway_module schaltet das Gateway. |
Verwende use_application_gateway_module. |
Das WAF-Template legt eine eigene resource group an (rg-<company>-agw-…) und ignoriert die übergebene Gateway-resource-group (rg-<company>-appgw-…). |
WAF policies und das Gateway liegen in unterschiedlichen resource groups. | Bilde firewall_policy_id aus der -agw--resource-group. |
Im Gateway-JSON wird identity_ids ignoriert (die Template-Identität wird immer verwendet), und kv_name, pip_name, uai_name und fips_enabled werden nicht gelesen. |
Das Bearbeiten hat keine Wirkung. | – |
Zertifikatspasswörter werden mit azapi_resource .properties.value gelesen. Mit azapi 2.x kann dieser Pfad zu null aufgelöst werden. Nicht verifiziert. |
Passwortgeschützte PFX-Secrets können fehlschlagen. | Speichere Zertifikate ohne separates Passwort-Secret (Key-Vault-Zertifikatsimport). |
Betriebliche Fallstricke¶
Sie stammen aus Incidents und Post-Mortems laufender Plattformen. Sie beschreiben, wie sich die Plattform im Betrieb verhält, nicht Defekte in einer einzelnen Datei. Prüfe sie gegen die Version, die du fixiert hast.
| Fallstrick | Auswirkung | Was zu tun ist |
|---|---|---|
| Eine große firewall-Änderung (viele Rule Collections gleichzeitig hinzugefügt und entfernt) läuft in das Update-Limit für Regelsätze: Azure akzeptiert keine gleichzeitigen Updates mehrerer Regelsätze, daher staut sich der Apply und endet in einem Time-out, und einige Rule Collections existieren in Azure, aber nicht im state. | Der nächste Lauf schlägt mit „already exists“ fehl. Der Verkehr kann unterbrochen werden, solange Regeln fehlen. | Teile die Änderung in mehrere kleinere pull requests. Behandle einen Time-out auf canary als Grund anzuhalten. Füge neue Regeln hinzu, bevor du alte entfernst. Behebe state-Unterschiede mit terraform import, nicht durch Zerstören von Produktionsregeln (Post-Mortems). |
Der firewall-Layer wird mit -parallelism=1 angewendet, daher dauert eine große Änderung lange (Firewallregeln). |
Ein langer Lauf kann das Apply-Time-out überschreiten. | Halte Änderungen klein. |
| Eine zusätzliche WAF-Einstellung, etwa die Inspektion des Request Body, ohne Test aktivieren. | Legitime Anfragen treffen WAF-Regeln und Nutzer erhalten 403. |
Teste auf canary. Halte die Änderung fest. Siehe Application Gateway. |
| Ein fehlender Private-DNS-Eintrag für einen Backend-Namen. | Das Application-Gateway-Backend ist unhealthy und Nutzer erhalten 502. Leicht mit einem firewall-Problem zu verwechseln. |
Prüfe die Namensauflösung vom hub aus, bevor du firewall-Regeln änderst (Incident-Management). |
| Eine Site-to-Site-VPN-Verbindung meldet connected, leitet aber keinen Verkehr durch. | Ein Ausfall, den kein zustandsbasierter Alert erkennt. | Alarmiere auf Traffic, nicht nur auf den Zustand. Nutze wo möglich zwei Verbindungen. In einem gemeldeten Fall stellte das Zurücksetzen der Verbindung auf beiden Seiten den Verkehr wieder her. |
| Ein Destroy, der auf halbem Weg scheitert (zum Beispiel eine gestoppte VM, deren Extensions sich nicht entfernen lassen), hinterlässt ein Teilergebnis. | Ein späterer erneuter Lauf erstellt Teile neu, zum Beispiel eine leere Daten-Disk, die nicht angehängt ist. | Prüfe, was nach einem fehlgeschlagenen Destroy übrig ist, bevor du erneut ausführst oder neu baust. |
| Ressourcen- oder Konfigurationsnamen, die die Umgebung doppelt enthalten. | Die falsche Ressource wird zum Löschen ausgewählt. | Vergleiche den Plan mit den echten Ressourcen und hole die Bestätigung des Eigentümers ein, bevor du einen Destroy anwendest. |
Dokumentation, die an anderer Stelle in diesem Repository veraltet ist¶
| Dokument | Problem |
|---|---|
docs/howto/run-initialize-pipeline.md, run-container-pipeline.md |
Sie verweisen auf initialize.yaml / stage-initialize.yaml und Selektorvariablen für canary/production. Die aktuelle Pipeline ist infrastructure.yaml, die alles aus mcp.json liest. |
PLATFORM_FEATURES.md |
Sie behauptet, alle Ressourcen erhielten die Tags environment/managedBy/layer/region, und nennt Terraform >= 1.0 / AzureRM >= 3.0. Der Code hat keine globalen Tags (siehe hub-Tags); das Image pinnt Terraform 1.14.4, und die Layer pinnen azurerm 4.60.0. Für die Ressourcen und ihre Schalter nutze Was die Plattform deployt. |
docs/howto/configure-terraform-logging.md |
Sie beschreibt die Parameter terraformLogCore und terraformLogProvider der pipelines environment_canary und environment_prod. Prüfe, ob die Entry-pipelines, die du verwendest, sie anbieten (Troubleshooting). |
docs/howto/run-pool-smoke-tests.md |
Sie ruft Resolve-XebiaMcpConfiguration -Environment canary auf (die Funktion hat nur -Path) und dev.ps1 -Action Initialize. Verwende den Aufruf aus Troubleshooting. |
Ältere Update-Runbooks (einzelne main.yaml-pipeline) |
Sie weichen bei der Layer-Reihenfolge ab (wo ghrunners steht) und beschreiben Layer, die die aktuelle hub-pipeline nicht ausführt. Siehe Generisches Update-Runbook. |
| Übersicht der Release Notes | Sie nennt v4.4.0 als aktuelle stabile Version und endet bei v4.6.1. Siehe Release-Historie. |
| Ältere Alerting-Übersichtsdokumente | Zwei Dokumente nennen unterschiedliche Severities für dieselben Alerts (zum Beispiel die VPN-Tunnel-Alerts), und eines nennt einen Alert für das Löschen einer Firewallregel mit der Operation eines anderen Resource Providers. Behandle die Alert-Definitionen im Code als maßgeblich (Alert-Katalog). |
docs/policy_exemptions/current-platform-exemptions.md |
Mehrere Listen weichen von infra/deploy/postdeployment/main.tf ab, zum Beispiel die Subscription-Ausnahmen für NIS2 und CIS 1.4.0. |
docs/service_management/standard_changes.md |
Ältere Anfrageformulare. Die Anfragefelder in diesem Leitfaden folgen dem aktuellen Standardänderungs-Katalog. |
CONTRIBUTING.md |
Sie verwendet Resolve-XebiaMcpConfiguration -Environment (die Funktion hat nur -Path) und verweist auf Functions/Public/Runner/, das es nicht gibt. |