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_emailsgefüllt ist. - Nur der erste Log-Analytics-Workspace wird für die Alert Rule und die Dashboard-Variable verwendet.