Ga naar inhoud

Deployment en omgevingen

Deze pagina legt uit hoe de portal is opgebouwd, hoe een omgeving wordt beschreven en hoe een wijziging productie bereikt. Ze beschrijft het referentieontwerp: pipelines, repositorylayout en namen kunnen in jouw deployment afwijken. Volg voor de eerste deployment van een omgeving Een klant onboarden.

Overzicht

flowchart LR
    pr[Pull request] --> lint[Lint and<br/>Terraform tests]
    lint --> build[Build image once<br/>no Azure credential]
    build --> r1[Ring 1<br/>plan, approve, apply]
    r1 --> r2[Ring 2]
    r2 --> r3[Ring 3]
Principe Detail
Eén keer bouwen, vaak deployen Per run wordt één container image gebouwd en naar de registry van elke omgeving gepusht. De buildjob heeft geen Azure-credential.
Eén Terraform root per omgeving Elke klant en omgeving heeft een eigen main.tf, zodat een wijziging voor de ene klant een andere niet per ongeluk kan aanpassen.
Het plan wordt ongewijzigd toegepast Het plan dat is gemaakt en getoond, is het plan dat wordt toegepast. Het wordt niet opnieuw berekend tijdens het toepassen.
Configuratie in een bestand De gegevens van een omgeving zijn rijen in één JSON-bestand, geen pipelinevariabelen.

Terraform roots

infra/
  modules/            shared modules
  platform/ado        private connections from the provider network
  platform/pagerduty  shared escalation policy and schedule
  <customer>/<env>/   one root per environment

De gedeelde modules:

Module Maakt aan
backstage Web app met staging slot, identities, private endpoints, PostgreSQL, role assignments
postgresql PostgreSQL Flexible Server 16
key_vault Key Vault met RBAC, purge protection, geen publieke toegang
container_registry Premium registry, geen publieke toegang
azure_monitor Application Insights en Log Analytics
tenant_configuration Secrets van de tenant in Key Vault
cost_insights Data Factory, storage, Data Lake, Azure SQL (Cost insights setup)
foundry_platform Azure AI Foundry account, project, modeldeployments (AI setup)
pagerduty Service, afhankelijkheid en Azure Monitor action group
landing_zone_spoke_canvas Alleen data: leest de bestaande resource group, VNet, subnets, Key Vault en Log Analytics van de spoke

Een typische omgevingsroot combineert: spoke canvas, naming, resource group, App Service plan, Key Vault, een secret voor het MCP-token, container registry, Azure Monitor, tenantconfiguratie, backstage, foundry_platform en pagerduty. De root geeft de app settings van de web app door: APP_CONFIG_organization_name, feature flags, het modelendpoint, het MCP-token en optionele instellingen voor integraties en de module registry. Zie Configuratie.

Bronnen van gedeelde modules

Sommige omgevingsroots verwijzen naar gedeelde modules uit een registry of repository buiten deze codebase. De bron beschrijft dat mechanisme niet, dus bevestig bij de provider waar die modules vandaan komen.

Het omgevingenbestand

Elke omgeving is één rij in infra/customer-environments.json. Een schema valideert het bestand zodra een pull request wordt geopend, dus een ontbrekend veld faalt vóór de merge.

Veld Betekenis
owner, environment Naam van klant en omgeving (acc, prod)
deploymentEnvironment Naam van het GitHub Environment, <owner>_<env>
ring Deployvolgorde
enabled Sla de rij over als dit false is
terraform.directory Pad van de root van de omgeving
terraform.backend Resource group, storage account en container (standaard tfstate) van de state
terraform.backstageClientSecretName Naam van het repository secret met de Terraform client secret
terraform.appSecretNames Namen van optionele app-secrets (GitHub App)
azure.clientId, tenantId, subscriptionId Identity en subscription voor plan en apply
azure.clientSecretName Alleen voor de terugval op een client secret
azure.useDeployEnvironmentForPlan Koppel het GitHub Environment aan de planjob
backstage.containerRegistry Login server van de registry
backstage.appService.name, resourceGroup De web app

Voorbeeldrij (placeholders):

{
  "owner": "<customer>",
  "environment": "acc",
  "deploymentEnvironment": "<customer>_acc",
  "ring": 2,
  "terraform": {
    "directory": "infra/<customer>/acc",
    "backstageClientSecretName": "BACKSTAGE_CLIENT_SECRET_<CUSTOMER>_ACC",
    "backend": {
      "resourceGroup": "<backend-resource-group>",
      "storageAccount": "<backend-storage-account>"
    }
  },
  "azure": {
    "clientId": "<client-id>",
    "tenantId": "<tenant-id>",
    "subscriptionId": "<subscription-id>"
  },
  "backstage": {
    "containerRegistry": "<registry>.azurecr.io",
    "appService": { "name": "<web-app-name>", "resourceGroup": "<resource-group>" }
  }
}

Uitrol in rings

Omgevingen worden in genummerde rings gedeployd. Ring N start pas als ring N-1 als geheel is afgerond: als één omgeving in een ring faalt, start de volgende ring niet. Dit is een veiligheidspoort voor de hele ring en geen isolatie per klant. De ring van elke omgeving staat in het veld ring, dus controleer het bestand voor de actuele indeling.

Voor elke omgeving in een ring doet de pipeline het volgende:

  1. Maakt een Terraform plan en een leesbare samenvatting, standaard zonder GitHub Environment.
  2. Wacht bij de poort van het GitHub Environment.
  3. Past het opgeslagen plan toe.
  4. Deployt de portal, als de run dat bevat (Slot swap).

Elke omgeving heeft bovendien een eigen concurrency slot voor de hele deployment, zodat twee runs niet tegelijk dezelfde Terraform state kunnen wijzigen. De pipeline vergelijkt geen branches of commits, dus een engineer kan bewust een branch of een oudere commit deployen, bijvoorbeeld voor een rollback.

Pipelines

Workflow Doel
CI/CD (push naar main) Lint, Terraform tests, build, daarna ring 1, 2 en 3 met infrastructuur en portal
Dispatch Handmatige run. Inputs: deploy_to (ring 1, 2 of 3), run_lint, deploy_infra, build_and_deploy_backstage
Terraform plan Maakt plannen voor gewijzigde roots op pull requests en voor elke omgeving aan het begin van haar ring
Deploy environment Past het opgeslagen plan toe en deployt optioneel de portal
Platform private connections Plant op pull requests, past toe bij een merge
Platform alerting Past het gedeelde escalation policy en schedule toe

De run heeft een timeout van 210 minuten, omdat het aanmaken van een Foundry account meer dan twee uur kan duren.

Environment gate

Het GitHub Environment dat in deploymentEnvironment staat, bevat de goedkeuring. Acceptatie heeft normaal geen reviewers; productie vereist goedkeuring door het platformteam. De planjob gebruikt het environment niet, tenzij azure.useDeployEnvironmentForPlan true is, zodat het leesbare plan bestaat voordat iemand goedkeurt.

Slot swap

De portal wordt gedeployd via het staging slot van de web app:

  1. Push de image naar de registry van de omgeving.
  2. Start het staging slot.
  3. Zet de container image op het slot.
  4. Preview swap.
  5. Smoke test: het readiness-endpoint geeft 200 terug en een responseheader x-build-id is gelijk aan de run-ID. Timeout 600 seconden.
  6. Bij succes: swap. Bij een fout: reset de swap.
  7. Stop het staging slot.

Authenticatie naar Azure

Plan en apply authenticeren met OIDC via een federated credential op een app registration in de doeltenant. Er wordt geen Azure-secret in GitHub opgeslagen.

Federated credential Subject
Pull requests repo:<owner-id>/<repo-id>:pull_request
Main branch repo:<owner-id>/<repo-id>:ref:refs/heads/main
Elke omgeving repo:<owner-id>/<repo-id>:environment:<owner>_<env>

Alle hebben audience api://AzureADTokenExchange. De issuer is de OIDC-issuer van de GitHub Enterprise-tenant die de repository host. Die verschilt van de publieke GitHub-issuer, dus kopieer hem niet uit generieke voorbeelden. Het subject gebruikt de onveranderlijke owner- en repository-ID's, zodat een hernoeming of overdracht de credentials niet breekt.

Secret Gebruik
BACKSTAGE_CLIENT_SECRET_<OWNER>_<ENV> Repository secret met de client secret van de app registration van de portal, doorgegeven aan Terraform. Het moet een repository secret zijn, omdat het plan zonder GitHub Environment draait.
GH_APP_* Optionele GitHub App-waarden, benoemd in appSecretNames, aan Terraform doorgegeven als var.app_secrets en opgeslagen in Key Vault, waarnaar de app settings verwijzen
AZURE_CLIENT_SECRET_<OWNER>_<ENV> Alleen als er geen federated credential kan worden aangemaakt. Een laatste redmiddel: een langlevend secret dat je handmatig roteert.

Plan en apply delen één identity

De federated credential per omgeving scheidt de planfase nog niet van de applyfase, omdat beide dezelfde identity gebruiken. Het besluitenlog noemt dit als openstaand risico (Decisions).

De portal bijwerken

Een wijziging in de code gaat via een pull request en daarna door de rings. Een configuratiewijziging voor één klant is een wijziging in diens app-config.<customer>.yaml of in de app settings in diens Terraform root. Zie Configuratie. Er worden geen klantspecifieke codewijzigingen gedaan.