Zum Inhalt

Observability (Managed Grafana)

Dieses Runbook richtet sich an das Plattform-Team. Es behandelt den optionalen Observability-Tier: eine Azure-Managed-Grafana-Instanz pro Umgebung, die Log Analytics liest und den Zustand der Fabric-pipelines zeigt. Workload-Teams lesen Monitoring.

Was deployt wird

Der Tier ist eine eigene Terraform-Root (infra/deploy/observability) mit eigenem State (observability.tfstate) und hat damit einen eigenen Lebenszyklus. Die einzige Abhängigkeit ist der Log-Analytics-Workspace des spokes, der zuerst existieren muss.

flowchart LR
    fp["Fabric pipelines"] --> lh["pipeline_logs Lakehouse"]
    lh --> law["Log Analytics workspace"]
    law --> g["Managed Grafana (KQL dashboards)"]
    law --> alert["Scheduled query rule: pipeline failures"]
    law -->|"data export rule (optional)"| st["Storage account: cool, then archive, then delete"]
Ressource Hinweise
Resource group rg-<workload>-observability-<env>-<region>-001
Managed Grafana grafana-<workload>-<env>-<region>, SKU Standard, Größe X1 als Default, Major-Version 12, System-assigned Identity, deterministische ausgehende IPs an, API-Keys aus, öffentlicher Zugriff standardmäßig an, Zonenredundanz standardmäßig aus
Rollenzuweisungen für die Grafana-Identity Monitoring Reader und Log Analytics Reader auf jedem verbundenen Log-Analytics-Workspace
Rollenzuweisungen für Gruppen Grafana Admin, Grafana Editor und Grafana Viewer für die Gruppen in grafana_rbac
Private Endpoint (optional) Im Private-Endpoint-Subnet des spokes. Private DNS wird per Policy gesetzt, deshalb ignoriert das Terraform Änderungen an der DNS Zone Group.
Diagnoseeinstellung Audit-Logs und Metriken von Grafana an den ersten Log-Analytics-Workspace
Alert Rule und Action Group alert-pipeline-failure-grafana-... und ag-pipeline-alerts-grafana-...
Speicher für historische Logs (optional) Ein Storage Account mit einer Data Export Rule und einer Lifecycle Policy

Designentscheidungen

Entscheidung Grund
Eigene Resource group und eigener State Trennt die Observability von Workload-Ressourcen und erlaubt einen unabhängigen Lebenszyklus
System-assigned Managed Identity Grafana liest Log Analytics ohne Zugangsdaten, über das Azure-Backbone
Deterministische ausgehende IPs Egress-Adressen sind fest und können deshalb in Logs identifiziert und in Firewalls erlaubt werden
Nur Entra ID, keine API-Keys Aller Zugriff läuft über Entra ID mit MFA per Conditional Access. Automatisierung nutzt einen Service Principal oder eine Managed Identity.
Getrennte Gruppen für Grafana Anderer Schadensradius: Zugriff auf Grafana ist kein Zugriff auf Fabric
Standardmäßig öffentlich, Private Endpoint optional Die Entwicklung nutzt öffentlichen Zugriff mit Entra ID und MFA. Die Produktion kann auf das VNet beschränken.
Dashboards als Code JSON-Templates im Konfigurations-Repository, bereitgestellt mit dem Grafana-Terraform-Provider

Voraussetzungen

Sicherheitsgruppen

Erstelle vor dem Deployment pro Workload drei Entra-ID-Sicherheitsgruppen. Sie sind getrennt von den Fabric-Workspace-Gruppen.

Gruppe (Namensmuster) Grafana-Rolle Vorgesehene Mitglieder
sg-fabric-<workload>-grafana-admins Admin Engineers des Plattform-Teams
sg-fabric-<workload>-grafana-editors Editor Data Engineers und Analysten des Workload-Teams
sg-fabric-<workload>-grafana-viewers Viewer Fachliche Stakeholder, Management

Zum Erstellen von Gruppen brauchst du in Entra ID die Rolle Groups Administrator oder Global Administrator.

WORKLOAD="<workload>"
for role in admins editors viewers; do
  az ad group create \
    --display-name "sg-fabric-${WORKLOAD}-grafana-${role}" \
    --mail-nickname "sg-fabric-${WORKLOAD}-grafana-${role}" \
    --security-enabled true --query id -o tsv
done

Füge Mitglieder mit az ad group member add --group <name> --member-id <object id> hinzu. Trage die Object-IDs in die Variablen ein:

grafana_rbac = {
  admins  = ["<admins group object id>", "<deploying service principal object id>"]
  editors = ["<editors group object id>"]
  viewers = ["<viewers group object id>"]
}

Der deployende Service Principal muss Grafana Admin sein

Die Dashboards werden über die Grafana-API bereitgestellt. Dafür braucht es die Rolle Grafana Admin auf der Instanz, eine separate Zuweisung neben den Contributor-Rechten, die die Instanz erstellen. Trage die Object-ID des deployenden Service Principals in grafana_rbac.admins ein.

Sonstiges

  • Die IDs der Log-Analytics-Workspaces, die verbunden werden sollen (log_analytics_workspace_ids). Der erste wird für die Diagnose, die Alert Rule, die Data Export Rule und die Template-Variable des Dashboards verwendet.
  • Optional das Subnet und die private DNS zone für einen Private Endpoint.

Variablen

Variable Zweck und Default
grafana_config sku (Standard), sku_size (X1), api_key_enabled (false), deterministic_outbound_ip_enabled (true), public_network_access (true), zone_redundancy (false), grafana_major_version ("12")
grafana_private_endpoint enabled (false), subnet_id, private_dns_zone_id
grafana_rbac Listen von Object-IDs für admins, editors, viewers
alert_rules pipeline_failure_enabled (false), pipeline_failure_interval (300 Sekunden), pipeline_failure_lookback (3600 Sekunden), notification_contact_emails
dashboard_definitions enabled (false)
dashboard_path Verzeichnis mit den Dashboards. Wird von der pipeline über die Umgebungsvariable TF_VAR_dashboard_path gesetzt.
historical_log_storage Siehe Aufbewahrung historischer Logs

Erlaubte Regionen und Umgebungen sind dieselben wie bei den anderen Tiers (Plattformkonfiguration).

Deployment

Die pipeline hat eine Lauf-Option, um den Observability-Tier zu deployen. Die pipeline-Definitionen sind nicht Teil der Quellen dieser Lösung, der genaue Name der Option hängt also von deiner pipeline ab.

Zwei Phasen beim ersten Deployment. Der Grafana-Provider braucht die URL einer Instanz, die noch nicht existiert.

Phase Was passiert
Erster Lauf Die Grafana-Instanz, Rollenzuweisungen, Diagnose und Alert Rule werden erstellt. Die Dashboard-Ressourcen schlagen fehl, weil es noch keinen Endpoint gibt. Das ist erwartet.
Zweiter Lauf Die pipeline liest den Output grafana_endpoint, holt ein Token für die Azure-Managed-Grafana-Anwendung (Umgebungsvariablen GRAFANA_URL und GRAFANA_AUTH), und die Dashboards werden bereitgestellt

Danach läuft jeder Lauf in einer einzigen Phase. Data Engineers fügen Dashboards im Konfigurations-Repository hinzu und setzen dashboard_definitions.enabled = true.

Das Dashboard-Verzeichnis hat einen Unterordner pro Grafana-Ordner und eine .json-Datei pro Dashboard. Das Modul findet alle */*.json-Dateien, eine Konfiguration pro Datei ist also nicht nötig. Die Datei ist ein Terraform-Template mit einer Variable: ${LAW_RESOURCE_ID}. Grafana-Template-Variablen müssen escaped werden ($${...}).

Sicherheitskontrollen

Kontrolle Umsetzung
Authentifizierung Entra-ID-SSO, keine lokalen Konten
MFA Conditional-Access-Policies
API-Keys Standardmäßig deaktiviert. Wenn aktiviert, erfolgt die Rotation manuell.
Audit-Logging Diagnoseeinstellungen an Log Analytics (Audit-Logs, alle Logs, Metriken)
Ausgehende IPs Deterministisch
TLS Nur HTTPS
DNS-Label-Scope TenantReuse, was einen vorhersagbaren DNS-Namen ergibt
Private DNS Per Policy verwaltet

Aufbewahrung historischer Logs

Logs können für eine günstigere Langzeitaufbewahrung in Stufen aufgeteilt werden. Das ist standardmäßig aus (historical_log_storage.enabled = false).

Stufe Dauer Storage Abfrage
Hot 0 bis 30 Tage Log-Analytics-Workspace Interaktives KQL
Cool 31 bis 90 Tage Blob Storage, cool Log Search Jobs oder Restore
Archive 91 bis 365 Tage Blob Storage, archive Zuerst rehydrieren (dauert Stunden)
Einstellung Default
export_tables ["FabricPipelineRuns_CL"]
archive_after_days 90
delete_after_days 365
law_resource_group_name Resource group des Log-Analytics-Workspaces, für die Export Rule nötig

Das Storage Account ist Standard, LRS, StorageV2, Access Tier Cool, mit Soft Delete für Blobs und Container von 7 Tagen. Eine Lifecycle Rule verschiebt Blobs ins Archive und löscht sie nach den konfigurierten Tagen. Voraussetzungen: Die benutzerdefinierte Tabelle muss in Log Analytics existieren, bevor die Export Rule erstellt werden kann, und Export Rules unterstützen nur DCR-basierte benutzerdefinierte Tabellen (Suffix _CL). Deploye den Speicher für historische Logs nachdem die Data Engineers die Log-Ingestion-pipeline eingerichtet haben.

Fehlerbehebung

Symptom Ursache Lösung
„No data“ in allen Panels Die Tabelle FabricPipelineRuns existiert noch nicht Die Data-Engineering-pipeline hat Log Analytics noch nicht befüllt
„No data“ in manchen Panels Zeitraum zu eng, oder keine Läufe mit diesem Status Zeitraum erweitern, prüfen, ob pipelines gelaufen sind
„Insufficient permissions“ an der Datenquelle Die Rollenzuweisungen der Grafana-Identity sind noch nicht propagiert 10 Minuten nach dem Deployment warten
Anmeldung nicht möglich (403) Der Benutzer ist in keiner Grafana-Gruppe Den Benutzer einer Gruppe hinzufügen
Anmeldung nicht möglich (Timeout) im privaten Modus VPN oder ExpressRoute ist nicht verbunden, oder DNS liefert keine private IP Verbinden und DNS prüfen
„Datasource not found“ Die Azure-Monitor-Datenquelle ist nicht konfiguriert Prüfen, ob die Grafana-Identity Monitoring Reader auf dem Workspace hat
Alert löst nicht aus Rule deaktiviert, oder keine E-Mail konfiguriert pipeline_failure_enabled und notification_contact_emails prüfen
Deployment schlägt bei grafana_major_version fehl Die Standard-SKU braucht eine unterstützte Major-Version grafana_major_version = "12" setzen
Terraform will private_dns_zone_group ändern Die Policy hat die DNS Zone Group nach der Erstellung gesetzt Erwartet. Den ignore_changes-Lifecycle-Block beibehalten.

Bekannte Einschränkungen

  • Keine Berechtigungen auf Ordner- oder Dashboard-Ebene in Azure Managed Grafana. Optionen, wenn du Trennung brauchst: eine Instanz pro Team (jeweils mit eigenen Gruppen und Log-Analytics-Verbindungen), eine gemeinsame Instanz akzeptieren oder ein eigenes Grafana Enterprise betreiben (mehr Kosten und Betriebsaufwand).
  • Keine automatische Rotation der Grafana-API-Keys, falls du sie aktivierst.
  • Alerts bei pipeline-Fehlern senden nur dann E-Mail, wenn notification_contact_emails gefüllt ist.
  • Nur der erste Log-Analytics-Workspace wird für die Alert Rule und die Dashboard-Variable verwendet.