Shared Services: Was deployt wird und wie¶
Diese Seite richtet sich an das Plattform-Team. Sie beschreibt, was der Code der Shared Services deployt, wie er konfiguriert wird und wie die Deployment-pipeline funktioniert. Die Sicht des Workload-Teams steht unter Shared services. Die Extensions, die einen spoke mit diesen Services verbinden, stehen unter Spoke extensions.
Wer „das Plattform-Team“ ist, hängt von deinem Betriebsmodell ab: XMMS im Managed-Modell, dein eigenes Team im Eigenbetrieb.
Referenzdesign, dein Deployment kann abweichen
Shared Services sind nicht Teil des Core-MCP-hub-and-spoke (Servicetypen). Die folgenden Fakten stammen aus dem Terraform-Code und der pipeline einer Referenzimplementierung. Ressourcennamen, Größen und die Menge der Addons, die du betreibst, können abweichen. Werte in Beispielen sind Platzhalter.
Wie alles zusammenspielt¶
flowchart LR
code["Shared services code<br/>(Terraform, one folder per addon)"] --> pipe["Deployment pipeline<br/>(plan, then apply)"]
cfg["Shared services configuration<br/>(one variables file per addon and environment)"] --> pipe
pipe -->|"service connection"| spoke["Shared services spoke<br/>(spoke canvas: VNet, Key Vault, Log Analytics)"]
spoke --> svc["Addons: gateway, registry, API Management,<br/>messaging, communication, build agents"]
ws["Workload spokes"] -->|"spoke extensions<br/>(roles, groups, identities)"| svc
Zwei Repositories arbeiten zusammen:
| Repository | Inhalt |
|---|---|
| Shared services Code | Wiederverwendbares Terraform pro Addon in infra/<addon>/ und die pipeline-Templates in pipelines/templates/ |
| Shared services Konfiguration | Die umgebungsspezifischen Werte (variables.tfvars) pro Addon |
Der Code enthält keine Umgebungswerte. Ein Deployment kombiniert einen Addon-Ordner des Codes mit der passenden Variablen-
datei der Konfiguration. Das Code-Repository hat einen Workflow, der bei jedem Push auf main und bei tags, die mit v beginnen, eine nachgelagerte Synchronisierung
auslöst. Zum Mechanismus siehe Code-Synchronisierung.
Was der Code deployt¶
Die Shared Services werden in einen bestehenden spoke gebaut. Jedes Addon liest Ressourcengruppe, virtuelles Netzwerk, Subnet,
Key Vault und Log Analytics workspace dieses spokes per Name (Variable spoke_config), der spoke muss also existieren, bevor du
ein Addon deployst (Spoke-Deployment).
Addon (Ordner in infra/) |
Was es deployt | Zugriff, den es erstellt |
|---|---|---|
appgw |
Application Gateway mit WAF-Policies, öffentliche IP, user-assigned Identität, Key Vault für Zertifikate | Die Gateway-Identität erhält Key-Vault-Rollen. Siehe unten |
acr |
Container Registry aus modules (Premium, private endpoint, kundenverwalteter Schlüssel) | Optionale Rollenzuweisungen für Gruppen, die du per Object-ID übergibst |
acr-alt |
Container Registry, in sich geschlossen (Premium, private endpoint, kundenverwalteter Schlüssel) | Erstellt eine AcrPull- und eine AcrPush-Gruppe |
apim |
API Management, Application Insights mit eigenem Log Analytics workspace, optionales Developer Portal | Monitoring-Reader-Gruppe, optionale Gruppe für Portal-Content-Editoren |
event-hub-namespace |
Event-Hubs-Namespace und Event Hubs, private endpoint, kundenverwalteter Schlüssel | Eine Sender-Gruppe und eine Receiver-Gruppe pro Event Hub |
service-bus |
Service-Bus-Namespace (Premium), private endpoint, optionaler kundenverwalteter Schlüssel | Eine Contributors-Gruppe auf dem Namespace |
acs |
Azure Communication Services und Email Communication Services, mit Domains | Eine Contributors-Gruppe |
cae-agents |
Selbst gehosteter Azure-Pipelines-Agent-Pool auf Container Apps jobs | Managed identity mit AcrPull und Administrator auf dem Pool. Siehe Container Agent Pool |
Gruppen werden in der Administrative Unit erstellt, die du übergibst (administrative_unit_id), der Unit der landing zone.
Gemeinsame Sicherheitseinstellungen¶
| Einstellung | Wo |
|---|---|
| Public network access deaktiviert, Zugriff über einen private endpoint | Registry, Service Bus, Event Hubs, Key Vault des Gateways. API Management im SKU StandardV2 (siehe unten) |
| Lokale Authentifizierung (Schlüssel, SAS) deaktiviert | Service Bus (local_auth_enabled = false), Event Hubs (local_authentication_enabled = false), Application Insights und sein workspace |
| Registry: Admin-User aus, anonymer Pull aus, Export Policy aus | acr und acr-alt |
| Kundenverwalteter Schlüssel im Key Vault des spokes | Registry, Event Hubs, Service Bus (wenn customer_managed_key_enabled auf true steht) |
| RBAC-Autorisierung, purge protection an | Key Vault des Gateways |
Die kundenverwalteten Schlüssel sind RSA-2048-Schlüssel mit Ablauf ein Jahr nach der Erstellung, einer automatischen Rotation Policy und einer
Benachrichtigung vor dem Ablauf. Die Private-DNS-zone-Gruppe der private endpoints wird nicht vom Code verwaltet
(ignore_changes auf dem private endpoint oder private_endpoints_manage_dns_zone_group = false): Die DNS-Registrierung kommt von
der Plattform (Abdeckung des private-endpoint-DNS). Prüfe, dass deine Plattform die
Services abdeckt, die du deployst.
Namen und Umgebungen¶
Jedes Addon unterstützt zwei Namensmodi:
| Modus | Variablen | Beispielergebnis |
|---|---|---|
| Umgebungsbasiert (empfohlen für neue Deployments) | environment (höchstens 7 Zeichen) und location_short |
apim-nonprod-weu-001, Ressourcengruppe rg-apim-nonprod-weu-001 |
| Legacy | resource_postfix |
apim-<postfix>-001 |
Die umgebungsbasierten Namen werden nur genutzt, wenn beide environment und location_short gesetzt sind. Bestehende Deployments, die
resource_postfix nutzen, planen ohne Änderungen. Ein bestehendes Deployment von einem Modus in den anderen zu verschieben ändert die Namen, sodass
Terraform neue Ressourcen erstellt: Plane eine Migration (neues Deployment, Datenmigration, Aufräumen) und wechsle nicht, indem du
die Variablen bearbeitest. Das Application-Gateway-Addon hat keinen Legacy-Modus: environment und location_short sind Pflicht.
| Service | Muster für den Ressourcennamen (umgebungsbasiert) |
|---|---|
| Ressourcengruppe | rg-<service>-<environment>-<location_short>-001 |
| API Management | apim-<environment>-<location_short>-001 |
| Service-Bus-Namespace | sbns-<environment>-<location_short>-001 |
| Event-Hubs-Namespace | ehns-<environment>-<location_short>-001 |
Container Registry (acr-alt) |
acr<environment><location_short>001 (Bindestriche entfernt) |
| Communication Services | acs-<environment>-<location_short>-001, Email Service ecs-... |
| Application Gateway | agw-<environment>-<location_short>-001 |
Betreibe Non-production und Production als getrennte Deployments: getrennte subscriptions, getrennte Terraform-state-Dateien (zum Beispiel
apim-nonprod.tfstate und apim-prod.tfstate) und getrennte Gruppen. Die Beispielwerte im Code-Repository unterscheiden sich pro
Umgebung, zum Beispiel:
| Einstellung | Beispiel Non-production | Beispiel Production |
|---|---|---|
| API-Management-SKU und Units | StandardV2, 1 |
Premium, 2, Zonen 1, 2, 3 |
| Event Hubs | Standard, Capacity 1, 2 Partitionen, Retention 1 | Standard, Capacity 2, Auto-Inflate bis 10 Throughput Units, 4 Partitionen, Retention 7 |
| Service Bus | Capacity 1, 1 Messaging-Partition | Capacity 2, 4 Messaging-Partitionen |
Registry (acr-alt) |
Kein Data Endpoint, keine Quarantine, Zonenredundanz oder Trust Policy, Retention 7 | Data Endpoint, Quarantine, Zonenredundanz und Trust Policy an, Retention 30 |
Sieh das als Beispiele aus dem Deployment-Leitfaden des Repositorys, nicht als Defaults.
Hinweise zu den Addons¶
Application Gateway (appgw)¶
Referenzdesign: Das Gateway wird in einem spoke deployt, im Subnet AppGwSubnet des spoke-virtuellen-Netzwerks. Der Code
erstellt:
| Ressource | Hinweise |
|---|---|
Ressourcengruppe rg-agw-<environment>-<location_short>-001 |
Enthält alle Ressourcen unten |
| Öffentliche IP | Standard-SKU, statisch, Zonen 1, 2 und 3. Optionales DNS-Label (public_ip_dns_name). DDoS-Schutz ist standardmäßig an (use_ddos_protection_plan), dafür sind Plan-Name, Ressourcengruppe und subscription nötig (ddos_protection_plan, ddos_protection_plan_subscription_id). |
| Application Gateway | Zonen 1, 2 und 3. Eine user-assigned Identität. Alles Weitere kommt aus JSON-Dateien. |
| User-assigned Identität | Erhält Key Vault Certificates Officer und Key Vault Secrets User auf dem Key Vault des Gateways |
Key Vault kv-agw-<environment>-<location_short>-<random> |
RBAC, purge protection, 7 Tage Soft Delete, Public Access deaktiviert, private endpoint im Subnet aus spoke_config.subnet_pe_name |
| WAF-Policies | Eine pro JSON-Datei. Siehe WAF-Ausnahmen |
Eine optionale private Frontend-IP wird mit enable_private_ip und private_ip_address aktiviert.
Die Gateway-Konfiguration ist JSON, im Ordner, den application_gateway_json_file_relative_path festlegt (Default
gateway-definitions/, Muster *.json). Die Dateien haben ein Top-Level-Objekt application_gateway. Die Abschnitte aller Dateien werden
Abschnitt für Abschnitt zusammengeführt (Backend Pools, HTTP Settings, Frontend Ports, Listener, Routing Rules, Probes, Zertifikate, URL
Path Maps, Redirects, Rewrite Rules, SKU und Autoscale, TLS-Policies und -Profile). Plane mit allen vorhandenen Abschnitten, da das
module jeden Abschnitt direkt liest. Die Struktur eines Workload-Eintrags ist dieselbe wie unter
Application Gateway (Workload hinzufügen oder ändern) beschrieben.
Das Gateway nutzt die WAF-Policy aus der Datei web_application_firewall_policy_hub.json (der Dateiname bestimmt
den Policy-Schlüssel). Weitere WAF-Policy-Dateien erstellen Policies, auf die ein Listener oder eine Path Rule per Resource-ID verweisen kann.
Dieses Addon ist nicht in der Deployment-pipeline des Code-Repositorys (siehe Pipeline). Wie es in deiner Plattform deployt wird, ist in den Quellen nicht dokumentiert.
Zwei Gateway-Implementierungen
Der MCP hub kann auch ein Application Gateway aus dem layer connectivity deployen
(Plattformressourcen). Das Shared-Services-Addon oben ist eine
separate Implementierung mit anderen Ressourcennamen und Einstellungen. Wisse, welche deine Plattform nutzt, bevor du einem Runbook folgst.
Die Unterschiede stehen unter Application Gateway.
Container Registry (acr, acr-alt)¶
Beide erstellen eine Premium-Registry mit deaktiviertem Admin-User, anonymem Pull und Export, deaktiviertem Public Network Access, einem private endpoint und Verschlüsselung mit einem kundenverwalteten Schlüssel (mit einer user-assigned Identität, die Key Vault Crypto Service Encryption User auf dem Key Vault des spokes hat).
acr |
acr-alt |
|
|---|---|---|
| Struktur | Modules (container-registry, private_endpoint, role_assignments), aufgerufen aus deploy/ |
Ein in sich geschlossener Ordner |
| Gruppen | Du übergibst die Object-IDs von bis zu sieben Gruppen (Owner, Contributor, Reader, AcrPush, AcrPull, AcrDelete, AcrImageSigner). Jede Rolle wird nur für eine Gruppe zugewiesen, die du übergibst. | Erstellt zwei Gruppen (Namen aus acr_pull_group_name und acr_push_group_name) mit AcrPull und AcrPush |
| Registry-Einstellungen | data_endpoint_enabled und quarantine_policy_enabled sind in deploy/ fest auf false gesetzt |
container_registry_config: Data Endpoint, Quarantine, Zonenredundanz, Retention-Tage (Default 7), Trust Policy |
| Terraform Root | infra/acr/deploy |
infra/acr-alt |
Die Pull- und Push-Gruppen von acr-alt sind die Hauptgruppen, die die ACR spoke extension erwartet (acr_pull_group_object_id und
acr_push_group_object_id im Block shared_services, siehe Spoke extensions).
Die Quellen sagen nicht, welche Variante die aktuelle ist. Der Code enthält keine Pull-through-Cache-Regeln für öffentliche Registries:
Wenn die Registry auf deiner Plattform die Microsoft Container Registry oder Docker Hub cached, ist das anderswo konfiguriert.
API Management (apim)¶
| Thema | Verhalten |
|---|---|
| SKU | StandardV2 oder Premium. Units 1 bis 10 bei StandardV2, 1 bis 99 bei Premium. Availability Zones nur mit Premium. |
| Netzwerk | Premium: Typ des virtuellen Netzwerks Internal, kein private endpoint. StandardV2: Typ External mit einem private endpoint, und der Public Network Access wird nach der ersten Erstellung abgeschaltet (die Eigenschaft lässt sich bei der Erstellung des Services nicht setzen, deshalb prüft der Code, ob der Service existiert). |
| Identität | Eine system-assigned und eine user-assigned Identität |
| Telemetrie | Application Insights (lokale Authentifizierung deaktiviert) auf einem eigenen Log Analytics workspace, mit einem API-Management-Logger, der die managed identity nutzt. Optionale Diagnoseeinstellungen an den workspace des spokes (diagnostic_settings). Die Aufbewahrung von Application Insights beträgt standardmäßig 90 Tage. |
| Developer Portal | Standardmäßig aus (developer_portal.enabled). Wenn an: Basic Authentication aus, Anmeldung erforderlich, optionale Nutzungsbedingungen, optionale Gruppe für Content-Editoren. |
| Zugriff | Eine Gruppe mit Monitoring Reader auf Application Insights (application_insights_monitoring_readers_group_name) |
| Custom Domain | Nicht deployt. Die Datei custom_domain.tf ist auskommentiert. |
Die API-Definitionen und -Produkte für Entwickler und die Nutzung von API Management als Integrationsbaustein sind in der Integration Platform beschrieben.
Event Hubs und Service Bus¶
| Thema | Event Hubs (event-hub-namespace) |
Service Bus (service-bus) |
|---|---|---|
| SKU | Gesetzt durch event_hub_namespace_config (sku, capacity, Auto-Inflate, maximale Throughput Units) |
Premium (nötig für kundenverwaltete Schlüssel und private endpoints). capacity 1, 2, 4, 8 oder 16. messaging_partitions 1, 2 oder 4. |
| Inhalt | Ein Event Hub pro Eintrag in event_hub_config (Name, Partitionsanzahl, Retention in Tagen, Status) |
Der Namespace. Queues und Topics werden von diesem Code nicht erstellt. |
| Netzwerk | Private endpoint, Network Rule Set mit Default-Aktion Deny, Trusted Services aus | Private endpoint, Public Access aus, Trusted Services aus |
| Gruppen | Pro Event Hub: eine Sender-Gruppe (Azure Event Hubs Data Sender) und eine Receiver-Gruppe (Azure Event Hubs Data Receiver und Contributor) auf diesem Event Hub | Eine Contributors-Gruppe mit Contributor auf dem Namespace |
| Verschlüsselung | Immer kundenverwalteter Schlüssel | Kundenverwalteter Schlüssel, wenn customer_managed_key_enabled auf true steht (Default false) |
Die spoke extensions ergänzen darauf die Rollen für die spokes (Spoke extensions). Die Messaging-Services als Integrationsbausteine behandelt die Integration Platform.
Communication Services (acs)¶
Erstellt eine Communication-Services-Ressource und eine Email-Communication-Services-Ressource in der Data Location, die du wählst
(data_location), eine von Azure verwaltete E-Mail-Domain (deploy_managed_domain, Default false) und eine kundenverwaltete Domain für
jeden Namen in customer_managed_domains. Diagnoseeinstellungen senden die E-Mail-Logs (Send Mail, Status Update, User Engagement) an
den workspace des spokes. Eine Gruppe mit Contributor gibt Zugriff. Die Code-Kommentare sagen, dass die Gruppe gebraucht wird, bis spoke
extensions für diesen Service verfügbar sind, was zu Spoke extensions passt.
Container Agent Pool (cae-agents)¶
Siehe Container Agent Pool.
Pipeline¶
Die Referenz-pipeline pipelines/deployment.yaml deployt ausgewählte Addons. Sie checkt Code- und Konfigurations-Repository
nebeneinander aus und hat einen booleschen Parameter pro Addon:
| Parameter | Addon-Ordner | State-Key |
|---|---|---|
deployACR |
infra/acr |
acr-deploy.tfstate |
deployAPIM |
infra/apim |
apim-deploy.tfstate |
deployACS |
infra/acs |
acs-deploy.tfstate |
deployEVHN |
infra/event-hub-namespace |
evhn-deploy.tfstate |
deployASB |
infra/service-bus |
asb-deploy.tfstate |
deployCAEAgents |
infra/cae-agents |
cae-agents-deploy.tfstate |
Es gibt außerdem einen Parameter branch, um einen Branch oder tag des Code-Repositorys zu deployen. Für appgw und
acr-alt gibt es keinen Parameter.
So läuft ein Durchlauf:
- Plan-Stage: ein Job pro ausgewähltem Addon. Terraform wird installiert (die Referenz fixiert Version 1.9.3), das State-Backend
(Ressourcengruppe, Storage Account, Container) wird erstellt, falls es nicht existiert,
terraform initundterraform planlaufen mit der Variablendatei des Addons aus dem Konfigurations-Repository, und der plan wird als pipeline-Artifact veröffentlicht. - Apply-Stage: eine Stage pro Addon, die von der Plan-Stage abhängt. Die Stage läuft als Deployment-Job gegen ein Azure-DevOps- Environment, sodass Genehmigungen und Checks auf diesem Environment gelten. Sie lädt das Plan-Artifact herunter, wendet genau diesen plan an und veröffentlicht den Terraform-Output als Artifact.
- Für
cae-agentsstartet ein zusätzlicher Job nach dem apply den Placeholder-Job des Agent-Pools.
Die Authentifizierung läuft über die Azure-DevOps-Service-Connection. Das Template nutzt ein federated Token (OIDC), wenn die Service- Connection eines liefert, sonst das Client Secret des Service Principals. Der state liegt in einem Azure Storage Account mit Microsoft-Entra-ID-Authentifizierung.
Die pipeline liest diese Werte aus einer Variable Group: den Namen der Service Connection, die Ziel-subscription, die State- Ressourcengruppe, den Storage Account und den Container sowie, für den Agent-Pool, den Workload-Namen und den Resource Postfix. Der Agent-Pool braucht außerdem ein Personal Access Token für den Azure-DevOps-Terraform-Provider (Container Agent Pool).
Die README des Code-Repositorys zeigt auch, wie du zwei pipelines für ein Addon ausführst, mit anderer Umgebung, subscription,
anderem State-Key und anderer Variablendatei (-var-file=nonprod.tfvars, -var-file=prod.tfvars). Die Referenz-pipeline deployt eine
Umgebung, in Azure DevOps prod genannt.
Prüfe die pipeline, bevor du dich darauf verlässt
Teile der Referenz-pipeline wirken inkonsistent zum Code-Layout: Der Registry-Job zeigt auf infra/acr, während der
Terraform Root infra/acr/deploy ist, und die Pfade der Variablendateien unterscheiden sich pro Job (../config/... gegenüber
../../../config/...). Das Template, das das State-Backend erstellt, erlaubt außerdem öffentlichen Blob-Zugriff auf einem Storage Account, den es
erstellt. Teste einen plan für jedes Addon und prüfe die Einstellungen des State-Storage-Accounts, bevor du es in Production nutzt.
Betrieb¶
| Aufgabe | Wie |
|---|---|
| Eine Einstellung ändern | Ändere die Variablendatei im Konfigurations-Repository (oder den Code), führe die pipeline für das Addon aus und prüfe den plan. |
| Ein Addon oder eine zweite Instanz hinzufügen | Erstelle eine Variablendatei und einen State-Key. Folge dem Namensmuster mit environment und location_short, halte die Variablen mit null-Defaults optional und halte die Legacy-Benennung funktionsfähig. |
| Einen Workload anbinden | Schalte die spoke extension ein (Spoke extensions). Sie braucht die Resource-ID des Services in shared_services. |
| Einer Gruppe eine servicespezifische Rolle geben | Füge das Mitglied der Gruppe hinzu, die das Addon erstellt hat. Mitglieder, die du von Hand zu diesen Gruppen hinzufügst, werden von den Extensions nicht entfernt. |
| Einen fehlgeschlagenen apply untersuchen | Lies das Plan-Artifact und den Terraform-Output der Stage. |
| Die kundenverwalteten Schlüssel prüfen | Sie liegen im Key Vault des spokes und sind nach dem Service benannt (zum Beispiel <resource name>-encryption-key; das module acr nutzt <registry name>-managedkey-001). Sie haben eine Rotation Policy. Prüfe ihre Ablaufdaten. |