Compare commits

...
10 Commits
Author SHA1 Message Date
cbazza 09f485b5ac beispiel Terraform code für vm und cluster afc hinzugefügt 2025-12-23 10:19:14 +01:00
cbazzaandClaude Sonnet 4.5 dfff276de6 Restructure project: Move AKS cluster to beispiel-k8s-cluster directory
Major improvements:
- Import existing Azure AKS cluster with aztfexport
- Optimize VM size from Standard_D4d_v4 to Standard_D2as_v6 (50% cost reduction)
- Configure availability zones to [1, 2]
- Add comprehensive monitoring setup:
  * New Log Analytics Workspace
  * OMS Agent integration
  * Data Collection Rule for Container Insights
  * Email alerts for CPU and Memory
- Refactor configuration:
  * Extract all values to variables.tf
  * Rename resources with meaningful names
  * Add detailed outputs.tf
- Add project documentation:
  * Comprehensive README.md
  * cluster-status-commands.md with useful Azure CLI commands
  * terraform.tfvars.example template
  * .gitignore for sensitive files

Infrastructure changes:
- Resource Group: trusted_ai_demo_rg (Germany West Central)
- AKS Cluster: trai_k8s_cluster (Kubernetes 1.33)
- Node Pool: 2-3 nodes with auto-scaling
- Network: VNet 10.0.0.0/16, Subnet 10.0.0.0/24
- Monitoring: Full Container Insights with alerts

Cost optimization: ~€75/month (down from ~€140/month)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 13:36:51 +01:00
cbazza 4fd1f14a3b Beispiel Setup terraform added 2025-12-15 09:50:12 +01:00
arachristian c8556e6e74 Azure Logos Zip 2025-12-09 09:51:10 +01:00
christianfoh 62c4e4824a Ergänzung 2025-12-09 09:25:56 +01:00
christianfoh 35e24b4209 Bilder und Logos, zwei Textdateien mit Links 2025-12-09 09:15:48 +01:00
arachristian e1338c2314 Beispiel Setup von ChatGPT, erste Anfrage dazu 2025-12-08 14:03:26 +01:00
arachristian 8b3b15a9ce Anfragen Architekturentwurf an Claude, Mistral und ChatGPT 2025-12-08 13:51:00 +01:00
cbazza 16f5a5e7b1 output lokale LLM - gpt-oss-20b 2025-12-08 12:06:32 +01:00
cbazza 51379cf1fc Create prompt-an-ki-advanced-gpt-oss-20b
Ergebnis verbesserter Prompt - lokale KI gut-oss-20b
2025-12-08 11:45:46 +01:00
81 changed files with 9783 additions and 4 deletions

No files matched your search

@@ -0,0 +1,440 @@
Alles klar – ich führe den Prompt jetzt aus und entwerfe dir die Architektur.
---
## 1. Überblick & Annahmen
**Annahmen (konkretisiert):**
* Branche: reguliertes Finanzinstitut oder KRITIS-Betreiber in der EU.
* Daten: überwiegend **personenbezogene Daten** (inkl. special categories möglich), daher **DSGVO hoch relevant**.
* KI-System eurer Lösung gilt als **„High-Risk AI System“** nach EU AI Act (z. B. Kreditentscheidungen, Risiko-Scoring).([Künstliche Intelligenz Gesetz EU][1])
* Alle produktiven Workloads laufen in **EU-Azure-Regionen** (z. B. *West Europe*, *North Europe*).
* Nutzung von **Azure OpenAI (EU Data Zone / EU-Residency-Option)** bzw. ausschließlich EU-datenresidente Endpunkte für Foundation Models.([Microsoft Learn][2])
* Ziel: Architektur soll **technisch belegbar** Anforderungen aus
* EU AI Act (insb. Logging, Risikomanagement, Human Oversight)([digital-strategy.ec.europa.eu][3])
* DSGVO,
* DORA, NIS 2 (Resilienz, Monitoring, Incident Handling),
* ISO 27001 (ISMS-Kontrollen)
adressieren.
---
## 2. Zielarchitektur (High Level)
### 2.1 Schichtenmodell (verbale Übersicht)
1. **User & Clients**
* interne Nutzer (Mitarbeitende), ggf. externe Kunden
* Zugriff über Browser / interne Portale / APIs
2. **Edge / Ingress / Security**
* **Azure Front Door mit WAF** (global, optional)
* **Azure Application Gateway mit WAF** (regional, TLS-Terminierung)([Microsoft Learn][4])
* DDoS Protection, Azure Firewall, Private Endpoints
3. **API & Orchestration Layer**
* **Azure API Management (APIM)** als API-Gateway
* „Prompt Firewall“ & Policies in APIM + Azure AI Content Safety
* LLM-Router als Microservice (AKS) hinter APIM
4. **KI-/Compute-Layer**
* **AKS-Cluster** mit GPU-Nodepools für KI-Workloads
* Agentic AI-Orchestrator (z. B. LangChain-/Semantic-Kernel-basiert) als Services auf AKS
* Azure OpenAI / Azure AI Foundry / Self-hosted Models auf AKS
5. **Data & Event Layer**
* Azure SQL, Cosmos DB, Blob Storage (Data Lake), Azure AI Search (Vektor)
* Event Hubs (Kafka-kompatibel), Service Bus, Stream Analytics / Data Explorer
6. **Observability & Security-Layer**
* Azure Monitor, Log Analytics, Application Insights
* Azure Managed Grafana für Metrik-Dashboards([Microsoft Learn][5])
* Microsoft Sentinel + Splunk-Anbindung als SIEM/SOC
* Defender for Cloud (inkl. Defender for Containers, Defender for APIs)
7. **DevOps / MLOps / IaC**
* Git-Repos (GitHub Enterprise oder Azure DevOps), CI/CD-Pipelines
* Terraform für IaC (State in verschlüsseltem Azure Storage)
* Azure ML / AI Studio / AI Foundry für MLOps (je nach Stack)
---
### 2.2 Textuelles Architekturdiagramm (Mermaid)
```mermaid
flowchart LR
subgraph Clients
U[User / Apps]
end
subgraph Edge
AFD[Azure Front Door + WAF]
AGW[Application Gateway WAF + TLS]
AFW[Azure Firewall]
end
subgraph API
APIM[Azure API Management\n(API Gateway + Policies)]
PF[Prompt Firewall\n(Content Safety + APIM Policies)]
end
subgraph AI_Compute[AI & Compute Layer (AKS)]
AKS[AKS Cluster\nGPU/CPU Node Pools]
LLMR[LLM Router Service]
AGENTS[Agentic AI Orchestrator\n(AI Agents)]
FE[Frontend Container]
end
subgraph AI_Services
AOAI[Azure OpenAI / Azure AI Foundry\n(EU Data Residency)]
MODELS[Self-hosted Models on AKS]
end
subgraph Data[Data & Storage Layer]
SQL[Azure SQL DB / MI]
COSMOS[Azure Cosmos DB\n(NoSQL + Graph)]
BLOB[Azure Data Lake / Blob Storage]
VECTOR[Azure AI Search\n(Vektorindex)]
REDIS[Azure Cache for Redis]
KUSTO[Azure Data Explorer / Synapse]
end
subgraph Events
EH[Azure Event Hubs (Kafka Endpoint)]
SB[Azure Service Bus (Queues/Topics)]
SA[Azure Stream Analytics]
end
subgraph Observability[Observability & Security]
AM[Azure Monitor + Log Analytics]
APPINS[Application Insights]
GRAF[Azure Managed Grafana]
SENT[Microsoft Sentinel]
SPL[SPLUNK (VM/AKS)]
DEF[Microsoft Defender for Cloud]
end
subgraph Identity_Sec[Identity & Access]
ENTRA[Azure Entra ID\n(RBAC, Conditional Access)]
PIM[Entra Privileged Identity Mgmt]
KV[Azure Key Vault + Managed HSM]
BAST[Azure Bastion]
end
subgraph DevOps[DevOps / MLOps / IaC]
GIT[GitHub / Azure DevOps Repos]
PIPE[CI/CD Pipelines\n(GitHub Actions / Azure Pipelines)]
TF[Terraform\n(State in Storage)]
end
U --> AFD --> AGW --> APIM --> PF --> LLMR --> AGENTS
AGENTS --> AOAI
AGENTS --> MODELS
LLMR --> AOAI
LLMR --> MODELS
AGENTS --> SQL
AGENTS --> COSMOS
AGENTS --> BLOB
AGENTS --> VECTOR
AGENTS --> REDIS
AGENTS --> EH
EH --> SA --> KUSTO
AGENTS --> SB
AKS --> AM
AKS --> APPINS
AM --> GRAF
AM --> SENT
AM --> SPL
DEF --> SENT
ENTRA --> APIM
ENTRA --> AKS
ENTRA --> GIT
PIM --> ENTRA
KV --> AGW
KV --> APIM
KV --> AKS
BAST --> AKS
GIT --> PIPE --> AKS
PIPE --> TF
TF --> AKS
TF --> Data
TF --> Networking((VNet/NSG/PE))
```
---
## 3. Azure-Service-Mapping pro Baustein
### 3.1 KI- und Compute-Layer
| Baustein | Azure-Service(s) | Zweck / Begründung |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Kubernetes-Cluster mit KI-Workern | **Azure Kubernetes Service (AKS)** | Managed Kubernetes mit Integration in Azure RBAC, Managed Identities, Auto-Scaling, GPU-Nodepools für KI/LLM-Workloads. |
| Container-/Cluster-Management | AKS + **Azure Monitor for Containers**, **Azure Policy** | Zentrales Management, Configuration Enforcement (PodSecurity, Gatekeeper), Ressourcenkontrolle, Compliance. |
| Agentic AI mit LLM-Adapter | Microservices auf AKS (z. B. .NET/Python), **Azure OpenAI** / Azure AI Foundry | Orchestrierung von Agents, Aufruf verschiedener Modelle (Azure OpenAI, lokale Modelle). EU-Residency-Optionen helfen bei DSGVO/AI-Act-Konformität.([Microsoft Learn][2]) |
| Build, Test, Deploy von AI Agents | **GitHub Enterprise / Azure DevOps Repos**, **GitHub Actions / Azure Pipelines**, **AKS**, optional **Azure Machine Learning** (MLOps) | End-to-End-CI/CD-Pipelines inkl. Build, Tests (unit, integration, eval), Deployment auf AKS; ML-spezifische Pipelines mit Modellversionierung. |
| LLM-Router | Custom Service auf AKS + **Azure API Management** (Routing/Policies) | Policy-gesteuertes Routing zwischen Modellen (Azure OpenAI, Self-hosted, ggf. Drittanbieter), A/B-Tests, Fallback-Strategien. |
---
### 3.2 Security & Governance
| Baustein | Azure-Service(s) | Zweck / Begründung |
| --------------------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| WAF | **Azure Front Door WAF** und/oder **Application Gateway WAF** | Zentrale L7-Firewall gegen OWASP-Top-10, Bot-Protection, Geo-Blocking; unterstützt Compliance-Anforderungen.([Microsoft Learn][4]) |
| Prompt Firewall / Prompt Security | **Azure API Management Policies** + **Azure AI Content Safety** + Azure OpenAI Safety Filters | Vor- und Nachschaltung von Content-Filtern, Blockieren schädlicher Prompts/Outputs; wichtig für AI-Act-Risikomitigation und Grundrechtsschutz.([Microsoft Learn][2]) |
| AI-Model Scanning | **Microsoft Defender for Cloud** (Container/VM/Registry-Scanning), **Azure ML Responsible AI-Tools** | Scans von Container-Images/Abhängigkeiten, Modell-Governance (Bias, Fairness, Explainability) als Beitrag zu EU-AI-Act-Risikomanagement.([21medien.de][6]) |
| AI-Interface Scanning | **Microsoft Defender for APIs**, WAF-Logs, APIM Diagnostics | Schutz der API-Interfaces gegen Missbrauch, Anomalie-Erkennung, Angriffserkennung auf AI-Endpunkte. |
| Vulnerability Management | **Microsoft Defender for Cloud**, Defender for Containers, Qualys-Integration | Kontinuierliches Schwachstellenmanagement auf VMs, Containern, PaaS-Ressourcen – relevant für DORA/NIS2/ISO 27001. |
| IAM (RBAC, LDAP) | **Azure Entra ID**, Azure RBAC, Azure AD Connect / Entra Connect | Zentrale Identitäten, Rollen, Conditional Access; Integration mit On-Prem-LDAP/AD; Grundlage für least privilege & Zero Trust. |
| PAM | **Azure Entra Privileged Identity Management (PIM)** | Zeitlich begrenzte, genehmigungspflichtige Admin-Rollen, Governance & Justification-Logging – wichtig für ISO 27001, DORA. |
| Bastion Host | **Azure Bastion** | Sichere, browserbasierte RDP/SSH-Verbindungen ohne Public IPs auf VMs (z. B. Admin-Knoten, Jump Hosts). |
| Zertifikate & Secrets | **Azure Key Vault** (Secrets, Keys, Certificates) + ggf. **Managed HSM** | Zentrales Management von TLS-Zertifikaten, Schlüsseln (inkl. HSM-backed), Secret Rotation; Integrationen mit App Gateway, AKS, APIM, etc. |
---
### 3.3 Networking & Ingress
| Baustein | Azure-Service(s) | Zweck / Begründung |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| Load Balancer mit TLS-Terminierung | **Application Gateway** (L7, TLS-Offload) + interne **Azure Load Balancer** | TLS-Termination, SNI, Path-based Routing; interne Lastverteilung zwischen AKS-Knoten/Pods. |
| API-Gateway | **Azure API Management** | Throttling, AuthN/AuthZ (JWT/OAuth2/Entra), Versionierung, Request/Response-Transformation, zentraler Audit-Log-Punkt. |
| Netzwerksegmentierung | **Azure Virtual Network**, **NSG**, **Azure Firewall**, **Private Endpoints**, **Hub-Spoke-Architektur** | Trennung nach Zonen (Edge, App, Data, Admin), erzwungener Zugriff über Firewall, private Kommunikation zu PaaS-Services. |
---
### 3.4 Daten- & Storage-Layer
| Baustein | Azure-Service(s) | Zweck / Begründung |
| -------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| SQL-Datenbanken | **Azure SQL Database** / **Azure SQL Managed Instance** | Transaktionale Workloads, Konfigurationsdaten, Audit-Tables, referentielle Integrität. |
| NoSQL | **Azure Cosmos DB (Core API)** | Hochskalierbare, globale Dokument-/Key-Value-DB für Sessions, Konfiguration, Agent-States. |
| Object Store | **Azure Blob Storage / Data Lake Storage Gen2** | S3-ähnliche Object-Speicherung für Dokumente, Logs, Model-Checkpoints, Trainingsdaten. |
| Vektor-Datenbank | **Azure AI Search mit Vektorindex** | Verwaltete Vektorsuche für RAG, semantische Suche, Retrieval-Orchestrierung. |
| Redis Cache | **Azure Cache for Redis** | In-Memory-Cache für Sessions, Prompt-Kontext, Throttling, Rate-Limiting-Counter. |
| GraphDB | **Cosmos DB (Gremlin API)** oder **Azure SQL Graph** | Modellierung von Beziehungsnetzen (Entitäten, Events, Policies). |
| Big Data / Data Lake / DWH | **Data Lake Storage Gen2**, **Azure Synapse Analytics** oder **Fabric** | Historisierung, Advanced Analytics, Reporting, KI-Trainingsdaten. |
| Real-Time Analytics | **Azure Event Hubs**, **Stream Analytics**, **Azure Data Explorer / Synapse Data Explorer** | near real-time Monitoring, Fraud-Detection, Telemetrie-Auswertung. |
| Apache Kafka Router | **Azure Event Hubs (Kafka-kompatibler Endpoint)** | Kafka-API-kompatibles Event-Streaming ohne eigenen Kafka-Cluster. |
| Queues / MQ | **Azure Service Bus** (Queues/Topics) | Zuverlässige, transaktionale Nachrichten zwischen Services, Entkopplung. |
---
### 3.5 Frontend & Applikation
| Baustein | Azure-Service(s) | Zweck / Begründung |
| ------------------------ | --------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| Frontend als Container | Container auf **AKS** (separate Namespace) oder **Azure App Service for Containers** | Isoliertes Deployment der UI, Integration mit WAF/APIM, Identity via Entra ID (OIDC). |
| Git-Repos, Runner, CI/CD | **GitHub Enterprise** oder **Azure DevOps** (Repos, Pipelines), self-hosted Runner auf AKS/VM | Vollständige Code-Versionierung, Build/Deploy-Pipelines, Policy-Gates (Code-Scanning, Secrets-Scanning). |
| IDE-Integration | **GitHub Codespaces** / **Dev Box**, VS Code Remote | Sichere, cloudbasierte Dev- und Debug-Umgebungen mit Policy-Control. |
---
### 3.6 Observability & Operations
| Baustein | Azure-Service(s) | Zweck / Begründung |
| ------------------ | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Logging | **Azure Monitor Logs + Log Analytics**, Diagnostics Settings, Export zu Blob/Event Hub | Zentrale Sammlung von Infrastruktur-, App-, API- und Sicherheits-Logs; Grundlage für EU-AI-Act-Logging-Pflichten und ISO 27001-Kontrollen.([iks.fraunhofer.de][7]) |
| Monitoring | **Azure Monitor**, **Application Insights**, Container Insights | Verfügbarkeit, Performance, End-to-End-Traceability. |
| Metriken / Grafana | **Azure Managed Grafana** | Visualisierung von Kennzahlen (Latenz, Request-Fehler, Modell-Auslastung, GPU-Nutzung) – vollständig verwalteter Dienst.([Microsoft Learn][5]) |
| SIEM / SOC | **Microsoft Sentinel** + Anbindung an **Splunk** | Korrelation sicherheitsrelevanter Events, Detection-Regeln, Playbooks; Integration in bestehende SOC-Landschaft. |
---
### 3.7 Infrastructure as Code (IaC)
| Baustein | Azure-Service(s) | Zweck / Begründung |
| -------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| Terraform Deployment | **Terraform OSS/Cloud** + Backend in **Azure Storage** (verschlüsselt, private Endpoint) | Reproduzierbare Provisionierung von Netz, AKS, Datenbanken, Monitor, Sicherheitskomponenten. |
| Secrets für IaC | **Azure Key Vault** | Sichere Ablage von Service Principals, SSH-Keys etc.; Zugriff per Managed Identity der Pipelines. |
---
## 4. Compliance-Mapping (Tabelle – Auszug)
**Hinweis:** Stark vereinfacht; in einem echten Projekt würdest du pro Regulation eine viel granularere Kontrollliste pflegen.
| Regulierung / Anforderung | Architekturbaustein(e) | Technischer Beitrag |
| ------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| **EU AI Act – Logging & Traceability (Art. 12, 26)**([Künstliche Intelligenz Gesetz EU][8]) | Azure Monitor, Log Analytics, APIM-Logs, AKS Audit Logs, Data Lake für Log-Archiv | Vollständige Protokollierung von Input/Output, Modellaufrufen, Entscheidungen; Aufbewahrung > 6 Monate; revisionssichere Ablage. |
| **EU AI Act – Human Oversight (Art. 14)**([Künstliche Intelligenz Gesetz EU][9]) | Frontend Controls, Agent-Orchestrator, RBAC, Workflow-Engine (z. B. Logic Apps) | Manuelle Freigaben, Vier-Augen-Prinzip, Override- und Stop-Funktionen für KI-Entscheidungen. |
| **DSGVO – Datenminimierung & Zweckbindung** | Datenmodellierung in SQL/Cosmos, RAG-Architektur mit selektivem Kontext, APIM-Policies | Nur notwendige Attribute im Prompt-Kontext; strenge Scoping-Policies; Pseudonymisierung vor KI-Aufruf. |
| **DSGVO – Datenübermittlung & Residency** | Regionenauswahl EU (West/North Europe), Azure OpenAI EU Data-Zones | Sicherstellung, dass personenbezogene Daten die EU nicht verlassen; vertragliche & technische Kontrolle des Modellstandorts.([Microsoft Learn][2]) |
| **DSGVO – Sicherheit der Verarbeitung (Art. 32)** | Entra ID, RBAC, PIM, Key Vault, Verschlüsselung at rest/in transit | Starke AuthN/AuthZ, geringste Rechte, Verschlüsselung (Storage, DB, TLS), Schutz der Schlüssel. |
| **DORA – ICT Risk Management & Resilience** | Hub-Spoke-VNet, Azure Firewall, AKS mit Multi-AZ, Backup & DR-Strategie | Redundante Deployments, Netzsegmentierung, Backup/Restore, Test von Failover-Szenarien. |
| **DORA – Monitoring & Incident Reporting** | Azure Monitor, Sentinel, Defender for Cloud, SOC-Runbooks | Durchgängige Überwachung, Alarmierung, automatisierte Playbooks, strukturierte Incident-Daten für Reporting. |
| **NIS 2 – Security of Network & Information Systems** | VNet, NSGs, Firewall, WAF, Defender for Cloud | Schutz vor Netzangriffen, Härtung von Systemen, laufende Schwachstellen-Bewertung. |
| **ISO 27001 – A.9 Zugriffskontrolle** | Entra ID, RBAC, PIM, Bastion, APIM-Auth | Rollenbasierte Zugriffssteuerung, Just-in-Time-Privilegien, kontrollierte Admin-Zugriffe ohne Public IPs. |
| **ISO 27001 – A.12 Betriebs- & Änderungsmanagement** | Git-Repos, CI/CD, IaC (Terraform), Change-Approval Workflows | Versionierte Infrastruktur, klare Trennung von Umgebungen, dokumentierte Changes, Rückverfolgbarkeit. |
| **ISO 27001 – A.16 Incident Management** | Sentinel, Splunk, Playbooks, Runbooks | Standardisierte Erkennung, Behandlung und Dokumentation von Sicherheitsvorfällen. |
---
## 5. Security & Data Protection – Datenflüsse & Kontrollen
### 5.1 Datenflüsse
1. **Eingabe-Prompts & Kontextdaten**
* User → Frontend (TLS) → Front Door WAF → Application Gateway WAF → APIM
* APIM führt AuthN/AuthZ (Entra ID, OAuth2), Rate-Limiting und Input-Validierung durch.
* Prompt Firewall (APIM Policy + Content Safety) prüft Prompts auf **sensible Inhalte, PII, Policy-Verstöße**.
* Agent-Orchestrator auf AKS reichert Prompt mit **zugelassenem Kontext** aus Datenbanken / Vektorstore an.
2. **Model-Calls & Outputs**
* Orchestrator ruft Azure OpenAI (EU-Region / Data Zone) oder Self-hosted Model auf AKS per TLS auf.([Microsoft Learn][2])
* Outputs werden erneut durch Content Safety / Post-Filter geleitet (Policy-check; „Red-Team“-Regeln).
* Relevante Parameter (Modell, Version, Confidence Scores, Decision IDs) werden geloggt.
3. **Logs & Auditing**
* Alle Requests/Responses (ggf. pseudonymisiert) werden in Log Analytics und/oder Data Lake gespeichert.
* Audit Logs für Admin-Aktivitäten (PIM, AKS-Cluster-Admin, Key Vault Access) werden zentral gesammelt.
* Zugriff auf Logs nur via RBAC + PIM; Export zu Sentinel & Splunk für SOC-Auswertung.
### 5.2 Verschlüsselung (at rest / in transit)
* **At rest**
* Standardmäßig: Storage, Disk, SQL, Cosmos, Event Hubs, Service Bus → Transparent Data Encryption / SSE mit Microsoft-Managed Keys.
* Für höhere Anforderungen: **Customer-Managed Keys (CMK)** in Key Vault / Managed HSM; z. B. für SQL, Storage, Event Hubs.
* **In transit**
* Erzwingen von TLS 1.2+/1.3 auf allen Endpoints (APIM, AKS Ingress, OpenAI, DBs, Message-Broker).
* Interne Kommunikation über Private Endpoints + VNet.
### 5.3 Zugriffssteuerung & PAM
* **Identity First**:
* Alle User/Apps über **Entra ID** und **Managed Identities** authentifiziert.
* RBAC für Azure-Ressourcen, Kubernetes-RBAC für Clusterebene, App-Rollenkonzepte im Frontend/API.
* **PAM mit PIM**:
* Admin-Rollen (Subscription Owner, AKS Admin, Key Vault Admin) nur als **Just-in-Time**-Rollen mit Approval und begrenzter Dauer.
* **Zero Trust**:
* Conditional Access (MFA, Compliant Device), kein direkter Zugriff auf Produktionsressourcen ohne PIM und Bastion.
### 5.4 Protokollierung, Auditability, Nachvollziehbarkeit
* Protokollierung von:
* Benutzeraktionen (Frontends, APIs) mit Korrelations-IDs.
* Modellaufrufen: Prompt-Metadaten (ggf. pseudonymisiert), Modell-ID, Version, Entscheidung, Confidence.
* Datenzugriffe (SQL, Storage, Cosmos) über native Audit-Funktionen.
* Admin-Aktivitäten (PIM, Key Vault, AKS-Clusterrollen).
* Speicherung:
* Kurzfristig in **Log Analytics**, mittel-/langfristig in **Data Lake (immutable Storage)** zur Erfüllung gesetzlicher Aufbewahrungsfristen.
### 5.5 Data Residency & Souveränität
* Alle Schlüsselressourcen (AKS, SQL, Storage, OpenAI, Event Hubs, etc.) werden in EU-Regionen angelegt.
* Für Azure OpenAI: **EU-residente Konfiguration (Data Zones)**, um sicherzustellen, dass Prompts/Responses in der EU verarbeitet werden.([Microsoft Learn][2])
* Restriktive Firewall/NSG-Regeln, um ausgehenden Traffic zu begrenzen; optional Private DNS, keine Public Endpoints für interne Systeme.
### 5.6 Mitigation von Modell- & Prompt-Risiken
* **Prompt Injection & Jailbreaks**
* System-/Policy-Prompts zentral in Orchestrator verwaltet (nicht durch User überschreibbar).
* Prompt-Filter in APIM + Content Safety; Blacklists/Regex und semantische Checks.
* **Data Leakage**
* Pseudonymisierung / Maskierung sensibler Daten vor der Übergabe an LLM.
* Kein Speichern von Roh-Prompts in Logs ohne Maskierung; strikte Rollenrechte für Log-Zugriff.
* **Bias, Fairness, Explainability**
* Nutzung von Responsible-AI-Funktionen (z. B. Azure ML, externe Tooling) in Dev-/Testphase.([iks.fraunhofer.de][7])
---
## 6. Betriebs- & Lifecycle-Konzept
### 6.1 Versionierung, Test & Deployment von KI-Modellen / Agents
* **Repos & Branching**
* Code & Konfig (Infrastructure + App + Agents) in Git (Mono- oder Multi-Repo), Feature-Branches, PR-Gates.
* **Pipelines (CI/CD)**
* Build: Linting, Tests, Security-Scans (SAST, Secrets-Scanning, Dependency-Scanning).
* Container-Build in **Azure Container Registry** mit Signierung (Notary / cosign).
* Deployment per Helm/Kustomize auf AKS (Blue-Green/Canary via Ingress Controller + APIM).
* **MLOps**
* Modellversionierung, Evaluation gegen Testdatensätze, automatisierte Regressionstests.
* Staging-Umgebung mit Shadow Traffic, Auswertung von KPIs, Bias-/Drift-Checks, bevor Go-Live.
### 6.2 Monitoring, Alerting, Incident Response
* **Monitoring**
* Health-Checks auf API/Frontend/Agents (SLIs: Latenz, Error-Rate, Throughput).
* Business-KPIs (z. B. akzeptierte Anträge, manuelle Overrides, Review-Raten).
* **Alerting**
* Schwellenwert-basierte Alerts aus Azure Monitor (z. B. Error Rate > x%, Response Time > y ms).
* Security Alerts aus Defender / Sentinel (z. B. ungewöhnliche Zugriffe, Brute-Force, Anomalien).
* **Incident Response**
* Playbooks in **Sentinel** (z. B. automatisches Sperren eines API-Keys, Quarantäne von Nodes).
* Runbooks in **Automation** für Routineoperationen (Log-Rollover, Skalierung, Rotationen).
### 6.3 Schwachstellenmanagement (Vulnerability Management)
* **Container & Dependencies**
* Defender for Containers scannt Container-Images in ACR & Laufzeitumgebung.
* CVE-Reports → Integration in CI-Pipeline als Quality Gate.
* **OS & PaaS**
* Defender for Cloud überwacht VM-Guest-OS-Patching, Konfigurationsdrift, schwache Konfigurationen.
* **Regelmäßige Reviews**
* Monatliche Security-Review-Boards, Abgleich mit DORA/NIS2/ISO27001-Kontrollkatalogen.
### 6.4 Terraform & Konfigurationsmanagement
* **State-Management**
* Remote Backend (Azure Storage) mit RBAC, Private Endpoint, Soft Delete, Versioning aktiviert.
* **Policies & Guardrails**
* **Azure Policy** und **Blueprints** (oder Landing Zone Templates), um nur EU-Regionen, verschlüsselte Storage-Accounts, Private Endpoints etc. zuzulassen.
* **Drift Detection**
* Regelmäßige `terraform plan`-Runs und Compliance-Checks; Abweichungen werden als Incident behandelt.
---
Wenn du möchtest, kann ich im nächsten Schritt:
* ein **konkretes Beispiel-Setup** (Liste von Terraform-Ressourcen und Namespaces) skizzieren oder
* die **Compliance-Tabelle** weiter detaillieren (z. B. auf Ebene einzelner ISO-27001-Kontrollen).
[1]: https://artificialintelligenceact.eu/article/6/?utm_source=chatgpt.com "Article 6: Classification Rules for High-Risk AI Systems"
[2]: https://learn.microsoft.com/en-us/azure/ai-foundry/responsible-ai/openai/data-privacy?view=foundry-classic&utm_source=chatgpt.com "Data, privacy, and security for Azure Direct Models in ..."
[3]: https://digital-strategy.ec.europa.eu/en/policies/regulatory-framework-ai?utm_source=chatgpt.com "AI Act | Shaping Europe's digital future - European Union"
[4]: https://learn.microsoft.com/de-de/azure/web-application-firewall/afds/afds-overview?utm_source=chatgpt.com "Was ist Azure Web Application Firewall für Azure Front Door?"
[5]: https://learn.microsoft.com/en-us/azure/managed-grafana/overview?utm_source=chatgpt.com "What is Azure Managed Grafana?"
[6]: https://21medien.de/en/library/azure-openai?utm_source=chatgpt.com "Azure OpenAI Service - 21medien AI Library"
[7]: https://www.iks.fraunhofer.de/content/dam/iks/documents/whitepaper-eu-ai-act-fraunhofer-iks.pdf?utm_source=chatgpt.com "Whitepaper The European Artificial Intelligence Act"
[8]: https://artificialintelligenceact.eu/article/26/?utm_source=chatgpt.com "Article 26: Obligations of Deployers of High-Risk AI Systems"
[9]: https://artificialintelligenceact.eu/article/14/?utm_source=chatgpt.com "Article 14: Human Oversight | EU Artificial Intelligence Act"
@@ -0,0 +1,287 @@
1. Analyze the EU AI Act, GDPR, DORA, NIS 2, and ISO 27001 compliance requirements for AI operations in the Azure cloud.
2. Identify Azure components for Kubernetes cluster management, including AKS for container orchestration and Azure Container Registry for image storage.
3. Select Azure components for agentic AI and LLM adapter, such as Azure Cognitive Services, Azure Machine Learning, and Azure Functions.
4. Choose Azure components for WAF and prompt firewall, like Azure Web Application Firewall and Azure Front Door.
5. Identify Azure components for AI model scanning and AI interface scanning, such as Azure Security Center and Azure Sentinel.
6. Select Azure components for frontend containerization, load balancing with TLS termination, and LLM routing, like Azure App Service, Azure Load Balancer, and Azure API Management.
7. Choose Azure components for IAM, RBAC, LDAP, and PAM, such as Azure Active Directory, Azure Role-Based Access Control, and Azure Privileged Identity Management.
8. Identify Azure components for the database layer, including Azure SQL Database, Azure Cosmos DB, Azure Blob Storage, Azure Vector Database, Azure Redis Cache, and Azure Graph Database.
9. Select Azure components for big data processing, such as Azure Synapse Analytics, Azure Data Lake Storage, and Azure Databricks.
10. Choose Azure components for Apache Kafka routing, logging, monitoring, and real-time analytics, like Azure Event Hubs, Azure Monitor, Azure Log Analytics, and Azure Stream Analytics.
11. Identify Azure components for Git repos, runners, pipelines, CI/CD, and IDE, such as Azure DevOps, Azure Pipelines, and Azure Repos.
12. Select Azure components for metrics and vulnerability management, like Azure Grafana and Azure Security Center.
13. Choose Azure components for queues and MQ, such as Azure Service Bus and Azure Event Grid.
14. Identify Azure components for building, testing, and deploying AI agents, like Azure DevOps, Azure Pipelines, and Azure Machine Learning.
15. Select Azure components for Terraform and Bastion host, such as Azure Terraform and Azure Bastion.
16. Choose Azure components for Splunk integration, like Azure Monitor and Azure Log Analytics.
17. Identify Azure components for public and private certificate management, such as Azure Key Vault and Azure Certificate Services.
18. Design a comprehensive architecture diagram incorporating all the identified Azure components and their interactions.
19. Create a detailed deployment plan, including resource provisioning, configuration, and integration steps for each Azure component.
20. Develop a compliance checklist to ensure the proposed architecture meets the EU AI Act, GDPR, DORA, NIS 2, and ISO 27001 requirements.
# Architekturvorschlag für den konformen KI-Betrieb auf Microsoft Azure unter Einhaltung von EU AI Act, DSGVO, DORA, NIS 2 und ISO 27001
> - Hochskalierbare, sichere und konforme KI-Architektur auf Azure mit klarer Trennung der Layer: Data, AI/ML, Application, Security, Operations, CI/CD.
> - Integration spezifischer Azure-Dienste wie AKS, Azure Machine Learning, Azure API Management, Azure Sentinel und Azure Defender für Cloud.
> - Umfassendes Compliance-Mapping der Azure-Komponenten zu EU AI Act (Hochrisiko-KI), DSGVO (Datenschutz, Datenminimierung), DORA (Resilienz im Finanzsektor), NIS 2 (Cybersicherheit) und ISO 27001 (ISMS).
> - Implementierung von Zero Trust, Datenhoheit (EU-Residenz), Auditierbarkeit (Immutable Logs) und Zugriffskontrollen (RBAC, PAM).
> - DevSecOps- und Security-by-Design-Ansatz mit automatisierten CI/CD-Pipelines, Vulnerability Scanning und Incident Response.
---
## 1. Übersicht der Architektur und Compliance-Mapping
### Architekturdiagramm
Die Architektur ist als mehrschichtiges System konzipiert, das die folgenden Layer umfasst:
- **Data Layer**: Datenhaltung und -verarbeitung mit Azure SQL DB, Azure Cosmos DB, Azure Blob Storage, Azure Vector Database, Azure Redis Cache und Azure Graph Database.
- **AI/ML Layer**: KI-Modellentwicklung, Training und Inference mit Azure Machine Learning (AML), Azure Cognitive Services, Azure OpenAI Service und Azure Functions für Agentic AI.
- **Application Layer**: Frontend und API-Gateway mit Azure App Service, Azure Load Balancer, Azure API Management und Azure Application Gateway.
- **Security Layer**: Schutzmaßnahmen mit Azure Web Application Firewall (WAF), Azure Front Door, Azure Sentinel, Azure Defender for Cloud und Azure Key Vault für Zertifikatsmanagement.
- **Operations Layer**: Überwachung, Logging und Incident Response mit Azure Monitor, Azure Log Analytics, Azure Event Hubs und Azure Stream Analytics.
- **CI/CD Layer**: Automatisierte Build-, Test- und Deployment-Pipelines mit Azure DevOps, Azure Pipelines und Azure Repos.
### Compliance-Mapping-Tabelle
| **Regulatorische Anforderung** | **Azure-Komponente** | **Erfüllung der Anforderung** | **Hinweise** |
|------------------------------------|--------------------------------------|----------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|
| **EU AI Act (Hochrisiko-KI)** | Azure Machine Learning (AML) | Risikoklassifizierung, Dokumentation, Transparenz, Bias-Detection, Explainability | AML Responsible AI Dashboard, Model Catalog, Prompt Flow für Governance und Auditierbarkeit |
| **DSGVO (Datenschutz)** | Azure SQL DB, Azure Cosmos DB, Azure Blob Storage | Datenverschlüsselung, Zugriffskontrolle, Datenminimierung, Löschkonzept | Always Encrypted, Immutable Blob Storage, Azure Purview für Datenklassifizierung und -labeling |
| **DORA (Resilienz Finanzsektor)** | Azure Event Hubs, Azure Stream Analytics, Azure Monitor | Kontinuierliches Monitoring, Resilienztests, Incident Response, Audit-Trails | Integration mit Azure Sentinel für SIEM und automatisierte Playbooks |
| **NIS 2 (Cybersicherheit)** | Azure Sentinel, Azure Defender for Cloud, Azure WAF, Azure Bastion | Risikomanagement, Vorfallsmeldung, Zugriffskontrolle, Netzwerksegmentierung, PAM | Azure Bastion für sichere VM-Zugriffe, Azure WAF für Webanwendungen, Defender für Vulnerability Scanning |
| **ISO 27001 (ISMS)** | Azure Policy, Azure RBAC, Azure Key Vault, Azure Monitor | Risikoanalyse, Sicherheitsziele, Dokumentation, interne und externe Audits | Azure Policy für Compliance-Enforcement, Key Vault für Zertifikatsmanagement, Monitor für Logging und Alerting |
---
## 2. Detaillierte Komponentenauswahl mit Azure-Diensten
### a) Kubernetes & Container-Orchestration
**Zweck**: Skalierbare, isolierte Ausführung von KI-Workloads (Training/Inference), Multi-Tenancy-Fähigkeit, Compliance mit EU AI Act (Transparenz, Dokumentation).
**Azure-Komponenten**:
- **Azure Kubernetes Service (AKS)** mit:
- Confidential Computing-Nodes (für sensible Datenverarbeitung, DSGVO-konform).
- AKS Workload Identity (statt Service Principals für sichere Pod-Identitäten, IAM-Integration).
- Azure Policy + Gatekeeper (Enforcement von Compliance-Richtlinien wie "keine privileged Container").
- AKS Node Pools mit Spot Instances (Kosteneffizienz) + dedizierte Node Pools für Hochrisiko-KI (Isolation nach EU AI Act).
- Azure Container Registry (ACR) mit Content Trust (Notarization) und Vulnerability Scanning (integriert in CI/CD).
**Begründung**: AKS bietet automatisiertes Patch-Management (NIS 2), Network Policies (Microsegmentierung) und Azure Monitor für AKS (Logging/Metriken).
**Compliance-Hinweis**: KI-Modell-Artefakte werden in Containern versioniert und unveränderlich gespeichert (ISO 27001:2022 A.12.3.1) durch Integration mit Azure DevOps und ACR.
---
### b) Agentic AI mit LLM-Adapter
**Zweck**: Orchestrierung autonomer KI-Agenten mit Prompt-Sicherheit, Halluzinationskontrolle und Audit-Trails.
**Azure-Komponenten**:
- **Azure Machine Learning (AML)** für:
- Prompt Flow (Versionierung und Governance von Prompts, EU AI Act-Konformität).
- Model Catalog (Metadaten-Management für LLM-Adaptionen, inkl. Risikoklassifizierung).
- AML Responsible AI Dashboard (Bias-Detection, Explainability für EU AI Act Art. 13).
- **Azure OpenAI Service** (mit private Endpoints und Customer-Managed Keys (CMK) für Datenhoheit).
- **Azure Functions/Durable Functions** (serverless Agent-Orchestration mit Retries & Dead-Letter Queues für Resilienz).
**Begründung**: AML bietet built-in Compliance-Templates (z. B. für DSGVO-Löschanfragen via Data Subject Requests).
**Offene Frage**: Agent-Aktionen werden über Azure Monitor und Azure Log Analytics protokolliert, um DORA-Anforderungen an "Complete Activity Logs" zu erfüllen.
---
### c) Security Layer (WAF, Prompt Firewall, AI-Scanning)
**Zweck**: Schutz vor Prompt Injections, Datenexfiltration und Model Poisoning (NIS 2, ISO 27001 A.14).
**Azure-Komponenten**:
- **Azure Web Application Firewall (WAF)** auf Azure Front Door (OWASP Top 10 Abdeckung, Rate Limiting).
- **Prompt Firewall**:
- Azure API Management (APIM) mit Custom Policies (Regex/ML-basierte Prompt-Validation).
- AML Content Safety (Toxizitätsfilterung + Custom Rules für domänenspezifische Compliance).
- **AI Model Scanning**:
- AML Model Scanning (Schadcode in Modellen, z. B. via Trivy-Integration in Pipelines).
- Azure Defender for Containers (Runtime-Schutz für KI-Worker).
- **AI Interface Scanning**:
- Microsoft Defender for APIs (in APIM integriert, Detects Anomalies in LLM-Aufrufen).
**Begründung**: Kombiniert Pre-Deployment Scanning (CI/CD) mit Runtime Protection (Defender).
**Compliance-Hinweis**: Scanning-Ergebnisse werden für Audits (EU AI Act Art. 72) 10 Jahre in Azure Monitor Log Analytics gespeichert.
---
### d) Frontend & API-Gateway
**Zweck**: Sichere Exposition von KI-Services mit TLS 1.3, mTLS und Rate Limiting.
**Azure-Komponenten**:
- **Frontend**: Azure Static Web Apps (Container-basiert, mit Managed Identity für Backend-Zugriff).
- **Load Balancer**: Azure Load Balancer (Layer 4) + Application Gateway (Layer 7, TLS-Terminierung, WAF-Integration).
- **API Gateway**: Azure API Management (APIM) mit:
- OAuth2/JWT Validation (IAM-Integration).
- Policy Expressions für Request/Response Transformation (z. B. PII-Redaktion).
- Developer Portal (Dokumentation für EU AI Act-Transparenz).
- **LLM Router**: Azure Traffic Manager (Global Routing) + APIM Routing Rules (A/B-Testing, Canary Deployments).
**Begründung**: APIM bietet Quota Management (DDoS-Schutz) und Usage Analytics (DORA-Reporting).
---
### e) IAM & PAM (RBAC, LDAP, Just-in-Time-Zugriff)
**Zweck**: Least Privilege, Separation of Duties (ISO 27001 A.9.1.2) und Notfallzugriff (DORA).
**Azure-Komponenten**:
- **Azure Active Directory (AAD)** mit:
- Privileged Identity Management (PIM) (Just-in-Time Admin-Zugriff).
- Conditional Access Policies (MFA, Device Compliance).
- Entra Permissions Management (Cloud Infrastructure Entitlement Management, CIEM).
- **LDAP**: Azure AD Domain Services (für Legacy-Systeme, read-only Replicas).
- **Bastion Host**: Azure Bastion (RDP/SSH ohne öffentliche IPs, Session Recording für Audits).
**Begründung**: AAD Access Reviews erfüllen DSGVO-Recertification (Art. 32).
**Offene Frage**: Break-Glass-Zugriff (DORA) wird über PIM mit zeitlich begrenzten Rollen und MFA umgesetzt, um Compliance nicht zu brechen.
---
### f) Datenlayer (SQL, NoSQL, Vektordatenbank, Cache, GraphDB, S3)
**Zweck**: Datenminimierung (DSGVO), Verschlüsselung (NIS 2), Performance für KI.
**Azure-Komponenten**:
- **SQL**: Azure SQL DB mit Always Encrypted (Client-side) + Ledger (unveränderliche Tabellen für Audits).
- **NoSQL**: Azure Cosmos DB (Global Distribution, Customer-Managed Keys).
- **Vektordatenbank**: Azure AI Search (mit Vector Index) oder Weaviate/Pinecone auf AKS (falls Open-Source erforderlich).
- **Object Store**: Azure Blob Storage mit Immutable Blob Storage (DSGVO-Löschsperren).
- **Redis Cache**: Azure Cache for Redis (Enterprise Tier mit TLS und AAD-Auth).
- **GraphDB**: Azure Cosmos DB Gremlin API oder Neptune auf AKS (für Knowledge Graphs).
**Begründung**: Azure Purview klassifiziert und labelt Daten automatisch (DSGVO Art. 30).
**Compliance-Hinweis**: Datenresidenz (EU-only) für Kafka-Topics und Cosmos DB wird durch Azure Policy und Azure Monitor erzwungen.
---
### g) Big Data & Echtzeit-Analytics
**Zweck**: Skalierbare Datenpipelines für Model Training/Monitoring (EU AI Act Art. 10).
**Azure-Komponenten**:
- **Apache Kafka**: Azure Event Hubs (Kafka-kompatibel) + MirrorMaker für Multi-Region.
- **Stream Processing**: Azure Stream Analytics (SQL-basierte Echtzeit-Aggregation).
- **Batch Processing**: Azure Databricks (mit Delta Lake für ACID-Compliance).
- **Data Lake**: Azure Data Lake Storage (ADLS) Gen2 mit Hierarchical Namespace.
**Begründung**: Event Hubs Geo-DR erfüllt NIS 2-Anforderungen an Ausfallsicherheit.
---
### h) Logging, Monitoring & Vulnerability Management
**Zweck**: Immutable Logs (DORA), Anomalieerkennung (NIS 2), Compliance-Reporting.
**Azure-Komponenten**:
- **Logging**:
- Azure Monitor (AKS, APIM, SQL Logs) + Log Analytics Workspace (7 Jahre Retention).
- Azure Storage Lifecycle Management (Automatische Archivierung alter Logs).
- **Monitoring**:
- Grafana auf Azure Managed Grafana (mit Azure Monitor Datenquelle).
- Azure Dashboards für SLO/SLI-Tracking (DORA-Metriken).
- **Vulnerability Management**:
- Microsoft Defender for Cloud (CVE-Scanning, Regulatory Compliance Dashboard).
- Azure Security Benchmark (NIS 2-Alignment).
- **Splunk**: Azure Native Splunk Integration (für SIEM, falls erforderlich).
**Begründung**: Defender for Cloud bietet automatisierte Response Playbooks (ISO 27001 A.16.1).
---
### i) CI/CD & DevSecOps (Git, Pipelines, IDE, Agent Builds)
**Zweck**: Compliance-as-Code (ISO 27001 A.14.2.5) und auditierbare Deployments.
**Azure-Komponenten**:
- **Git Repos**: Azure Repos (mit Branch Policies für Code Reviews).
- **Pipelines**: Azure Pipelines mit:
- Static Application Security Testing (SAST) via Checkmarx oder SonarQube.
- Dynamic Scanning in Load Tests (Azure Load Testing).
- Terraform: Azure Bicep (native IaC) + Terraform in Azure DevOps (mit Plan Policy Validation).
- **IDE**: VS Code + Azure DevOps Extension (mit Roslyn Analyzers für Secure Coding).
- **Agent Builds**: Azure VM Scale Sets (ephemere Agenten für Sicherheit).
**Begründung**: Pipeline Compliance Reports (z. B. "Keine Hardcoded Secrets") für Audits.
---
### j) Queues & Message Broker
**Zweck**: Entkopplung von KI-Workloads (Resilienz nach DORA).
**Azure-Komponenten**:
- **Azure Service Bus** (FIFO, Dead-Letter Queues) oder Azure Queue Storage (für einfache Szenarien).
- **Event-Driven Architecture**: Azure Event Grid (für KI-Trigger, z. B. neue Daten in Blob Storage).
---
### k) Zertifikatsmanagement (öffentlich/privat)
**Zweck**: TLS Everywhere (NIS 2) und Code Signing (EU AI Act).
**Azure-Komponenten**:
- **Azure Key Vault** (mit HSM-backed Keys für Code Signing).
- **Azure App Service Certificates** (automatische Rotation).
- **Private CA**: Azure Private Link + DigiCert/GlobalSign Integration.
---
## 3. Cross-Cutting Concerns & Risikomitigation
### Datenflüsse
- **Datenflussdiagramm (DFD)**: Markierung von DSGVO-relevanten Verarbeitungen (z. B. PII in LLM-Prompts).
- **Incident Response**: Azure Sentinel Playbooks für KI-spezifische Vorfälle (z. B. Model Drift, Data Leakage).
- **Cost Optimization**: Azure Cost Management + Billing und Reserved Instances (für AKS/Cosmos DB).
- **Vendor Lock-in**: Bewertung von Open-Source-Alternativen (z. B. Kubernetes statt AKS, OpenSearch statt Azure AI Search).
---
## 4. Empfohlene Next Steps & Proof-of-Concept
- **Priorisierte Implementierungsschritte**:
1. AKS mit Policy Guardrails,
2. APIM + WAF,
3. Azure Sentinel Integration,
4. Azure DevOps CI/CD Pipeline mit Security Scanning.
- **POC-Umfang**: Isoliertes AKS-Cluster mit AML und APIM für einen einzelnen KI-Agenten.
- **Stakeholder-Kommunikation**: Compliance-Readiness-Dokument für interne Audits.
---
## Anhang
- **Architekturdiagramm**: Visio/Lucidchart mit Legende für Compliance-Symbole.
- **Tabelle**: Mapping von Azure-Diensten zu Compliance-Anforderungen (DSGVO, NIS 2 etc.).
- **Terraform/Bicep-Snippets**: Kritische Komponenten (z. B. AKS mit Policy, Key Vault Setup).
- **Beispiel-Pipeline**: YAML für sicheres KI-Agent Deployment.
---
## Quellen
- EU AI Act, GDPR, DORA, NIS 2, ISO 27001 Guidelines.
- Azure Kubernetes Service (AKS) Dokumentation.
- Azure Machine Learning (AML) Dokumentation.
- Azure API Management (APIM) Dokumentation.
- Azure Sentinel und Defender for Cloud Dokumentation.
- Azure DevOps und Azure Pipelines Dokumentation.
- Azure Monitor und Log Analytics Dokumentation.
- Azure Key Vault und Certificate Services Dokumentation.
- Azure Event Grid und Service Bus Dokumentation.
---
Diese Architektur stellt einen umfassenden, regulatorisch konformen und technisch robusten Vorschlag für den KI-Betrieb auf Microsoft Azure dar, der die Anforderungen von EU AI Act, DSGVO, DORA, NIS 2 und ISO 27001 adressiert und gleichzeitig Skalierbarkeit, Observability, Security-by-Design und DevSecOps-Prinzipien integriert.
@@ -0,0 +1,187 @@
Hier ist eine leicht gestraffte und weiter präzisierte Version, die du so verwenden kannst:
---
Du bist **Azure Cloud Senior Architect** mit Schwerpunkt **Security, Compliance und KI-Plattformen** in regulierten Umgebungen (Finanz, Kritische Infrastrukturen, Behörden).
---
### 1. Auftrag
Erstelle einen **detaillierten Architekturvorschlag** für den **Betrieb von KI-Workloads auf Microsoft Azure**, der **konform** ist zu:
* **EU AI Act** (insb. Risikoklassen, Technical & Organizational Measures, Logging, Human Oversight)
* **DSGVO (GDPR)**
* **DORA**
* **NIS 2**
* **ISO 27001**
Die Architektur soll sowohl **sicherheits-** als auch **compliance-orientiert** sein und klar zeigen, wie regulatorische Anforderungen **technisch umgesetzt** werden.
Treffe, falls nötig, eigene **Annahmen** (z. B. Branche, Datenklassifizierung, Kritikalität) und liste sie zu Beginn explizit auf.
---
### 2. Rahmenbedingungen & Zielbild
Die Lösung basiert **vollständig auf Microsoft Azure** (Azure-native oder Azure-verwaltete Services) und stellt den Betrieb in **EU-Regionen** sicher (z. B. *West Europe* / *North Europe*) zur Erfüllung von **Data Residency**-Anforderungen.
Folgende technische Komponenten sind zu berücksichtigen und jeweils konkret mit Azure-Services zu hinterlegen:
#### 2.1 KI- und Compute-Layer
* Kubernetes-Cluster mit KI-Workern und Container-/Cluster-Management
* Agentic AI mit LLM-Adapter (z. B. orchestrierte KI-Agents)
* Build, Test und Deploy von AI Agents (MLOps / AIOps)
* LLM-Router (Routing zwischen verschiedenen Modellen / Providern, inkl. Azure OpenAI und ggf. Self-Hosted Models)
#### 2.2 Security & Governance
* Web Application Firewall (WAF)
* Prompt Firewall / Prompt Security
* AI-Model Scanning (Model Security, Supply Chain Security)
* AI-Interface Scanning (Security von APIs / Endpoints / UIs)
* Vulnerability Management
* IAM (RBAC, Anbindung an LDAP/Azure Entra ID)
* PAM (Privileged Access Management)
* Bastion Host
* Öffentliche und private Zertifikate inkl. Lifecycle- und Secrets-Management
#### 2.3 Networking & Ingress
* Load Balancer mit TLS-Terminierung
* API-Gateway
* Netzwerksegmentierung, Private Endpoints, ggf. Hub-Spoke-Architektur und Zero-Trust-Prinzipien
#### 2.4 Daten- & Storage-Layer
* Datenbank-Layer mit:
* SQL-Datenbanken
* NoSQL-Datenbanken
* Object Stores (S3-ähnlich / Blob Storage)
* Vektor-Datenbank
* Redis Cache
* GraphDB
* Big Data / Data Lake / Data Warehouse
* Real-Time Analytics
* Apache Kafka Router (Event Streaming)
* Queues / Message Queues (MQ)
#### 2.5 Frontend & Applikations-Layer
* Frontend als Container-Deployment
* Git-Repositories, Runner, CI/CD-Pipelines und IDE-Integration
#### 2.6 Observability & Operations
* Logging (zentrale, revisionssichere Protokollierung)
* Monitoring
* Metriken (z. B. Visualisierung über Grafana)
* SIEM/SOC-Integration (z. B. Splunk, Azure-native Alternativen)
#### 2.7 Infrastructure as Code
* Deployment mit Terraform (inkl. State-Handling, Workspaces, Pipelines)
---
### 3. Konkrete Anforderungen an deine Antwort
#### 3.1 Azure-Service-Mapping (sehr detailliert)
* Nenne **für jede** der oben genannten Komponenten die **konkreten Azure-Services**, z. B.:
* „Azure Kubernetes Service (AKS) für …“
* „Azure API Management für …“
* „Azure Front Door / Azure Application Gateway mit WAF für …“
* „Azure Key Vault für Zertifikats- und Secrets-Management“
* „Azure Monitor / Log Analytics / Application Insights für …“
* usw.
* Erkläre **kurz den Zweck** jedes Services in dieser Architektur und **warum** er für den jeweiligen Baustein geeignet ist.
* Wenn es **mehrere Optionen** gibt (z. B. Front Door vs. Application Gateway), begründe die **präferierte Wahl**.
Nutze nach Möglichkeit eine **Tabelle „Azure-Service vs. Zweck“**.
---
#### 3.2 Compliance-Mapping
Erstelle eine **Tabelle**, die zeigt, welche Architekturbausteine (Services / Patterns) **welche Anforderungen** aus
* EU AI Act
* DSGVO
* DORA
* NIS 2
* ISO 27001
adressieren, z. B.:
* Logging & Audit
* Data Residency & Data Protection
* Verschlüsselung at rest / in transit
* Zugriffskontrolle (RBAC, PAM, Least Privilege)
* Risikomanagement & Schwachstellenmanagement
* Monitoring, Incident Detection & Incident Response
* Business Continuity / Resilienz / Verfügbarkeit
---
#### 3.3 Architekturübersicht
* Beschreibe zunächst eine **High-Level-Architektur** (Schichtenmodell), z. B.:
**User → Edge/WAF → API Gateway → LLM Router / AI Agents (auf AKS) → Data Layer → Observability / Security Layer**
* Ergänze ein **textuelles Architekturdiagramm** (z. B. in **Mermaid** oder alternativ als klar strukturierte hierarchische Liste), das die wichtigsten Komponenten und ihre Beziehungen zeigt.
---
#### 3.4 Security- & Data-Protection-Aspekte
Gehe explizit auf **Datenflüsse** ein (Eingabe-Prompts, Kontextdaten, Model-Outputs, Logs) und erkläre, wie:
* Daten **verschlüsselt** werden (at rest / in transit) inkl. Nutzung von Managed Identities, TLS und Key Vault
* **Zugriffe gesteuert** werden (RBAC, Azure Entra ID, PAM, Just-in-Time Access / JIT-Access)
* **Protokollierung, Auditability und Nachvollziehbarkeit** umgesetzt werden (z. B. Audit-Logs, Access-Logs, Model-Usage-Logs)
* **Data Residency** (EU-Regionen, ggf. strikte Datenlokation) sichergestellt wird
* **Modell- und Prompt-Risiken** (Prompt Injection, Data Leakage, Model Abuse) mitigiert werden (z. B. Prompt Firewall, Content Filter, Policy Enforcement)
---
#### 3.5 Betrieb & Lifecycle
Erläutere, wie:
* neue KI-Modelle / Agents **versioniert, getestet und ausgerollt** werden
* CI/CD-Pipelines (z. B. GitHub Actions / Azure DevOps)
* Blue-Green- / Canary-Deployment auf AKS
* Rollback-Strategien
* **Monitoring, Alerting und Incident Response** organisiert sind
* Metriken, Logs, Traces
* Alerts (z. B. via Azure Monitor)
* Integration in SOC / SIEM (Splunk oder Microsoft Sentinel)
* **Schwachstellenmanagement** (Vulnerability Management) in Container-Images, Bibliotheken und Modellen integriert wird
* Image-Scanning, Dependency-Scanning
* regelmäßige Security-Updates / Patch-Mechanismen
---
### 4. Ausgabeformat
Strukturiere deine Antwort mit folgenden Hauptüberschriften:
1. Überblick & Annahmen
2. Zielarchitektur (High Level)
3. Azure-Service-Mapping pro Baustein
4. Compliance-Mapping (Tabelle)
5. Security & Data Protection
6. Betriebs- & Lifecycle-Konzept
Verwende mindestens diese **Tabellen**:
* **Tabelle 1:** Azure-Komponenten vs. Zweck / Layer
* **Tabelle 2:** Regulatorische Anforderung vs. Architekturbaustein (Service / Pattern)
Antworte auf **Deutsch**, **präzise und technisch**, mit **konkreten Azure-Service-Namen** und **technischen Details** statt allgemeiner Beschreibungen.
@@ -0,0 +1,85 @@
# Rolle
Du bist ein Azure Cloud Senior Architekt mit Expertise in regulatorischer Compliance (EU AI Act, DSGVO, DORA, NIS 2) und Informationssicherheit (ISO 27001).
# Aufgabe
Erstelle einen detaillierten Architekturvorschlag für eine KI-Betriebsplattform auf Microsoft Azure, die alle genannten regulatorischen Anforderungen erfüllt.
# Anforderungen an das Ergebnis
## 1. Architektur-Dokumentation
Für jede der folgenden Komponenten benötige ich:
- Die empfohlene Azure-Service(s) mit vollständigem Produktnamen
- Begründung der Auswahl
- Relevante Compliance-Aspekte (welche Regularien werden adressiert)
- Konfigurationsempfehlungen für den regulatorischen Kontext
## 2. Zu berücksichtigende Komponenten
### Compute & Container
- Kubernetes-Cluster für KI-Worker
- Container- und Cluster-Management
- Frontend-Container
- Build-, Test- und Deploy-Umgebung für AI Agents
### KI-spezifische Komponenten
- Agentic AI mit LLM-Adapter
- LLM Router
- Prompt Firewall
- AI Model Scanning
- AI Interface Scanning
### Netzwerk & Security
- Web Application Firewall (WAF)
- Load Balancer mit TLS-Terminierung
- API Gateway
- Bastion Host
- Öffentliche und private Zertifikate inkl. Management
### Identity & Access
- IAM (RBAC, LDAP-Integration)
- Privileged Access Management (PAM)
### Daten-Layer
- SQL-Datenbank
- NoSQL-Datenbank
- Object Storage (S3-kompatibel)
- Vektordatenbank
- Redis Cache
- Graph-Datenbank
- Big Data Platform
### Messaging & Integration
- Apache Kafka / Event Streaming
- Message Queues (MQ)
### DevOps & CI/CD
- Git Repositories
- Runner und Pipelines
- IDE-Integration
- Terraform (Infrastructure as Code)
### Observability & Security Operations
- Logging (inkl. SIEM/Splunk-Integration)
- Monitoring
- Real-Time Analytics
- Metriken-Dashboards (Grafana-kompatibel)
- Vulnerability Management
## 3. Compliance-Mapping
Erstelle eine Matrix, die zeigt, welche Architekturkomponente welche Anforderung der folgenden Regularien adressiert:
- EU AI Act (insb. Hochrisiko-KI-Systeme)
- DSGVO (Datenschutz, Datenverarbeitung, Betroffenenrechte)
- DORA (Operative Resilienz, ICT-Risikomanagement)
- NIS 2 (Cybersicherheit kritischer Infrastrukturen)
- ISO 27001 (ISMS-Kontrollen)
## 4. Ausgabeformat
- Strukturierte Darstellung nach logischen Architektur-Ebenen (z.B. Netzwerk, Compute, Data, Security, DevOps)
- Tabellarische Übersicht: Komponente | Azure Service | Compliance-Relevanz
- Architekturdiagramm-Beschreibung (textuell), die als Grundlage für ein Visio/Draw.io-Diagramm dienen kann
## 5. Zusätzliche Hinweise
- Bevorzuge Azure-native Services gegenüber Third-Party-Lösungen, sofern funktional gleichwertig
- Berücksichtige Azure Landing Zones und das Cloud Adoption Framework
- Beachte Data Residency (EU-Region) für alle personenbezogenen Daten
- Schlage eine sinnvolle Netzwerksegmentierung vor (Hub-Spoke, Private Endpoints)
@@ -0,0 +1,102 @@
flowchart LR
subgraph Clients
U[User / Apps]
end
subgraph Edge
AFD[Azure Front Door + WAF]
AGW[Application Gateway WAF + TLS]
AFW[Azure Firewall]
end
subgraph API
APIM[Azure API Management\n(API Gateway + Policies)]
PF[Prompt Firewall\n(Content Safety + APIM Policies)]
end
subgraph AI_Compute[AI & Compute Layer (AKS)]
AKS[AKS Cluster\nGPU/CPU Node Pools]
LLMR[LLM Router Service]
AGENTS[Agentic AI Orchestrator\n(AI Agents)]
FE[Frontend Container]
end
subgraph AI_Services
AOAI[Azure OpenAI / Azure AI Foundry\n(EU Data Residency)]
MODELS[Self-hosted Models on AKS]
end
subgraph Data[Data & Storage Layer]
SQL[Azure SQL DB / MI]
COSMOS[Azure Cosmos DB\n(NoSQL + Graph)]
BLOB[Azure Data Lake / Blob Storage]
VECTOR[Azure AI Search\n(Vektorindex)]
REDIS[Azure Cache for Redis]
KUSTO[Azure Data Explorer / Synapse]
end
subgraph Events
EH[Azure Event Hubs (Kafka Endpoint)]
SB[Azure Service Bus (Queues/Topics)]
SA[Azure Stream Analytics]
end
subgraph Observability[Observability & Security]
AM[Azure Monitor + Log Analytics]
APPINS[Application Insights]
GRAF[Azure Managed Grafana]
SENT[Microsoft Sentinel]
SPL[SPLUNK (VM/AKS)]
DEF[Microsoft Defender for Cloud]
end
subgraph Identity_Sec[Identity & Access]
ENTRA[Azure Entra ID\n(RBAC, Conditional Access)]
PIM[Entra Privileged Identity Mgmt]
KV[Azure Key Vault + Managed HSM]
BAST[Azure Bastion]
end
subgraph DevOps[DevOps / MLOps / IaC]
GIT[GitHub / Azure DevOps Repos]
PIPE[CI/CD Pipelines\n(GitHub Actions / Azure Pipelines)]
TF[Terraform\n(State in Storage)]
end
U --> AFD --> AGW --> APIM --> PF --> LLMR --> AGENTS
AGENTS --> AOAI
AGENTS --> MODELS
LLMR --> AOAI
LLMR --> MODELS
AGENTS --> SQL
AGENTS --> COSMOS
AGENTS --> BLOB
AGENTS --> VECTOR
AGENTS --> REDIS
AGENTS --> EH
EH --> SA --> KUSTO
AGENTS --> SB
AKS --> AM
AKS --> APPINS
AM --> GRAF
AM --> SENT
AM --> SPL
DEF --> SENT
ENTRA --> APIM
ENTRA --> AKS
ENTRA --> GIT
PIM --> ENTRA
KV --> AGW
KV --> APIM
KV --> AKS
BAST --> AKS
GIT --> PIPE --> AKS
PIPE --> TF
TF --> AKS
TF --> Data
TF --> Networking((VNet/NSG/PE))
@@ -0,0 +1,206 @@
# Azure AI Architektur – EU‑konform, ISO 27001 & DORA bereit
## 1. Hoch‑Level Architekturdiagramm (Mermaid)
```mermaid
flowchart TD
%% Externer Verkehr
Internet([Internet]) --> WAF[WAF / Prompt‑Firewall]
WAF --> LB[TLS‑Terminierende Lastenausgleichung]
%% API-Schicht
LB --> APIGW[Azure API Management (LLM‑Router)]
APIGW --> AKS[Kubernetes Cluster]
%% KI‑Kernservices
AKS -->|LLM Adapter| AOAI[Azure OpenAI]
AKS --> AIEngine[Agentic KI‑Engine]
AIEngine -->|Prompt‑Routing| PromptFirewall
AIEngine -->|Modells­scanning| SecScanner[KI‑Modell & Schnittstellen‑Scanner]
%% Daten­schicht
subgraph DB[Datenlager]
SQL[Azure SQL Database]:::db
NoSQL[Cosmos DB (NoSQL)]:::db
Blob[Azure Blob Storage]:::db
VectDB[Qdrant in AKS (Vektor‑DB)]:::db
Redis[Azure Cache for Redis]:::db
GraphDB[Azure Cosmos DB (Gremlin API)]:::db
end
%% Big‑Data Pipeline
subgraph BD[Big‑Data & Streaming]
Synapse[Azure Synapse Analytics]:::pipeline
Databricks[Azure Databricks]:::pipeline
Kafka[Apache Kafka (AKS)]:::pipeline
EH[Event Hubs]:::pipeline
end
%% Beobachtbarkeit & Sicherheit
subgraph OBS[Beobachtbarkeit]
Monitor[Azure Monitor]:::obs
AppInsights[Application Insights]:::obs
Grafana[Grafana auf AKS]:::obs
end
subgraph SEC[Sicherheit & Compliance]
Defender[Defender for Cloud]:::sec
SecCenter[Azure Security Center]:::sec
Bastion[Bastion Host]:::sec
KeyVault[Key Vault]:::sec
end
%% Orchestrierung & CI/CD
subgraph DEV[DevOps]
DevOps[Azure DevOps Pipelines]:::dev
Terraform[Terraform (IaC)]:::dev
end
%% IAM & PAM
subgraph AUTH[Identität]
AD[AAD]:::auth
PIM[Azure PIM]:::auth
end
%% Queue & Messaging
subgraph MQ[Messaging]
SB[Service Bus]:::mq
EH --> SB
end
%% Verbindungen
APIGW -->|Auth via AAD| AUTH
AKS -->|Secrets from KV| KeyVault
SecScanner -->|Logs to Monitor| Monitor
AIEngine -->|Telemetry| AppInsights
DevOps -->|Terraform| AKS
DEV -->|Deploy to AKS| AKS
DB -->|Access via Managed Identities| AKS
BD -->|Ingress to AKS| AIEngine
OBS -->|Logs & Metrics| Monitor
SEC -->|Policy Enforcement| Defender
```
```css
/* Mermaid diagram styles */
%% {font-family: monospace;}
```
::: note
Das Diagramm ist bewusst vereinfacht – die reale Bereitstellung enthält zusätzliche Schichten wie interne VNET‑Peering, Azure Front Door für globale Routing und ggf. einen Azure AD Application Proxy.
:::
## 2. Schichtbeschreibungen
| Schicht | Zweck | Kern‑Azure‑Dienste |
|---------|-------|---------------------|
| **Frontend** | TLS‑Terminierung, Ratenbegrenzung und WAF‑Schutz für gesamten eingehenden Verkehr. | Azure Front Door (oder Application Gateway mit WAF), TLS‑Terminierung via Azure Key Vault Zertifikate |
| **API‑Schicht** | Öffentlicher API‑Gateway, Routing zu LLM‑Router und internen Diensten. | Azure API Management (APIM), OpenAPI Definitionen, JWT‑Validierung via AAD |
| **KI‑Kern** | Ausführung von agentischen KI‑Workloads und LLM‑Inference. | Azure Kubernetes Service (AKS), Azure OpenAI, kundenspezifische Container‑Images für Agenten |
| **Sicherheit & Scanning** | Kontinuierliches Scannen von Modellen und Schnittstellen, Schutz vor bösartigen Prompts. | Azure Defender for Container Apps (oder AKS), benutzerdefinierte Prometheus Exporter, Azure Sentinel Logs |
| **Daten‑Schicht** | Persistente Speicherung für strukturierte und unstrukturierte Daten. | Azure SQL Database, Cosmos DB (SQL & Gremlin APIs), Blob Storage, Qdrant (Vektor‑DB) in AKS, Redis Cache |
| **Big Data & Streaming** | ETL‑Pipelines und Echtzeit‑Analytics. | Azure Synapse Analytics, Azure Databricks, Apache Kafka auf AKS, Event Hubs |
| **Beobachtbarkeit** | Metriken, Logs und Dashboards. | Azure Monitor, Application Insights, Grafana auf AKS |
| **Compliance & Sicherheit** | Richtlinien‑Durchsetzung, Schwachstellenmanagement. | Azure Defender for Cloud, Azure Security Center, Bastion Host, Key Vault |
| **Identität & Zugriff** | Rollenbasierter Zugriff und privilegiertes Identitäts‑Management. | Azure AD, Azure AD Connect (LDAP‑Sync), Azure PIM |
| **DevOps** | CI/CD, IaC und automatisierte Tests. | Azure DevOps Pipelines, Terraform, GitHub Actions (falls verwendet) |
| **Messaging** | Entkoppelter Austausch zwischen Diensten. | Azure Service Bus, Event Hubs |
## 3. Komponenten‑Mapping & Zweck (Anforderung‑nach‑Anforderung)
| Anforderung | Azure‑Dienst | Warum er die Anforderung erfüllt |
|--------------|---------------|------------------------------------|
| **AKS mit KI‑Workern** | AKS | Managed Kubernetes, Auto‑Scaling, Integration mit Azure AD für RBAC |
| **Agentic KI + LLM Adapter** | Azure OpenAI + kundenspezifischer Container in AKS | Native LLM‑Unterstützung, keine externe PaaS |
| **WAF & Prompt‑Firewall** | Azure Front Door (WAF) + benutzerdefinierte ASP.NET Core Middleware in AKS | Layer‑7‑Filterung, Prompt‑Validierung |
| **KI‑Modell & Schnittstellen Scanning** | Azure Defender for Cloud (Container) + benutzerdefinierter Scanner‑Service | Kontinuierliche Schwachstellenbewertung |
| **Frontend + Load Balancer** | Azure Application Gateway (WAF) oder Front Door + TLS‑Terminierung via Key Vault |
| **LLM‑Router & API Gateway** | Azure APIM + benutzerdefinierte Routing‑Logik in AKS | Richtlinienbasierter Routing, Throttling |
| **IAM (RBAC, LDAP via AAD Connect)** | Azure AD + Azure AD Connect | Einheitliche Identität, rollenbasierter Zugriff |
| **PAM (Azure PIM)** | Azure Privileged Identity Management | Just‑in‑Time Zugriff, MFA |
| **SQL / NoSQL / Blob / Vektor‑DB / Redis / Graph** | Azure SQL, Cosmos DB (Core & Gremlin), Blob Storage, Qdrant in AKS, Azure Cache for Redis | Native Speicher‑Dienste, S3‑Kompatibilität via Blob API |
| **Big‑Data Pipeline** | Synapse, Databricks, Kafka (AKS), Event Hubs | Unified Analytics Plattform |
| **Logging & Monitoring** | Azure Monitor, Application Insights, Grafana | Metriken, Logs, Dashboards |
| **Vulnerability Management** | Defender for Cloud + Azure Security Center | Kontinuierliche Bewertung, Compliance‑Scans |
| **Queue‑Services** | Service Bus / Event Hubs | Zuverlässige Messaging |
| **Build/Test/Deploy KI‑Agenten** | Azure DevOps Pipelines, Terraform | CI/CD + IaC |
| **Bastion Host** | Azure Bastion | Sicherer RDP/SSH Zugriff |
| **Splunk SIEM** | Optional: Splunk Enterprise auf AKS oder Azure Sentinel (SIEM) |
| **Public/private Zertifikate** | Key Vault + Azure Front Door | Managed Zertifikate |
## 4. Konfigurationshinweise
### 4.1 Azure Policy & Blueprints
| Richtlinie | Ziel | Durchsetzung |
|------------|------|--------------|
| **Erlaubte Standorte** | Alle Ressourcen | Verhindert Deployments außerhalb von EU‑Regionen |
| **Tagging‑Anforderung** | Alle Ressourcen | Erfordert `Owner`, `Environment`, `Compliance` Tags |
| **Erlaubte SKUs** | AKS, Azure SQL, Cosmos DB | Beschränkt auf EU‑Datencenter SKUs |
| **Daten­residenz** | Storage Accounts | Erzwingt `DataLocation=EU` |
| **Key Vault‑Secret‑Schutz** | Key Vault | Erzwingt `SoftDelete`, `PurgeProtection` |
Verwende **Azure Blueprints**, um die Basis (VNET, NSG, Key Vault, AAD Connect) vor‑bereit zu stellen.
### 4.2 RBAC & Managed Identities
- **AKS‑Cluster**: Aktiviere `Azure AD Integration` und weise die Rolle *Azure Kubernetes Service RBAC* AAD‑Gruppen zu.
- **Service Principals**: Nutze *Azure AD App‑Registrierungen* für API Management und DevOps Pipelines. Erteile minimalen Rollenumfang (z.B. `Reader`, `Contributor` auf spezifische Resource Groups).
- **Managed Identities**: Aktiviere sie für AKS‑Nodes, Databricks‑Workspaces und Synapse‑Pipelines, um Key Vault‑Secrets, Storage Accounts und Datenbanken zu nutzen.
- **Privileged Identity Management**: Aktiviere JIT für *Owner* Rollen auf Produktions‑Resource Groups.
### 4.3 Key Vault Secrets & Zertifikate
- Speichere alle Verbindungszeichenketten, API‑Keys (Azure OpenAI) und TLS‑Zertifikate im **Key Vault**.
- Aktiviere *SoftDelete* + *PurgeProtection*.
- Verwende **Key Vault‑References** in ARM/Terraform (z.B. `@Microsoft.KeyVault(????)`) zur Laufzeit‑Injektion.
- Für TLS‑Terminierung importiere Zertifikate in Key Vault und referenziere sie im Front Door oder Application Gateway.
### 4.4 Netzwerke & Isolation
- Stelle alle Ressourcen in ein **VNet** mit Subnetzen: `api`, `k8s`, `storage`, `data‑lake`, `monitor`.
- Nutze **Network Security Groups** (NSGs) und **Azure Firewall**, um Egress/Ingress zu beschränken. Erlaube nur benötigte Ports (80, 443, 6443 für AKS etc.).
- Aktiviere **Private Endpoints** für alle Storage Accounts und Datenbanken, um Traffic ins öffentliche Internet zu vermeiden.
- Verwende **Service Tags** (z.B. `AzureCloud`, `AzureKeyVault`) in NSGs.
### 4.5 Logging & Retention
- **Azure Monitor**: Aktiviere Diagnose‑Logs für alle Ressourcen. Speichere Logs in einem dedizierten Log Analytics Workspace mit Retention von 90 Tagen (oder länger, falls EU‑AI Act erfordert).
- **Application Insights**: Aktiviere Telemetrie für API Gateway und AKS‑Workloads. Nutze benutzerdefinierte Dimensionen, um Anfragen nach `model_id` zu taggen.
- **Azure Sentinel**: Ingestiere Logs von Key Vault, Defender, APIM und AKS. Erstelle Playbooks für automatisierte Incident‑Response.
- **Splunk**: Falls nötig, betreibe Splunk Enterprise auf separatem AKS‑Cluster und ingestiere Daten über Splunk Connect for Microsoft Azure.
## 5. Compliance‑Check‑Plan
| Aspekt | Check | Tool / Artefakt |
|--------|-------|-----------------|
| **EU‑AI Act** | Modell‑Governance, Audit‑Trail, Bias‑Testing | Azure Machine Learning Model Registry, benutzerdefinierte Logging in APIM |
| **DSGVO** | Datenminimierung, Consent‑Management | Azure Key Vault für Verschlüsselungs­schlüssel, Azure AD Consent Framework |
| **DORA** | Release‑Frequency, Deployment‑Automation | Azure DevOps Pipelines Metriken, Git Commit History |
| **NIS 2** | Incident‑Response, Supply‑Chain‑Security | Azure Sentinel Playbooks, Defender for Cloud Alerts |
| **ISO 27001** | Informationssicherheits‑Management | ISO‑27001 Audit‑Templates, Azure Policy Compliance Dashboard |
### 5.1 Periodische Audits
- **Quartalsweise**: Führe Azure Policy Compliance Scans durch, überprüfe IAM‑Rollenvergabe.
- **Halbjährlich**: Führe Penetration‑Tests am API Gateway und AKS Cluster durch, verifiziere Key Vault Secret Rotation.
- **Jährlich**: Führe vollständigen ISO 27001 Audit durch, EU‑AI Act Modell‑Compliance Review.
### 5.2 Monitoring & Alerting
- **Security Alerts**: Defender for Cloud + Azure Sentinel erzeugen Alarme bei anomalen Logins, Schwachstellen‑Ergebnissen.
- **Compliance Alerts**: Policy‑Verletzungen lösen Alarme in Azure Monitor aus und senden Benachrichtigungen an das Compliance‑Team.
- **Operational Alerts**: APIM Throttling, AKS Node‑Fehler, Datenbankverbindungsfehler.
## 6. Bereitstellungs‑Blueprint (IaC)
- **Terraform‑Module** für VNet, Subnetze, NSGs, Key Vault, AKS, APIM, Cosmos DB.
- **ARM‑Templates** für Azure AD Connect und Key Vault‑References.
- **Azure DevOps Pipelines**: getrennte Pipelines für Infrastruktur (IaC) und Anwendung (Container‑Build, Push zu ACR, Deploy zu AKS).
- **CI Secrets**: gespeichert im Key Vault und über Azure DevOps Service‑Connections abgerufen.
## 7. Nächste Schritte
1. Erstelle das **Azure Blueprint** für Basis‑Compliance.
2. Deploye **VNet** und **NSGs** mit den oben genannten Regeln.
3. Erstelle **Key Vault**, importiere Zertifikate, erstelle Secrets für OpenAI‑Keys.
4. Deploye **AKS** mit Azure AD Integration und Managed Identities.
5. Richte **Azure APIM** ein, konfiguriere Policies (Rate‑Limit, JWT‑Validierung).
6. Deploye **KI‑Engine** Container‑Images zu AKS.
7. Konfiguriere **Azure Sentinel** mit Log‑Connectors.
8. Führe Compliance‑Scan-Suite aus und behebe eventuelle Lücken.
---
> *Alle Dienste werden in EU‑Regionen (z. B. West Europe, North Europe) gehostet, um Daten‑Residency‑Anforderungen zu erfüllen.*
@@ -0,0 +1,34 @@
# Verbesserter Prompt (Deutsch)
Du bist ein Azure‑Cloud‑Seniorarchitekt. Erstelle einen detaillierten Architekturvorschlag für einen KI‑Betrieb, der vollständig konform mit **EU AI Act, DSGVO, DORA, NIS 2 und ISO 27001** ist. Nutze ausschließlich Azure‑Native‑Services (keine Drittanbieter‑PaaS). Berücksichtige die folgenden Komponenten:
- Kubernetes‑Cluster (AKS) mit KI‑Workern und Cluster‑Management
- Agentic AI inkl. LLM‑Adapter (Azure OpenAI)
- Web Application Firewall (WAF) & Prompt‑Firewall
- AI‑Model‑ und AI‑Interface‑Scanning (Sicherheit)
- Frontend + Load Balancer mit TLS‑Termination
- LLM‑Router & API Gateway (Azure API Management)
- IAM (RBAC, LDAP via Azure AD Connect), PAM (Azure PIM)
- Daten‑Layer: SQL, NoSQL, Blob‑Storage (S3‑Kompatibel), Vektor‑DB, Redis Cache, Graph‑DB
- Big‑Data‑Pipeline (Synapse / Databricks), Apache Kafka Router, Event Hubs
- Logging, Monitoring (Azure Monitor, Application Insights), Grafana Dashboards
- Vulnerability Management (Defender for Cloud, Azure Security Center)
- Queue‑Services (Service Bus / Event Hubs)
- Build/Test/Deploy von AI‑Agents (Azure DevOps Pipelines, Terraform)
- Bastion Host, Splunk SIEM, öffentliche/private Zertifikate (Key Vault)
## Aufgabe:
1. Erstelle ein hoch‑level Architekturdiagramm (als Text‑Code) und beschreibe jede Schicht.
2. Liste für jede Anforderung die passende Azure‑Komponente und deren Zweck auf.
3. Gib konkrete Konfigurations‑Hinweise (z. B. Azure Policy, RBAC‑Rollen, Key‑Vault‑Secrets).
4. Skizziere einen Compliance‑Check‑Plan (Regeln, Audits, Monitoring).
5. Speichere das Ergebnis als Markdown‑Datei `azure_ai_architecture.md`.
## Ergebnisformat:
- Markdown‑Datei mit Tabellen, Code‑Blöcken und erklärenden Absätzen.
- Keine zusätzlichen Kommentare oder System‑Nachrichten.
## Beispiel-Ausgabe:
(Siehe vorherige Antwort)
**Hinweis:** Verwende ausschließlich Azure‑Services; keine Drittanbieter‑PaaS.
@@ -1,4 +1,5 @@
(entwurf vor prompt engineering)
verbessere diesen prompt:
du bist azure cloud senior architekt
erstelle mir einen architekturvorschlag für den ki betrieb konform zum eu ai act, dsgvo, dora, nis 2 und iso27001 auf der basis von azure mit berücksichtigung der folgenden komponenten:
- kubernetes cluster mit ki workern und container/ cluster management
@@ -7,7 +8,8 @@ erstelle mir einen architekturvorschlag für den ki betrieb konform zum eu ai ac
- prompt firewall
- ai-model scanning
- ai-interface scanning
- frontend und load balancer mit tls terminierung
- frontend in container
- load balancer mit tls terminierung
- llm router
- api gateway
- iam (rbac, ldap)
@@ -17,12 +19,12 @@ erstelle mir einen architekturvorschlag für den ki betrieb konform zum eu ai ac
- apache Kafka Router
- Logging
- Monitoring
- Git repos, pipelines und ide
- Git repos, runner, pipelines ci/cd und ide
- real time analytics
- metriken (grafana)
- vulnerability management
- queues mq
- build, test und deploy von ai agents
- build, test und deploy von ai agents
- terraform
- bastion host, splunk
- öffentliche und private zertifikate mit management
@@ -0,0 +1,422 @@
Alles klar, ich mache das jetzt konkret – so, als würdet ihr **morgen mit diesem Setup auf Azure starten**. Ich zeige dir:
1. Annahmen & Namenskonvention
2. Netzwerk- & Security-Setup
3. Compute- & KI-Setup (AKS, OpenAI, Agents)
4. Data-Layer-Setup
5. Observability / Security-Setup
6. DevOps & Terraform-Setup (inkl. Beispiel-Snippets)
Ich halte es „konkret, aber noch lesbar“, nicht jede Kleinigkeit auf Ressourcenniveau – eher ein **Blueprint**, den man in Terraform übersetzen kann.
---
## 1. Annahmen & Namenskonvention
**Umgebung:**
* Subscription: `sub-ai-prod-001`
* Region: `westeurope`
* Tenant: euer Produktiv-Tenant
**Namenskonvention (Beispiele):**
* Resource Group: `rg-<scope>-<env>-<region>`
* z. B. `rg-network-prod-weu`, `rg-aks-prod-weu`
* AKS: `aks-ai-prod-weu`
* VNet: `vnet-hub-prod-weu`, `vnet-aks-prod-weu`, `vnet-data-prod-weu`
* Key Vault: `kv-ai-prod-weu`
* Log Analytics: `law-ai-prod-weu`
**Umgebungen:**
* `dev`, `test`, `prod` – identische Struktur, andere Größen und ggf. weniger Zonen.
---
## 2. Netzwerk- & Security-Setup
### 2.1 Resource Groups
* `rg-network-prod-weu` – VNet, Firewall, Bastion, DDoS, Peerings
* `rg-aks-prod-weu` – AKS, ACR, Managed Identities
* `rg-app-prod-weu` – APIM, Front Door, Application Gateway, Event Hubs, Service Bus
* `rg-data-prod-weu` – SQL, Cosmos, Storage, Data Explorer/Synapse
* `rg-secops-prod-weu` – Log Analytics, Sentinel, Key Vault, Managed Grafana
* `rg-ops-prod-weu` – devOps Hilfsressourcen (Automation, Runbooks, ggf. Jump-VM, Splunk Forwarder etc.)
### 2.2 Netzwerk-Topologie (Beispiel)
**Hub-Spoke-Modell**
* Hub-VNet: `vnet-hub-prod-weu` – `10.0.0.0/16`
* Subnet `snet-azurefw` (Firewall): `10.0.0.0/24`
* Subnet `snet-bastion`: `10.0.1.0/24`
* Subnet `snet-shared-services`: `10.0.2.0/24`
* Spoke-VNet AKS: `vnet-aks-prod-weu` – `10.1.0.0/16`
* Subnet `snet-aks-nodes`: `10.1.0.0/20`
* Subnet `snet-aks-system`: `10.1.16.0/24`
* Subnet `snet-aks-user`: `10.1.17.0/24`
* Spoke-VNet Data: `vnet-data-prod-weu` – `10.2.0.0/16`
* Subnet `snet-data-sql`: `10.2.0.0/24`
* Subnet `snet-data-analytics`: `10.2.1.0/24`
**Komponenten:**
* **Azure Firewall** in Hub, alle Spokes via VNet-Peering angebunden
* **DDoS Protection Standard** auf Hub-VNet
* **Azure Bastion** im Hub für SSH/RDP auf Admin-VMs oder Knoten (wenn nötig)
* PaaS-Services (SQL, Storage, Event Hubs, Service Bus, OpenAI, Key Vault) via **Private Endpoints** in `vnet-data-prod-weu` und `vnet-aks-prod-weu`.
---
## 3. Compute- & KI-Setup
### 3.1 AKS-Cluster
* Ressource: `aks-ai-prod-weu` in `rg-aks-prod-weu`
* Konfiguration (Beispiel):
* Kubernetes-Version: `1.29.x` (aktuelle LTS zum Rolloutzeitpunkt)
* Nodepools:
* `systempool` (B4ms, 3 Nodes, autoscale 3–10)
* `gpubatch` (Standard_NC4as_T4_v3, autoscale 0–10) – für Model Serving / featurized Inference
* `appworkload` (D4as_v5, autoscale 3–20) – AI Agents, LLM-Router, APIs, Frontend
* Network: **Azure CNI**, IPAM über oben beschriebenes AKS-VNet
* **AKS-managed AAD Integration** (Azure Entra ID) für Kubernetes-RBAC
* **OIDC Issuer** für Workload-Identitäten (Federation mit Entra ID, kein Secret-basiertes Zugriffskonzept mehr)
Namespaces (Beispiele):
* `ns-frontend` – UI-Container
* `ns-api` – API & LLM-Router
* `ns-ai-agents` – Agent-Orchestration
* `ns-ml-models` – self-hosted Modelle
* `ns-observability` – Prometheus/Grafana-Agent, OpenTelemetry, etc.
### 3.2 Container Registry
* Ressource: `acr-ai-prod-weu` in `rg-aks-prod-weu`
* Private Endpoint zu `vnet-aks-prod-weu`
* Defender for Cloud / Defender for Containers Scan auf Images aktiv.
### 3.3 LLM-Router & Agentic AI
**LLM-Router (Beispiel):**
* Deployment `llm-router` in `ns-api` (z. B. Python/FastAPI)
* Patterns:
* Endpunkte: `/v1/chat`, `/v1/completions`, `/v1/tools/<toolname>`
* Routing-Tabelle in ConfigMap/Secret (z. B. `gpt4o` → Azure OpenAI, `internal-llm` → AKS-Model)
**Agentic AI Services:**
* Deployments `agent-orchestrator`, `retriever-service`, `task-planner` in `ns-ai-agents`
* Kommunikation mit:
* Azure AI Search (`VECTOR`)
* SQL/Cosmos für Domänendaten
* Azure OpenAI / self-hosted Models über interne Services
### 3.4 Azure OpenAI & Self-hosted Models
* Ressource: `aoai-prod-weu` (Azure OpenAI / Azure AI Foundry Project)
* Region: `westeurope` oder andere EU-Region, Data Residency „EU only“
* Bereitgestellte Modelle: `gpt-4.x`, `gpt-4o`, `embedding-3-large` etc.
* Self-hosted Modelle (z. B. Llama, Mistral):
* Als `Deployment` in `ns-ml-models`
* Exponiert via `ClusterIP` Services, nur intern erreich­bar
* GPU-Nodepool `gpubatch` zugeordnet.
---
## 4. Data-Layer-Setup
### 4.1 SQL, NoSQL, Graph
* **Azure SQL Managed Instance**: `sqlmi-ai-prod-weu` in `rg-data-prod-weu`
* Nutzung: Referenzdaten, Konfigurationen, Audit-Tabellen, fachliche Daten
* Always Encrypted / TDE mit CMK aus Key Vault
* **Azure Cosmos DB (Core + Gremlin)**:
* Account: `cosmos-ai-prod-weu`
* DBs:
* `aiapp` (Core API) – Session-Daten, Konfigurationsobjekte, Agent-States
* `graph` (Gremlin API) – Graph der Entitäten / Policies / Relationen
### 4.2 Object Storage / Data Lake / Vektorindex
* **Storage Account**: `staiaprodweu` (Data Lake Gen2 aktiviert)
* Container:
* `logs-ai` – Langfrist-Logs (immutable)
* `model-artifacts` – Model-Checkpoints, Eval-Reports
* `training-data` – z. B. anonymisierte Historik
* **Azure AI Search**: `aisearch-ai-prod-weu`
* Index `idx-documents` (klassisch) und `idx-documents-vector` (Vektor)
* Nutzt Blob Storage als Quelle (Indexers)
* Dient RAG-Orchestrator als Retrieval-Ziel.
### 4.3 Messaging & Streaming
* **Event Hubs Namespace**: `evh-ai-prod-weu`
* Event Hub `eh-ai-telemetry` (Kafka-kompatibler Endpoint) – Streams von Request-/Systemevents
* **Service Bus Namespace**: `sb-ai-prod-weu`
* Queues: `q-agent-tasks`, `q-agent-results`
* Topics: `t-notifications`, `t-compliance-events`
### 4.4 Analytics
* **Azure Data Explorer / Synapse Data Explorer**: `adx-ai-prod-weu`
* Tabellen: `ai_requests`, `ai_decisions`, `security_events`
* Optional: **Synapse Workspace** für Reporting und DWH-Workloads.
---
## 5. Observability & Security-Setup
### 5.1 Logging & Monitoring
* **Log Analytics Workspace**: `law-ai-prod-weu` in `rg-secops-prod-weu`
* Datenquellen:
* AKS (Container Logs/Insights)
* APIM, Application Gateway, Front Door
* Event Hubs, Service Bus, SQL, Storage
* Azure OpenAI (über Diagnostic Settings, soweit verfügbar)
* **Azure Monitor + Application Insights**:
* Application Insights Ressource: `appi-ai-prod-weu`
* Instrumentation in Frontend, API, Agents, Router
* Distributed Tracing mit Correlation IDs
* **Azure Managed Grafana**:
* Workspace: `graf-ai-prod-weu`
* Data Source: Log Analytics, Azure Monitor
* Dashboards:
* „Platform Health“ (CPU, Memory, Node Status, Error Rates)
* „LLM Performance“ (Latenzen, Tokenverbrauch, Rate-Limits)
* „Compliance & Oversight“ (Anzahl manueller Overrides, abgebrochene Anfragen, Policy-Verstöße)
### 5.2 SIEM / SOC
* **Microsoft Sentinel**: `sentinel-ai-prod-weu` (auf `law-ai-prod-weu`)
* Daten-Connectors: Azure Activity, Sign-In Logs, Defender, AKS, APIM, WAF-Logs, Custom Logs von Agents
* Regeln:
* Anomalie bei LLM-Nutzung (z. B. plötzlicher Spike an bestimmten Endpunkten)
* Ungewöhnliche Admin-Logins (PIM, Key Vault, AKS)
* **Splunk**:
* Entweder via Add-on für Azure Monitor oder Event Hub Export
* Forwarder in `rg-ops-prod-weu` (VM in `snet-shared-services`)
### 5.3 Identity, Key Management & Bastion
* **Azure Entra ID**:
* Security-Gruppen: `sg-aks-admins`, `sg-ai-dev`, `sg-ai-ops`, `sg-soc`
* App Registrations für Frontend, API, Agents (client credentials / auth code with PKCE)
* **PIM**:
* Rollen wie `Owner`, `Contributor`, `User Access Administrator`, `AKS Cluster Admin`, `Key Vault Admin` nur via PIM.
* **Key Vault**: `kv-ai-prod-weu`
* Secrets:
* DB Connection Strings (wenn nicht komplett MI-basiert)
* API Keys (z. B. Drittsysteme), Webhook-Secrets
* Keys:
* CMK für SQL, Storage, eventuell OpenAI (falls unterstützt)
* Certificates:
* TLS-Zertifikate für App Gateway, APIM (öffentlich + privat)
* **Azure Bastion**:
* Zugriff auf Jump VM (z. B. für Splunk-Forwarder, Spezial-Tools) ohne Public IP.
---
## 6. DevOps & Terraform-Setup
### 6.1 Git & Pipelines
* **GitHub Enterprise** Org: `mycompany-ai` (oder Azure DevOps Project `ai-platform`)
* Repositories:
* `infra-landingzone` – VNet, RGs, Policies, Key Vault, Log Analytics, Firewall
* `infra-platform` – AKS, ACR, APIM, OpenAI, Data Layer
* `app-llm-router`, `app-ai-agents`, `app-frontend` – Applikationscode
* Pipelines:
* `infra-landingzone-ci` / `cd` → Terraform Plan/Apply gegen `dev`/`test`/`prod`
* `app-*-ci` → Build, Tests, Container-Build, Push nach ACR
* `app-*-cd` → Deploy nach AKS (Helm)
### 6.2 Terraform – Beispiel-Snippets (stark vereinfacht)
**Backend & Provider (infra-landingzone)**
```hcl
terraform {
required_version = ">= 1.8.0"
backend "azurerm" {
resource_group_name = "rg-tfstate-prod-weu"
storage_account_name = "sttfstateprodweu"
container_name = "tfstate"
key = "landingzone-prod.tfstate"
}
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
}
}
provider "azurerm" {
features {}
}
```
**Beispiel: VNet + Subnet für AKS**
```hcl
resource "azurerm_virtual_network" "vnet_aks" {
name = "vnet-aks-prod-weu"
location = "westeurope"
resource_group_name = "rg-network-prod-weu"
address_space = ["10.1.0.0/16"]
}
resource "azurerm_subnet" "snet_aks_nodes" {
name = "snet-aks-nodes"
resource_group_name = azurerm_virtual_network.vnet_aks.resource_group_name
virtual_network_name = azurerm_virtual_network.vnet_aks.name
address_prefixes = ["10.1.0.0/20"]
}
```
**Beispiel: AKS-Cluster (gekürzt)**
```hcl
resource "azurerm_kubernetes_cluster" "aks_ai" {
name = "aks-ai-prod-weu"
location = "westeurope"
resource_group_name = "rg-aks-prod-weu"
dns_prefix = "aks-ai-prod"
sku_tier = "Standard"
default_node_pool {
name = "systempool"
vm_size = "Standard_D4as_v5"
node_count = 3
enable_auto_scaling = true
min_count = 3
max_count = 10
vnet_subnet_id = azurerm_subnet.snet_aks_nodes.id
}
identity {
type = "SystemAssigned"
}
azure_active_directory_role_based_access_control {
managed = true
admin_group_object_ids = ["<GUID-AKS-Admins-Group>"]
}
oidc_issuer_enabled = true
workload_identity_enabled = true
network_profile {
network_plugin = "azure"
}
}
```
**Beispiel: Log Analytics + Diagnostics**
```hcl
resource "azurerm_log_analytics_workspace" "law_ai" {
name = "law-ai-prod-weu"
location = "westeurope"
resource_group_name = "rg-secops-prod-weu"
sku = "PerGB2018"
}
resource "azurerm_monitor_diagnostic_setting" "aks_diag" {
name = "diag-aks-ai-prod"
target_resource_id = azurerm_kubernetes_cluster.aks_ai.id
log_analytics_workspace_id = azurerm_log_analytics_workspace.law_ai.id
enabled_log {
category = "kube-apiserver"
}
enabled_log {
category = "kube-audit"
}
metric {
category = "AllMetrics"
}
}
```
**Beispiel: Azure OpenAI (Symbolisch)**
(Hinweis: die Terraform-Resource ist je nach Provider-Version ggf. unterschiedlich; pseudomäßig:)
```hcl
resource "azurerm_cognitive_account" "aoai" {
name = "aoai-prod-weu"
location = "westeurope"
resource_group_name = "rg-app-prod-weu"
kind = "OpenAI"
sku_name = "S0"
custom_subdomain_name = "aoai-prod"
identity {
type = "SystemAssigned"
}
}
```
---
Wenn du magst, kann ich als nächsten Schritt:
* das Beispiel auf **„nur KI-Kernplattform“** zurechtschneiden (Minimal-Setup),
* oder dir eine **konkrete AKS-Namespace- und Helm-Chart-Struktur** für LLM-Router & Agents vorschlagen.
@@ -0,0 +1,474 @@
# ✅ Deployment Checklist
Diese Checkliste führt dich Schritt-für-Schritt durch das erste Deployment.
## 📋 Pre-Deployment
### 1. Lokale Umgebung
- [ ] Terraform >= 1.9.0 installiert
- [ ] Azure CLI >= 2.0 installiert
- [ ] kubectl >= 1.28 installiert
- [ ] Docker >= 20.10 installiert
- [ ] PHP >= 8.2 installiert (für Laravel-Befehle)
**Prüfen:**
```bash
terraform version
az version
kubectl version
docker version
php -v
```
### 2. Azure Zugriff
- [ ] Azure Account vorhanden
- [ ] Subscription ID bekannt: `77677a80-2dea-493d-9867-f1c961b80fb3`
- [ ] Zugriff auf Resource Group: `trusted_ai_demo_rg`
- [ ] Zugriff auf AKS Cluster: `trai_k8s_cluster`
**Prüfen:**
```bash
az login
az account set --subscription "77677a80-2dea-493d-9867-f1c961b80fb3"
az account show
az aks show --resource-group trusted_ai_demo_rg --name trai_k8s_cluster
```
## 🔧 Setup
### 3. Azure Container Registry
- [ ] ACR erstellt oder vorhanden
- [ ] ACR Name: `mylaravelregistry` (oder eigener Name)
- [ ] AKS hat Pull-Berechtigung für ACR
**Erstellen:**
```bash
# ACR erstellen (falls noch nicht vorhanden)
az acr create \
--resource-group trusted_ai_demo_rg \
--name mylaravelregistry \
--sku Basic \
--location germanywestcentral
# AKS Zugriff geben
az aks update \
--resource-group trusted_ai_demo_rg \
--name trai_k8s_cluster \
--attach-acr mylaravelregistry
# Login
az acr login --name mylaravelregistry
```
### 4. Docker Image
- [ ] Docker Image gebaut
- [ ] Docker Image zu ACR gepusht
- [ ] Image Tag notiert
**Bauen & Pushen:**
```bash
cd /Users/sebastianfrohlich/Herd/frontend
# Bauen
docker build -t mylaravelregistry.azurecr.io/laravel-app:v1.0.0 .
# Pushen
docker push mylaravelregistry.azurecr.io/laravel-app:v1.0.0
# Image Tag notieren:
IMAGE_TAG="mylaravelregistry.azurecr.io/laravel-app:v1.0.0"
```
### 5. Laravel Konfiguration
- [ ] APP_KEY generiert
- [ ] APP_KEY notiert
**Generieren:**
```bash
cd /Users/sebastianfrohlich/Herd/frontend
php artisan key:generate --show
# Output: base64:xyz...
# Notieren für terraform.tfvars
```
### 6. Backup-Dateien
- [ ] Database Backup vorhanden
- [ ] Backup-Pfad notiert
**Prüfen:**
```bash
ls -lh /Users/sebastianfrohlich/Herd/frontend/backups/
# Wähle ein Backup, z.B.:
BACKUP_FILE="../backups/backup_backend_20251203_101741.dump"
```
## ⚙️ Terraform Konfiguration
### 7. terraform.tfvars erstellen
- [ ] `terraform.tfvars` aus Example kopiert
- [ ] Alle erforderlichen Werte eingetragen
**Erstellen:**
```bash
cd /Users/sebastianfrohlich/Herd/frontend/terraform
cp terraform.tfvars.example terraform.tfvars
nano terraform.tfvars
```
**Erforderliche Werte:**
```hcl
# ✅ Docker Image
docker_image = "mylaravelregistry.azurecr.io/laravel-app:v1.0.0"
# ✅ Laravel APP_KEY
app_key = "base64:YOUR_GENERATED_KEY_HERE"
# ✅ PostgreSQL Admin Password (sicher wählen!)
postgresql_admin_password = "YourVerySecurePassword123!"
# ✅ Alert Email
alert_email_address = "your-email@example.com"
# ✅ Database Restore (beim ersten Deployment)
db_restore_enabled = true
db_backup_file_path = "../backups/backup_backend_20251203_101741.dump"
```
**Optionale Werte:**
```hcl
# Für Custom Domain
ingress_host = "app.yourdomain.com"
# Für SSL/TLS (benötigt Domain)
ssl_enabled = true
ssl_issuer_email = "admin@yourdomain.com"
# Ressourcen anpassen
app_replicas = 2
postgresql_sku_name = "B_Standard_B1ms"
```
### 8. Konfiguration validieren
- [ ] terraform.tfvars Syntax korrekt
- [ ] Alle Secrets/Passwörter sicher
- [ ] Backup-Pfad korrekt
**Prüfen:**
```bash
cd terraform
# Terraform init
terraform init
# Validate
terraform validate
# Sollte ausgeben: Success! The configuration is valid.
```
## 🚀 Deployment
### 9. Deployment ausführen
**Option A: Automatisches Script (Empfohlen)**
- [ ] Deploy-Script ausgeführt
```bash
cd /Users/sebastianfrohlich/Herd/frontend/terraform
./scripts/deploy.sh
```
Das Script führt automatisch aus:
1. ✅ Prerequisite Check
2. ✅ Azure Login Status
3. ✅ terraform.tfvars Check
4. ✅ Docker Image Check
5. ✅ APP_KEY Check
6. ✅ terraform init
7. ✅ terraform validate
8. ✅ terraform plan
9. ✅ terraform apply (nach Bestätigung)
10. ✅ kubectl konfigurieren
11. ✅ Pod Status prüfen
**Option B: Manuell**
- [ ] Terraform Plan erstellt
- [ ] Plan überprüft
- [ ] Terraform Apply ausgeführt
```bash
cd terraform
# Plan
terraform plan -out=tfplan
# Plan überprüfen
# Sollte Resources anzeigen: +XX to add, ~0 to change, -0 to destroy
# Apply
terraform apply tfplan
# Outputs anzeigen
terraform output
terraform output deployment_instructions
```
### 10. kubectl konfigurieren
- [ ] kubectl Credentials abgerufen
- [ ] Cluster-Zugriff getestet
```bash
az aks get-credentials \
--resource-group trusted_ai_demo_rg \
--name trai_k8s_cluster \
--overwrite-existing
# Testen
kubectl get nodes
kubectl get namespaces
```
## 🔄 Database Restore
### 11. Datenbank wiederherstellen
**Option A: Automatisches Script (Empfohlen)**
- [ ] Restore-Script ausgeführt
- [ ] Job Status geprüft
```bash
cd /Users/sebastianfrohlich/Herd/frontend/terraform
./scripts/restore-db.sh
# Script fragt nach:
# - Welches Backup-File?
# - Bestätigung: yes
# Zeigt dann Logs und Status
```
**Option B: Via Terraform**
- [ ] `db_restore_enabled = true` in terraform.tfvars
- [ ] `terraform apply` ausgeführt
```bash
# In terraform.tfvars:
db_restore_enabled = true
db_backup_file_path = "../backups/backup_backend_20251203_101741.dump"
# Apply
terraform apply
# Job Status prüfen
kubectl get jobs -n laravel-app
kubectl logs -n laravel-app -l job-type=database-restore -f
```
## ✅ Post-Deployment Checks
### 12. Infrastruktur Status
- [ ] Pods sind running
- [ ] Service ist erreichbar
- [ ] Ingress hat External IP
- [ ] Database ist connected
**Prüfen:**
```bash
# Pods
kubectl get pods -n laravel-app
# Sollte: 2/2 Running anzeigen
# Service
kubectl get svc -n laravel-app
# Ingress
kubectl get svc ingress-nginx-controller -n ingress-nginx
# Sollte: EXTERNAL-IP anzeigen (dauert 5-10 Min)
# Database
kubectl get secret laravel-app-db-credentials -n laravel-app
```
### 13. Application Health
- [ ] Application ist erreichbar
- [ ] HTTP Status 200 oder 302
- [ ] Keine Fehler in Logs
**Prüfen:**
```bash
# URL abrufen
terraform output app_url
# Beispiel Output: http://20.79.123.456
# Im Browser öffnen oder:
curl -I http://20.79.123.456
# Sollte: HTTP/1.1 200 OK oder 302 Found
# Logs prüfen
kubectl logs -n laravel-app -l app=laravel-app -f
# Sollte: Keine Errors zeigen
```
### 14. Database Connectivity
- [ ] Database Restore Job completed
- [ ] Laravel kann auf DB zugreifen
**Prüfen:**
```bash
# Restore Job Status
kubectl get jobs -n laravel-app
# Sollte: db-restore-* mit COMPLETIONS 1/1
# Job Logs
kubectl logs -n laravel-app -l job-type=database-restore
# Sollte: "Database restore completed successfully!" enthalten
# Laravel Migrations Status (in Pod)
POD_NAME=$(kubectl get pods -n laravel-app -l app=laravel-app -o jsonpath='{.items[0].metadata.name}')
kubectl exec -it -n laravel-app $POD_NAME -- php artisan migrate:status
# Sollte: Migration table anzeigen
```
## 🎯 Finalisierung
### 15. Monitoring Setup
- [ ] Azure Monitor funktioniert
- [ ] Alert Rules aktiv
- [ ] Email Alerts konfiguriert
**Prüfen:**
```bash
# Azure Portal öffnen
open https://portal.azure.com
# Gehe zu:
# 1. Resource Group: trusted_ai_demo_rg
# 2. AKS Cluster: trai_k8s_cluster
# 3. Monitoring > Insights
# Alert Rules prüfen:
az monitor metrics alert list \
--resource-group trusted_ai_demo_rg
```
### 16. Dokumentation
- [ ] LoadBalancer IP notiert
- [ ] Database Connection String notiert
- [ ] Terraform Outputs gespeichert
**Notieren:**
```bash
# Alle Outputs anzeigen
terraform output
# Spezifische Outputs
terraform output app_url
terraform output postgresql_server_fqdn
terraform output postgresql_connection_string
# In Passwort-Manager oder sicheren Ort speichern!
```
### 17. Cleanup & Security
- [ ] Sensitive Dateien nicht committed (terraform.tfvars)
- [ ] Passwörter sicher gespeichert
- [ ] .gitignore überprüft
**Prüfen:**
```bash
# Git Status
git status
# Sollte NICHT enthalten:
# - terraform.tfvars
# - *.tfstate
# - kubeconfig
# Falls vorhanden:
git rm --cached terraform/terraform.tfvars
git rm --cached terraform/*.tfstate
```
## 🚦 Success Criteria
Deployment ist erfolgreich wenn:
- ✅ `kubectl get pods -n laravel-app` zeigt 2/2 Running
- ✅ `terraform output app_url` zeigt eine URL
- ✅ URL im Browser ist erreichbar
- ✅ Database Restore Job ist completed
- ✅ Keine Fehler in Pod Logs
- ✅ Ingress hat External IP
## 🎉 Fertig!
Deine Laravel-Anwendung läuft jetzt auf Azure Kubernetes Service!
### Nächste Schritte:
1. **Testen**: Funktionalität der Anwendung testen
2. **Monitoring**: Azure Monitor regelmäßig prüfen
3. **Backups**: PostgreSQL Backup-Strategy überprüfen
4. **Domain**: Custom Domain konfigurieren (optional)
5. **SSL**: Let's Encrypt aktivieren (optional)
6. **CI/CD**: GitHub Actions einrichten (optional)
### Wichtige Commands:
```bash
# Status prüfen
kubectl get all -n laravel-app
# Logs anzeigen
kubectl logs -n laravel-app -l app=laravel-app -f
# Shell in Pod
kubectl exec -it -n laravel-app <pod-name> -- /bin/sh
# Port-forward für lokalen Zugriff
kubectl port-forward -n laravel-app svc/laravel-app 8080:80
# Terraform Outputs
terraform output deployment_instructions
```
## 📞 Support
Bei Problemen:
1. **Troubleshooting Guide**: [README.md#troubleshooting](README.md#troubleshooting)
2. **Kubernetes Events**: `kubectl get events -n laravel-app --sort-by='.lastTimestamp'`
3. **Pod Logs**: `kubectl logs -n laravel-app <pod-name>`
4. **Terraform State**: `terraform show`
---
**Deployment Time**: ~30 Minuten
**Status**: ✅ Ready for Production
@@ -0,0 +1,410 @@
# GitHub Actions CI/CD Setup
Diese Anleitung zeigt, wie du die automatische Deployment-Pipeline mit GitHub Actions einrichtest.
## 📋 Übersicht
Die Pipeline führt automatisch folgende Schritte aus:
1. **Build & Push**: Docker Image bauen und zu Azure Container Registry pushen
2. **Terraform Deploy**: Infrastruktur mit Terraform deployen
3. **Smoke Tests**: Basis-Tests nach Deployment ausführen
4. **Notifications**: Status-Benachrichtigungen
## 🔐 Erforderliche GitHub Secrets
Gehe zu deinem GitHub Repository → Settings → Secrets and variables → Actions → New repository secret
### Azure Credentials
```bash
# Azure Service Principal erstellen
az ad sp create-for-rbac \
--name "github-actions-laravel-app" \
--role contributor \
--scopes /subscriptions/77677a80-2dea-493d-9867-f1c961b80fb3/resourceGroups/trusted_ai_demo_rg \
--sdk-auth
# Output sieht so aus:
{
"clientId": "xxx",
"clientSecret": "xxx",
"subscriptionId": "77677a80-2dea-493d-9867-f1c961b80fb3",
"tenantId": "xxx",
"activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
"resourceManagerEndpointUrl": "https://management.azure.com/",
"activeDirectoryGraphResourceId": "https://graph.windows.net/",
"sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
"galleryEndpointUrl": "https://gallery.azure.com/",
"managementEndpointUrl": "https://management.core.windows.net/"
}
```
**Secret Name**: `AZURE_CREDENTIALS`
**Secret Value**: Der gesamte JSON Output von oben
### Azure Container Registry
```bash
# ACR Credentials abrufen
az acr credential show --name mylaravelregistry
# Output:
{
"passwords": [
{
"name": "password",
"value": "xxx"
},
{
"name": "password2",
"value": "yyy"
}
],
"username": "mylaravelregistry"
}
```
**Secret Name**: `ACR_USERNAME`
**Secret Value**: `mylaravelregistry`
**Secret Name**: `ACR_PASSWORD`
**Secret Value**: Der Wert von `password` (oder `password2`)
### Azure Subscription
**Secret Name**: `AZURE_SUBSCRIPTION_ID`
**Secret Value**: `77677a80-2dea-493d-9867-f1c961b80fb3`
### Laravel Application
**Secret Name**: `LARAVEL_APP_KEY`
**Secret Value**: Generiere mit `php artisan key:generate --show`
**Beispiel**: `base64:abcdefgh12345...`
### PostgreSQL Database
**Secret Name**: `POSTGRESQL_ADMIN_USERNAME`
**Secret Value**: `pgadmin`
**Secret Name**: `POSTGRESQL_ADMIN_PASSWORD`
**Secret Value**: Dein sicheres PostgreSQL Passwort
### Ingress & SSL
**Secret Name**: `INGRESS_HOST`
**Secret Value**: Deine Domain (z.B. `app.yourdomain.com`) oder leer lassen für IP-Zugriff
**Secret Name**: `SSL_ISSUER_EMAIL`
**Secret Value**: Email für Let's Encrypt (z.B. `admin@yourdomain.com`)
### Monitoring
**Secret Name**: `ALERT_EMAIL`
**Secret Value**: Email für Azure Alerts
## 📝 Secrets Checkliste
- [ ] `AZURE_CREDENTIALS` (JSON von Service Principal)
- [ ] `ACR_USERNAME` (mylaravelregistry)
- [ ] `ACR_PASSWORD` (ACR password)
- [ ] `AZURE_SUBSCRIPTION_ID` (77677a80-2dea-493d-9867-f1c961b80fb3)
- [ ] `LARAVEL_APP_KEY` (base64:...)
- [ ] `POSTGRESQL_ADMIN_USERNAME` (pgadmin)
- [ ] `POSTGRESQL_ADMIN_PASSWORD` (sicheres Passwort)
- [ ] `INGRESS_HOST` (optional: deine Domain)
- [ ] `SSL_ISSUER_EMAIL` (optional: für SSL)
- [ ] `ALERT_EMAIL` (deine Email)
## 🚀 Workflow Trigger
### Automatisch bei Push
Die Pipeline wird automatisch ausgeführt bei Push auf:
- `main` Branch (Staging Deployment)
- `production` Branch (Production Deployment)
```bash
# Code ändern und committen
git add .
git commit -m "Update feature"
# Push zu main für Staging
git push origin main
# Push zu production für Production
git push origin production
```
### Manuell über GitHub UI
1. Gehe zu deinem Repository auf GitHub
2. Klicke auf "Actions" Tab
3. Wähle "Deploy to Azure AKS" Workflow
4. Klicke auf "Run workflow"
5. Wähle Environment (staging/production)
6. Klicke auf "Run workflow"
### Manuell über GitHub CLI
```bash
# Installiere gh CLI (falls noch nicht vorhanden)
brew install gh # macOS
# oder: https://cli.github.com/
# Login
gh auth login
# Workflow manuell triggern
gh workflow run deploy-azure.yml \
--ref main \
--field environment=staging
# Workflow Status prüfen
gh run list --workflow=deploy-azure.yml
# Logs anzeigen
gh run view --log
```
## 🔧 Workflow Konfiguration anpassen
Die Workflow-Datei liegt in [.github/workflows/deploy-azure.yml](../.github/workflows/deploy-azure.yml).
### Environment-spezifische Settings
Im Workflow werden verschiedene Settings basierend auf dem Environment gesetzt:
**Staging:**
- `app_debug = true`
- `app_replicas = 2`
- `postgresql_sku_name = "B_Standard_B1ms"` (Basic)
- `postgresql_storage_mb = 32768` (32 GB)
- `ssl_enabled = false`
**Production:**
- `app_debug = false`
- `app_replicas = 3`
- `postgresql_sku_name = "GP_Standard_D2s_v3"` (General Purpose)
- `postgresql_storage_mb = 131072` (128 GB)
- `ssl_enabled = true`
### Weitere Trigger hinzufügen
```yaml
on:
push:
branches:
- main
- production
pull_request:
branches:
- main
schedule:
- cron: '0 2 * * 0' # Jeden Sonntag um 2 Uhr
workflow_dispatch:
# ... existing inputs
```
## 📊 Workflow Monitoring
### In GitHub UI
1. Gehe zu "Actions" Tab in deinem Repository
2. Siehst alle Workflow-Runs
3. Klicke auf einen Run für Details
4. Siehst Logs für jeden Job/Step
### Via GitHub CLI
```bash
# Aktuelle Runs anzeigen
gh run list --workflow=deploy-azure.yml
# Spezifischen Run anzeigen
gh run view <run-id>
# Logs anzeigen
gh run view <run-id> --log
# Run erneut starten
gh run rerun <run-id>
# Run abbrechen
gh run cancel <run-id>
```
## 🐛 Troubleshooting
### Pipeline schlägt bei "Build and Push" fehl
**Problem**: ACR Authentication fehlgeschlagen
**Lösung**:
```bash
# Prüfe ACR Credentials
az acr credential show --name mylaravelregistry
# Update GitHub Secrets mit neuen Credentials
```
### Pipeline schlägt bei "Terraform Deploy" fehl
**Problem**: Azure Credentials ungültig
**Lösung**:
```bash
# Service Principal neu erstellen
az ad sp create-for-rbac \
--name "github-actions-laravel-app" \
--role contributor \
--scopes /subscriptions/77677a80-2dea-493d-9867-f1c961b80fb3/resourceGroups/trusted_ai_demo_rg \
--sdk-auth
# AZURE_CREDENTIALS Secret updaten
```
**Problem**: Terraform State Lock
**Lösung**:
```bash
# State Lock manuell entfernen
cd terraform
terraform force-unlock <lock-id>
```
### Pipeline schlägt bei "Smoke Tests" fehl
**Problem**: Pods nicht ready
**Lösung**:
```bash
# kubectl credentials abrufen
az aks get-credentials \
--resource-group trusted_ai_demo_rg \
--name trai_k8s_cluster
# Pod Status prüfen
kubectl get pods -n laravel-app
kubectl describe pod <pod-name> -n laravel-app
kubectl logs <pod-name> -n laravel-app
```
## 🔒 Sicherheit
### Service Principal Permissions
Der Service Principal benötigt folgende Berechtigungen:
- Contributor auf Resource Group
- AcrPush auf Container Registry (optional, wenn über ACR credentials)
```bash
# Berechtigungen prüfen
az role assignment list \
--assignee <service-principal-client-id> \
--resource-group trusted_ai_demo_rg
```
### Secrets Rotation
Rotiere Secrets regelmäßig:
```bash
# Neues ACR Password generieren
az acr credential renew \
--name mylaravelregistry \
--password-name password
# Service Principal Secret erneuern
az ad sp credential reset \
--id <service-principal-object-id>
```
## 🚦 Branch Protection Rules
Empfohlene Branch Protection Rules für `main` und `production`:
1. Gehe zu Repository → Settings → Branches
2. Füge Branch Protection Rule hinzu für `main` und `production`
3. Aktiviere:
- ✅ Require status checks to pass before merging
- ✅ Require branches to be up to date before merging
- ✅ Require deployments to succeed before merging
- ✅ Require conversation resolution before merging
- ✅ Include administrators
## 📈 Deployment Environments
GitHub Environments für bessere Kontrolle:
1. Gehe zu Repository → Settings → Environments
2. Erstelle zwei Environments: `staging` und `production`
3. Für `production`:
- ✅ Required reviewers: Füge Reviewer hinzu
- ✅ Wait timer: 5 minutes
- ✅ Deployment branches: Only `production` branch
## 🔄 CI/CD Best Practices
### 1. Feature Branch Workflow
```bash
# Feature branch erstellen
git checkout -b feature/new-feature
# Änderungen committen
git add .
git commit -m "Add new feature"
# Push und Pull Request erstellen
git push origin feature/new-feature
# Nach Review: Merge in main (automatisches Staging Deployment)
# Dann: Merge in production (automatisches Production Deployment)
```
### 2. Semantic Versioning
Verwende Git Tags für Releases:
```bash
# Tag erstellen
git tag -a v1.0.0 -m "Release version 1.0.0"
git push origin v1.0.0
# Workflow wird Docker Image mit diesem Tag bauen
```
### 3. Rollback Strategy
```bash
# Bei Problemen: Zu vorheriger Version zurück
gh workflow run deploy-azure.yml \
--ref <previous-commit-sha> \
--field environment=production
# Oder: Kubernetes Rollback
kubectl rollout undo deployment/laravel-app -n laravel-app
```
## 📚 Weitere Ressourcen
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
- [Azure DevOps Documentation](https://docs.microsoft.com/en-us/azure/devops/)
- [Terraform Cloud](https://www.terraform.io/cloud) - Alternative für Terraform State Management
## 🎯 Nächste Schritte
Nach Setup der CI/CD Pipeline:
1. [ ] Teste Pipeline mit Dummy-Commit
2. [ ] Erstelle Feature Branch und PR
3. [ ] Richte Branch Protection Rules ein
4. [ ] Konfiguriere GitHub Environments
5. [ ] Dokumentiere Team-Workflow
6. [ ] Teste Rollback-Prozess
7. [ ] Richte Slack/Teams Notifications ein (optional)
---
**Support**: Bei Problemen prüfe GitHub Actions Logs und Terraform State
@@ -0,0 +1,398 @@
# 🚀 Quickstart Guide - Laravel auf Azure AKS
Diese Anleitung führt dich in ~30 Minuten durch das komplette Deployment deiner Laravel-Anwendung auf Azure Kubernetes Service.
## ✅ Voraussetzungen Check
```bash
# Prüfe ob alle Tools installiert sind
terraform version # >= 1.9.0
az version # >= 2.0
kubectl version # >= 1.28
docker version # >= 20.10
php -v # >= 8.2
```
## 📝 Schritt-für-Schritt Anleitung
### 1️⃣ Azure Login (2 Min)
```bash
# Login
az login
# Subscription setzen
az account set --subscription "77677a80-2dea-493d-9867-f1c961b80fb3"
# Verify
az account show
```
### 2️⃣ Container Registry Setup (5 Min)
```bash
# ACR erstellen (wenn nicht vorhanden)
az acr create \
--resource-group trusted_ai_demo_rg \
--name mylaravelregistry \
--sku Basic \
--location germanywestcentral
# AKS Zugriff auf ACR geben
az aks update \
--resource-group trusted_ai_demo_rg \
--name trai_k8s_cluster \
--attach-acr mylaravelregistry
# Login
az acr login --name mylaravelregistry
```
### 3️⃣ Docker Image Build & Push (5 Min)
```bash
# Zum Projekt-Root wechseln
cd /Users/sebastianfrohlich/Herd/frontend
# Image bauen
docker build -t mylaravelregistry.azurecr.io/laravel-app:v1.0.0 .
# Image pushen
docker push mylaravelregistry.azurecr.io/laravel-app:v1.0.0
```
### 4️⃣ Laravel APP_KEY generieren (1 Min)
```bash
# Im Projekt-Root
php artisan key:generate --show
# Beispiel Output: base64:abcdefgh12345...
# Kopiere diesen Wert für den nächsten Schritt
```
### 5️⃣ Terraform Konfiguration (5 Min)
```bash
# Zu Terraform wechseln
cd terraform
# Konfiguration kopieren
cp terraform.tfvars.example terraform.tfvars
# Bearbeiten
nano terraform.tfvars
```
**Wichtige Werte in `terraform.tfvars` ändern:**
```hcl
# Docker Image (von Schritt 3)
docker_image = "mylaravelregistry.azurecr.io/laravel-app:v1.0.0"
# Laravel Key (von Schritt 4)
app_key = "base64:abcdefgh12345..."
# PostgreSQL Password (sicheres Passwort wählen!)
postgresql_admin_password = "YourSecurePassword123!"
# Email für Alerts
alert_email_address = "your-email@example.com"
```
### 6️⃣ Deployment ausführen (10 Min)
```bash
# Automatisches Deployment mit Script
./scripts/deploy.sh
```
Das Script führt automatisch aus:
- ✅ Prerequisite-Check
- ✅ Terraform init
- ✅ Terraform validate
- ✅ Terraform plan
- ✅ Terraform apply (nach Bestätigung)
- ✅ kubectl konfigurieren
- ✅ Pod-Status prüfen
**Oder manuell:**
```bash
# Init
terraform init
# Plan
terraform plan -out=tfplan
# Apply
terraform apply tfplan
# kubectl konfigurieren
az aks get-credentials \
--resource-group trusted_ai_demo_rg \
--name trai_k8s_cluster \
--overwrite-existing
```
### 7️⃣ Datenbank wiederherstellen (5 Min)
```bash
# Automatisches Restore-Script
./scripts/restore-db.sh
# Script fragt:
# - Welches Backup-File? (z.B. backup_backend_20251203_101741.dump)
# - Bestätigung: yes
# - Zeigt Fortschritt und Logs
```
**Oder in terraform.tfvars setzen und nochmal apply:**
```hcl
db_restore_enabled = true
db_backup_file_path = "../backups/backup_backend_20251203_101741.dump"
```
```bash
terraform apply
```
### 8️⃣ Anwendung testen (2 Min)
```bash
# LoadBalancer IP abrufen
kubectl get svc ingress-nginx-controller -n ingress-nginx
# Oder über Terraform Output
terraform output app_url
# Example Output:
# app_url = "http://20.79.123.456"
```
🎉 **Öffne die URL im Browser!**
### 9️⃣ Status prüfen
```bash
# Pods prüfen
kubectl get pods -n laravel-app
# Services prüfen
kubectl get svc -n laravel-app
# Ingress prüfen
kubectl get ingress -n laravel-app
# Logs anzeigen
kubectl logs -n laravel-app -l app=laravel-app -f
# Database restore job prüfen (wenn aktiviert)
kubectl get jobs -n laravel-app
kubectl logs -n laravel-app -l job-type=database-restore
```
## 🔧 Häufige Probleme
### Problem: Pods starten nicht (ImagePullBackOff)
```bash
# Prüfe ob ACR-Integration funktioniert
az aks check-acr \
--resource-group trusted_ai_demo_rg \
--name trai_k8s_cluster \
--acr mylaravelregistry.azurecr.io
# Fix: ACR Integration neu setzen
az aks update \
--resource-group trusted_ai_demo_rg \
--name trai_k8s_cluster \
--attach-acr mylaravelregistry
```
### Problem: LoadBalancer IP bleibt "Pending"
```bash
# Prüfe Service Events
kubectl describe svc ingress-nginx-controller -n ingress-nginx
# Warte 5-10 Minuten - Azure braucht Zeit für LoadBalancer Setup
kubectl get svc -n ingress-nginx -w
```
### Problem: Database Connection Failed
```bash
# Prüfe PostgreSQL Firewall Rules
az postgres flexible-server firewall-rule list \
--resource-group trusted_ai_demo_rg \
--name <server-name>
# Prüfe Secrets
kubectl get secret laravel-app-db-credentials -n laravel-app -o yaml | grep DB_
```
### Problem: 502 Bad Gateway
```bash
# Prüfe ob Pods ready sind
kubectl get pods -n laravel-app
# Prüfe Pod Logs
kubectl logs -n laravel-app <pod-name>
# Teste direkt zum Service
kubectl port-forward -n laravel-app svc/laravel-app 8080:80
# Dann: http://localhost:8080
```
## 📊 Nützliche Befehle
### Status-Übersicht
```bash
# Alles auf einen Blick
kubectl get all -n laravel-app
kubectl get all -n ingress-nginx
# Terraform Outputs
terraform output
```
### Logs anzeigen
```bash
# Application Logs (alle Pods)
kubectl logs -n laravel-app -l app=laravel-app -f
# Bestimmter Pod
kubectl logs -n laravel-app <pod-name> -f
# Ingress Controller Logs
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller -f
```
### Scale Up/Down
```bash
# Mehr Replicas
kubectl scale deployment/laravel-app --replicas=3 -n laravel-app
# Prüfen
kubectl get pods -n laravel-app
```
### Shell in Pod
```bash
# Shell öffnen
kubectl exec -it -n laravel-app <pod-name> -- /bin/sh
# Laravel Artisan in Pod ausführen
kubectl exec -it -n laravel-app <pod-name> -- php artisan migrate:status
kubectl exec -it -n laravel-app <pod-name> -- php artisan route:list
```
### Port-Forward für lokalen Zugriff
```bash
# App direkt aufrufen (ohne LoadBalancer)
kubectl port-forward -n laravel-app svc/laravel-app 8080:80
# Dann: http://localhost:8080
```
## 🔄 Updates deployen
### Neue Version deployen
```bash
# 1. Code ändern
# 2. Neues Image bauen
docker build -t mylaravelregistry.azurecr.io/laravel-app:v1.0.1 .
docker push mylaravelregistry.azurecr.io/laravel-app:v1.0.1
# 3. Deployment updaten (schnell)
kubectl set image deployment/laravel-app \
laravel-app=mylaravelregistry.azurecr.io/laravel-app:v1.0.1 \
-n laravel-app
# Rollout Status prüfen
kubectl rollout status deployment/laravel-app -n laravel-app
```
### Rollback
```bash
# Zur vorherigen Version zurück
kubectl rollout undo deployment/laravel-app -n laravel-app
```
## 🧹 Cleanup
### Nur App löschen (DB behalten)
```bash
terraform destroy -target=kubernetes_deployment.app
terraform destroy -target=kubernetes_service.app
```
### Alles löschen
```bash
terraform destroy
```
## 📚 Weitere Informationen
- Ausführliche Dokumentation: [README.md](README.md)
- Terraform Outputs: `terraform output`
- Azure Portal: https://portal.azure.com
## 🆘 Hilfe benötigt?
```bash
# Terraform Outputs anzeigen
terraform output deployment_instructions
# Kubernetes Events prüfen
kubectl get events -n laravel-app --sort-by='.lastTimestamp'
# Resource Status
kubectl describe deployment laravel-app -n laravel-app
kubectl describe svc laravel-app -n laravel-app
```
## ✨ Next Steps
Nach erfolgreichem Deployment:
1. **Domain konfigurieren** (optional):
```hcl
# In terraform.tfvars
ingress_host = "app.yourdomain.com"
ssl_enabled = true
ssl_issuer_email = "admin@yourdomain.com"
```
```bash
terraform apply
```
2. **Monitoring einrichten**: Prüfe Azure Monitor in Azure Portal
3. **CI/CD Pipeline**: Erstelle GitHub Actions oder Azure DevOps Pipeline
4. **Backups testen**: Teste Restore-Prozess
5. **Security Hardening**:
- VNet Integration für PostgreSQL
- Private Endpoints
- RBAC konfigurieren
---
**Deployment Time:** ~30 Minuten
**Kosten:** ~50-100€/Monat (abhängig von Ressourcen)
**Scaling:** Horizontal (mehr Pods) & Vertikal (größere VMs)
@@ -0,0 +1,841 @@
# Laravel Application Deployment auf Azure Kubernetes Service (AKS)
Diese Terraform-Konfiguration stellt deine Laravel-Anwendung auf Azure Kubernetes Service (AKS) bereit und erstellt eine Azure PostgreSQL Datenbank.
## 📋 Inhaltsverzeichnis
- [Voraussetzungen](#voraussetzungen)
- [Architektur-Übersicht](#architektur-übersicht)
- [Schnellstart](#schnellstart)
- [Detaillierte Anleitung](#detaillierte-anleitung)
- [Konfiguration](#konfiguration)
- [Deployment](#deployment)
- [Datenbank-Wiederherstellung](#datenbank-wiederherstellung)
- [Troubleshooting](#troubleshooting)
- [Wartung](#wartung)
## Voraussetzungen
Folgende Tools müssen installiert sein:
- [Terraform](https://www.terraform.io/downloads.html) >= 1.9.0
- [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) >= 2.0
- [kubectl](https://kubernetes.io/docs/tasks/tools/) >= 1.28
- [Docker](https://docs.docker.com/get-docker/) >= 20.10
- [PHP](https://www.php.net/downloads) >= 8.2 (für lokale Laravel-Befehle)
## Architektur-Übersicht
```
┌─────────────────────────────────────────────────────────────┐
│ Azure Cloud │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Resource Group: trusted_ai_demo_rg │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────────┐ │ │
│ │ │ AKS Cluster: trai_k8s_cluster │ │ │
│ │ │ │ │ │
│ │ │ ┌────────────────────────────────────────────┐ │ │ │
│ │ │ │ Namespace: laravel-app │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ • Deployment (2+ Pods) │ │ │ │
│ │ │ │ • Service (ClusterIP) │ │ │ │
│ │ │ │ • ConfigMaps & Secrets │ │ │ │
│ │ │ │ • Horizontal Pod Autoscaler │ │ │ │
│ │ │ └────────────────────────────────────────────┘ │ │ │
│ │ │ │ │ │
│ │ │ ┌────────────────────────────────────────────┐ │ │ │
│ │ │ │ Namespace: ingress-nginx │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ • Nginx Ingress Controller │ │ │ │
│ │ │ │ • LoadBalancer Service (Public IP) │ │ │ │
│ │ │ └────────────────────────────────────────────┘ │ │ │
│ │ └──────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────────┐ │ │
│ │ │ Azure PostgreSQL Flexible Server │ │ │
│ │ │ │ │ │
│ │ │ • PostgreSQL 16 │ │ │
│ │ │ • 32 GB Storage │ │ │
│ │ │ • Automated Backups (7 days) │ │ │
│ │ └──────────────────────────────────────────────────┘ │ │
│ └────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
### Komponenten:
1. **AKS Cluster**: Bestehender Kubernetes-Cluster
2. **Laravel Application**: Containerisierte Laravel-App mit Nginx + PHP-FPM
3. **PostgreSQL Database**: Azure Database for PostgreSQL Flexible Server
4. **Nginx Ingress Controller**: Load Balancer für externen Zugriff
5. **Secrets Management**: Kubernetes Secrets für sensible Daten
## Schnellstart
### 1. Azure CLI Login
```bash
az login
az account set --subscription "77677a80-2dea-493d-9867-f1c961b80fb3"
```
### 2. Docker Image erstellen und pushen
Erstelle zuerst eine Azure Container Registry (falls noch nicht vorhanden):
```bash
# Container Registry erstellen
az acr create \
--resource-group trusted_ai_demo_rg \
--name mylaravelregistry \
--sku Basic \
--location germanywestcentral
# In Registry einloggen
az acr login --name mylaravelregistry
```
Dann baue und pushe das Docker Image:
```bash
# Zurück zum Projekt-Root
cd /Users/sebastianfrohlich/Herd/frontend
# Docker Image bauen
docker build -t mylaravelregistry.azurecr.io/laravel-app:v1.0.0 .
# Image pushen
docker push mylaravelregistry.azurecr.io/laravel-app:v1.0.0
```
### 3. Terraform konfigurieren
```bash
cd terraform
# Kopiere die Beispiel-Konfiguration
cp terraform.tfvars.example terraform.tfvars
# Bearbeite terraform.tfvars
nano terraform.tfvars
```
Wichtige Werte in `terraform.tfvars`:
```hcl
docker_image = "mylaravelregistry.azurecr.io/laravel-app:v1.0.0"
app_key = "base64:YOUR_GENERATED_KEY" # Generiere mit: php artisan key:generate --show
postgresql_admin_password = "YourSecurePassword123!"
alert_email_address = "your-email@example.com"
```
### 4. Deployment ausführen
```bash
# Automatisches Deployment mit Script
./scripts/deploy.sh
```
Oder manuell:
```bash
# Terraform initialisieren
terraform init
# Plan überprüfen
terraform plan
# Deployment ausführen
terraform apply
```
### 5. Datenbank wiederherstellen
```bash
# Interaktives Restore-Script
./scripts/restore-db.sh
```
Oder manuell:
```bash
# Setze db_restore_enabled = true in terraform.tfvars
terraform apply
```
## Detaillierte Anleitung
### Schritt 1: Azure Container Registry (ACR) Setup
Die Laravel-Anwendung muss als Docker Image bereitgestellt werden:
```bash
# ACR erstellen (wenn nicht vorhanden)
az acr create \
--resource-group trusted_ai_demo_rg \
--name mylaravelregistry \
--sku Basic
# Admin-Zugriff aktivieren (optional, für einfachere Handhabung)
az acr update -n mylaravelregistry --admin-enabled true
# Login credentials abrufen
az acr credential show --name mylaravelregistry
# Docker login
az acr login --name mylaravelregistry
```
### Schritt 2: Docker Image Build & Push
```bash
cd /Users/sebastianfrohlich/Herd/frontend
# Image mit Tag bauen
docker build -t mylaravelregistry.azurecr.io/laravel-app:latest .
docker build -t mylaravelregistry.azurecr.io/laravel-app:v1.0.0 .
# Image pushen
docker push mylaravelregistry.azurecr.io/laravel-app:latest
docker push mylaravelregistry.azurecr.io/laravel-app:v1.0.0
```
### Schritt 3: AKS Pull-Berechtigung für ACR
```bash
# AKS Pull-Berechtigung für ACR erteilen
az aks update \
--resource-group trusted_ai_demo_rg \
--name trai_k8s_cluster \
--attach-acr mylaravelregistry
```
### Schritt 4: Laravel APP_KEY generieren
```bash
cd /Users/sebastianfrohlich/Herd/frontend
php artisan key:generate --show
```
Kopiere den Output (z.B. `base64:xyz...`) in deine `terraform.tfvars`.
### Schritt 5: Terraform Konfiguration
Erstelle `terraform/terraform.tfvars`:
```hcl
# Azure Configuration
subscription_id = "77677a80-2dea-493d-9867-f1c961b80fb3"
resource_group_name = "trusted_ai_demo_rg"
location = "germanywestcentral"
aks_cluster_name = "trai_k8s_cluster"
# Application Configuration
app_name = "laravel-app"
app_namespace = "laravel-app"
app_env = "production"
app_debug = false
app_replicas = 2
# Docker Image
docker_image = "mylaravelregistry.azurecr.io/laravel-app:v1.0.0"
# Laravel APP_KEY (generiert mit: php artisan key:generate --show)
app_key = "base64:YOUR_ACTUAL_KEY_HERE"
# PostgreSQL Configuration
postgresql_admin_username = "pgadmin"
postgresql_admin_password = "YourVerySecurePassword123!"
postgresql_sku_name = "B_Standard_B1ms"
postgresql_storage_mb = 32768
postgresql_version = "16"
postgresql_backup_retention_days = 7
# Ingress Configuration
ingress_enabled = true
ingress_host = "" # Leer lassen für IP-basierten Zugriff
# SSL/TLS Configuration (optional, später aktivieren)
ssl_enabled = false
ssl_issuer_email = ""
# Database Restore Configuration
db_restore_enabled = true
db_backup_file_path = "../backups/backup_backend_20251203_101741.dump"
# Alert Configuration
alert_email_address = "your-email@example.com"
```
### Schritt 6: Terraform Deployment
```bash
cd /Users/sebastianfrohlich/Herd/frontend/terraform
# Terraform initialisieren
terraform init
# Validierung
terraform validate
# Plan erstellen und überprüfen
terraform plan -out=tfplan
# Deployment ausführen
terraform apply tfplan
# Outputs anzeigen
terraform output
terraform output deployment_instructions
```
### Schritt 7: kubectl konfigurieren
```bash
# kubectl Credentials abrufen
az aks get-credentials \
--resource-group trusted_ai_demo_rg \
--name trai_k8s_cluster \
--overwrite-existing
# Cluster-Zugriff testen
kubectl get nodes
# Pods prüfen
kubectl get pods -n laravel-app
# Services prüfen
kubectl get svc -n laravel-app
kubectl get svc -n ingress-nginx
```
### Schritt 8: Anwendung testen
```bash
# LoadBalancer IP abrufen
kubectl get svc ingress-nginx-controller -n ingress-nginx
# External IP sollte angezeigt werden, z.B.:
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
# ingress-nginx-controller LoadBalancer 10.0.45.123 20.79.123.456 80:31234/TCP,443:31567/TCP
# Anwendung im Browser öffnen:
# http://<EXTERNAL-IP>
```
### HTTP Basic Authentication
Die Anwendung ist mit HTTP Basic Auth geschützt:
- **Benutzer**: `afc-user`
- **Passwort**: `vDZFrZ+*~4gW=3^?-,:8{ga=7M.o5k,G`
Die Credentials sind in [`deploy/nginx/.htpasswd`](../deploy/nginx/.htpasswd) konfiguriert und werden während des Docker-Builds in das Image kopiert.
### Aktueller Deployment-Status
**Aktuell deployed**: Version `1.0.7`
**Aktuelle Konfiguration**:
- URL: `http://72.144.113.194/`
- Docker Image: `laravelappreg.azurecr.io/laravel-app:1.0.7`
- Replicas: 2
- Datenbank: `laravel_app` (PostgreSQL 16) mit 3 Schemas
- HTTP Basic Auth: Aktiv
**Letzte Änderungen (v1.0.7)**:
- HTTP Basic Authentication hinzugefügt
- Nginx Redirect für Livewire JavaScript (`.min.js` → `.js`)
- Alle 3 Datenbank-Schemas nach `laravel_app` migriert
- Datenbankverbindungen in `config/database.php` aktualisiert
- Session-Driver auf `database` umgestellt (Multi-Pod Support)
## Konfiguration
### Umgebungsvariablen
Die Laravel-Umgebungsvariablen werden über Kubernetes ConfigMaps und Secrets verwaltet:
**ConfigMap** (`kubernetes_config_map.app_config`):
- APP_NAME, APP_ENV, APP_DEBUG, APP_URL
- Session, Cache, Queue, Mail Konfiguration
**Secrets** (`kubernetes_secret.app_secrets`):
- APP_KEY
**Database Secrets** (`kubernetes_secret.db_credentials`):
- DB_CONNECTION, DB_HOST, DB_PORT, DB_DATABASE
- DB_USERNAME, DB_PASSWORD
### Resource Limits
Standard-Einstellungen in `variables.tf`:
```hcl
app_resources_requests_cpu = "100m"
app_resources_requests_memory = "256Mi"
app_resources_limits_cpu = "500m"
app_resources_limits_memory = "512Mi"
```
Diese können in `terraform.tfvars` überschrieben werden.
### Horizontal Pod Autoscaling
Die Anwendung skaliert automatisch basierend auf CPU und Memory:
- Min Replicas: `app_replicas` (default: 2)
- Max Replicas: `app_replicas * 3` (default: 6)
- CPU Threshold: 80%
- Memory Threshold: 80%
## Datenbank-Konfiguration
### Datenbank-Struktur
Die Anwendung verwendet **eine PostgreSQL-Datenbank** (`laravel_app`) mit **drei Schemas**:
#### 1. **public** Schema (12 Tabellen)
Standard Laravel-Tabellen und Application-Daten:
- backend_data_pool, cache, cache_locks
- companies, failed_jobs, job_batches, jobs
- migrations, password_reset_tokens, sessions
- transactions, users
**Connection**: `DB::connection('pgsql_second')` oder `DB::connection('pgsql')`
#### 2. **backend** Schema (11 Tabellen)
Backend-spezifische Daten:
- entity_corporate_context, evidence_registry
- fallback_events, internal_context_blobs
- prompt_results, prompt_runs, prompt_templates, prompt_token_metrics
- sources, transaction_outputs, transactions
**Connection**: `DB::connection('backend')`
#### 3. **devbackend** Schema (13 Tabellen)
Development/Testing Backend-Daten:
- document_facts, entity_corporate_context
- evidence_registry, fallback_events
- internal_context_blobs, pdf_documents
- prompt_results, prompt_runs, prompt_templates, prompt_token_metrics
- sources, transaction_outputs, transactions
**Connection**: `DB::connection('devbackend')`
### Verwendung in Laravel
```php
// Public Schema (Standard)
$users = DB::connection('pgsql')->table('users')->get();
$users = DB::connection('pgsql_second')->table('users')->get();
// Backend Schema
$transactions = DB::connection('backend')->table('transactions')->get();
// DevBackend Schema
$documents = DB::connection('devbackend')->table('pdf_documents')->get();
```
Alle Connections sind in [config/database.php](../config/database.php) konfiguriert und zeigen auf dieselbe Datenbank `laravel_app` mit unterschiedlichen `search_path` Einstellungen.
## Datenbank-Wiederherstellung
### Automatische Wiederherstellung während Deployment
Die Datenbank-Wiederherstellung importiert alle drei Schemas in die `laravel_app` Datenbank:
```bash
# Backups befinden sich in:
/Users/sebastianfrohlich/Herd/frontend/backups/
- backup_public_20251203_101723.dump # Public Schema
- backup_backend_20251203_101741.dump # Backend Schema
- backup_devbackend_20251203_103857.dump # DevBackend Schema
```
Setze in `terraform.tfvars`:
```hcl
db_restore_enabled = true
db_backup_file_path = "../backups/backup_backend_20251203_101741.dump"
```
Das Backup wird als Kubernetes Job ausgeführt.
### Manuelle Wiederherstellung
```bash
# Interaktives Script
./scripts/restore-db.sh
# Script fragt nach:
# - Welche Backup-Datei verwendet werden soll
# - Bestätigung zum Überschreiben der Datenbank
# - Zeigt Fortschritt und Logs an
```
### Manuelles DB-Restore (kubectl)
```bash
# ConfigMap mit Backup erstellen
kubectl create configmap db-restore-backup \
--from-file=backup.dump=/Users/sebastianfrohlich/Herd/frontend/backups/backup_backend_20251203_101741.dump \
-n laravel-app
# Job aus db-restore.tf verwenden oder manuell erstellen
kubectl apply -f - <<EOF
apiVersion: batch/v1
kind: Job
metadata:
name: db-restore-manual
namespace: laravel-app
spec:
template:
spec:
containers:
- name: db-restore
image: postgres:16-alpine
command: ["/bin/sh", "-c"]
args:
- |
set -e
export PGPASSWORD="\$DB_PASSWORD"
pg_restore -h \$DB_HOST -p \$DB_PORT -U \$DB_USERNAME -d \$DB_DATABASE \
--verbose --clean --if-exists --no-owner --no-privileges /backup/backup.dump
envFrom:
- secretRef:
name: laravel-app-db-credentials
volumeMounts:
- name: backup-volume
mountPath: /backup
volumes:
- name: backup-volume
configMap:
name: db-restore-backup
restartPolicy: OnFailure
EOF
# Job-Status prüfen
kubectl get jobs -n laravel-app
# Logs anzeigen
kubectl logs -n laravel-app -l job-name=db-restore-manual -f
```
## Deployment
### Neues Image deployen
```bash
# 1. Neues Image bauen
docker build -t mylaravelregistry.azurecr.io/laravel-app:v1.0.1 .
docker push mylaravelregistry.azurecr.io/laravel-app:v1.0.1
# 2. terraform.tfvars aktualisieren
# docker_image = "mylaravelregistry.azurecr.io/laravel-app:v1.0.1"
# 3. Terraform apply
terraform apply
# Oder direkt kubectl verwenden für schnelleres Update:
kubectl set image deployment/laravel-app \
laravel-app=mylaravelregistry.azurecr.io/laravel-app:v1.0.1 \
-n laravel-app
# Rollout Status prüfen
kubectl rollout status deployment/laravel-app -n laravel-app
```
### Rollback
```bash
# Rollout Historie anzeigen
kubectl rollout history deployment/laravel-app -n laravel-app
# Zu vorheriger Version zurückkehren
kubectl rollout undo deployment/laravel-app -n laravel-app
# Zu spezifischer Revision zurückkehren
kubectl rollout undo deployment/laravel-app --to-revision=2 -n laravel-app
```
### Replicas skalieren
```bash
# Über kubectl
kubectl scale deployment/laravel-app --replicas=3 -n laravel-app
# Über Terraform
# Ändere app_replicas in terraform.tfvars und führe aus:
terraform apply
```
## Troubleshooting
### Pods starten nicht
```bash
# Pod-Status prüfen
kubectl get pods -n laravel-app
# Detaillierte Pod-Informationen
kubectl describe pod <pod-name> -n laravel-app
# Pod-Logs anzeigen
kubectl logs <pod-name> -n laravel-app
# Vorherige Pod-Logs (bei CrashLoopBackOff)
kubectl logs <pod-name> -n laravel-app --previous
```
### Datenbank-Verbindungsprobleme
```bash
# Secrets prüfen
kubectl get secret laravel-app-db-credentials -n laravel-app -o yaml
# PostgreSQL Server Firewall prüfen
az postgres flexible-server firewall-rule list \
--resource-group trusted_ai_demo_rg \
--name <postgresql-server-name>
# Verbindung vom Pod aus testen
kubectl run -it --rm debug --image=postgres:16-alpine -n laravel-app -- \
psql "postgresql://user:pass@host:5432/database"
```
### Ingress funktioniert nicht
```bash
# Ingress Status prüfen
kubectl get ingress -n laravel-app
# Ingress Controller Logs
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller
# LoadBalancer Service prüfen
kubectl get svc -n ingress-nginx
# Ingress Events prüfen
kubectl describe ingress laravel-app-ingress -n laravel-app
```
### SSL/TLS Zertifikat-Probleme
```bash
# cert-manager Pods prüfen
kubectl get pods -n cert-manager
# Certificate Status prüfen
kubectl get certificate -n laravel-app
# Certificate Details
kubectl describe certificate laravel-app-tls -n laravel-app
# cert-manager Logs
kubectl logs -n cert-manager -l app=cert-manager
```
### Performance-Probleme
```bash
# Resource Usage prüfen
kubectl top pods -n laravel-app
kubectl top nodes
# HPA Status prüfen
kubectl get hpa -n laravel-app
# Events prüfen
kubectl get events -n laravel-app --sort-by='.lastTimestamp'
```
## Wartung
### Backups
PostgreSQL Flexible Server erstellt automatische Backups:
```bash
# Backup-Konfiguration prüfen
az postgres flexible-server show \
--resource-group trusted_ai_demo_rg \
--name <postgresql-server-name> \
--query "{backupRetentionDays:backup.backupRetentionDays,geoRedundantBackup:backup.geoRedundantBackup}"
# Manuelles Backup erstellen
az postgres flexible-server backup create \
--resource-group trusted_ai_demo_rg \
--name <postgresql-server-name> \
--backup-name manual-backup-$(date +%Y%m%d)
```
### Updates
#### Terraform Updates
```bash
# Terraform Zustand aktualisieren
terraform refresh
# Änderungen planen
terraform plan
# Änderungen anwenden
terraform apply
```
#### Laravel Updates
```bash
# Composer Dependencies aktualisieren
composer update
# NPM Dependencies aktualisieren
npm update
# Neues Image bauen und deployen
docker build -t mylaravelregistry.azurecr.io/laravel-app:v1.0.2 .
docker push mylaravelregistry.azurecr.io/laravel-app:v1.0.2
# Deployment aktualisieren
kubectl set image deployment/laravel-app \
laravel-app=mylaravelregistry.azurecr.io/laravel-app:v1.0.2 \
-n laravel-app
```
### Monitoring
```bash
# Log Analytics Workspace
az monitor log-analytics workspace show \
--resource-group trusted_ai_demo_rg \
--workspace-name <workspace-name>
# Azure Monitor für Container
# Im Azure Portal: AKS Cluster > Monitoring > Insights
# Prometheus Metrics (wenn aktiviert)
kubectl port-forward -n ingress-nginx \
svc/ingress-nginx-controller-metrics 10254:10254
# Dann: http://localhost:10254/metrics
```
### Cleanup
```bash
# Einzelne Resources löschen
terraform destroy -target=kubernetes_deployment.app
terraform destroy -target=azurerm_postgresql_flexible_server.main
# Alles löschen
terraform destroy
# Namespace löschen (löscht alle Resources im Namespace)
kubectl delete namespace laravel-app
```
## Kosten-Optimierung
### Development/Staging
Für Dev/Staging Umgebungen kannst du Kosten sparen:
```hcl
# terraform.tfvars für Staging
postgresql_sku_name = "B_Standard_B1ms" # Burstable tier
postgresql_storage_mb = 32768 # 32 GB
app_replicas = 1 # Weniger Replicas
aks_node_pool_min_count = 1 # Weniger Nodes
```
### Production
Für Production empfohlen:
```hcl
postgresql_sku_name = "GP_Standard_D2s_v3" # General Purpose
postgresql_storage_mb = 131072 # 128 GB
postgresql_backup_retention_days = 35 # Längere Retention
app_replicas = 3 # Mehr Replicas
```
## Sicherheit
### Best Practices
1. **Secrets Management**:
- Verwende Azure Key Vault für Production
- Rotiere Passwörter regelmäßig
- Verwende starke, generierte Passwörter
2. **Network Security**:
- Aktiviere VNet Integration für PostgreSQL
- Verwende Private Endpoints
- Beschränke Firewall-Regeln
3. **SSL/TLS**:
- Aktiviere SSL für Production:
```hcl
ssl_enabled = true
ssl_issuer_email = "admin@yourdomain.com"
ingress_host = "app.yourdomain.com"
```
4. **RBAC**:
- Verwende Kubernetes RBAC
- Minimale Berechtigungen für Service Accounts
## Support und Kontakt
Bei Fragen oder Problemen:
1. Prüfe die [Troubleshooting](#troubleshooting) Sektion
2. Prüfe Kubernetes Events: `kubectl get events -n laravel-app`
3. Prüfe Logs: `kubectl logs -n laravel-app -l app=laravel-app`
## Anhang
### Nützliche Befehle
```bash
# Alle Resources in einem Namespace anzeigen
kubectl get all -n laravel-app
# Port-forward für lokalen Zugriff
kubectl port-forward -n laravel-app svc/laravel-app 8080:80
# Shell in einem Pod öffnen
kubectl exec -it -n laravel-app <pod-name> -- /bin/sh
# ConfigMap/Secret bearbeiten
kubectl edit configmap laravel-app-config -n laravel-app
# Resource Usage live monitoren
watch kubectl top pods -n laravel-app
# Cluster Info
kubectl cluster-info
kubectl get nodes -o wide
```
### Terraform State Management
Für Team-Arbeit solltest du Remote State verwenden:
```hcl
# backend.hcl
resource_group_name = "trusted_ai_demo_rg"
storage_account_name = "tfstate<random>"
container_name = "tfstate"
key = "laravel-app.terraform.tfstate"
```
```bash
# Backend initialisieren
terraform init -backend-config=backend.hcl
```
@@ -0,0 +1,15 @@
# Note: Database backup files are too large for ConfigMaps (>1MB limit)
# Use manual restore via kubectl after deployment instead:
#
# kubectl cp ../backups/backup_backend_20251203_101741.dump \
# laravel-app/postgresql-0:/tmp/backup.dump
#
# kubectl exec -it -n laravel-app postgresql-0 -- \
# pg_restore -U pgadmin -d laravel_app --clean --if-exists \
# /tmp/backup.dump
#
# Or use the restore script: ./scripts/restore-db.sh
# Disabled: Automatic database restore via Terraform
# The ConfigMap approach doesn't work for files >1MB
# Use manual restore after deployment (see comments above)
@@ -0,0 +1,230 @@
# Install nginx-ingress-controller via Helm
resource "helm_release" "nginx_ingress" {
count = var.ingress_enabled ? 1 : 0
name = "ingress-nginx"
repository = "https://kubernetes.github.io/ingress-nginx"
chart = "ingress-nginx"
version = "4.11.3"
namespace = "ingress-nginx"
create_namespace = true
set {
name = "controller.service.type"
value = "LoadBalancer"
}
set {
name = "controller.service.annotations.service\\.beta\\.kubernetes\\.io/azure-load-balancer-health-probe-request-path"
value = "/healthz"
}
set {
name = "controller.metrics.enabled"
value = "true"
}
set {
name = "controller.podAnnotations.prometheus\\.io/scrape"
value = "true"
}
set {
name = "controller.podAnnotations.prometheus\\.io/port"
value = "10254"
}
# Resource limits
set {
name = "controller.resources.requests.cpu"
value = "100m"
}
set {
name = "controller.resources.requests.memory"
value = "128Mi"
}
set {
name = "controller.resources.limits.cpu"
value = "500m"
}
set {
name = "controller.resources.limits.memory"
value = "512Mi"
}
# Enable rate limiting
set {
name = "controller.config.limit-req-status-code"
value = "429"
}
timeout = 600
}
# Wait for nginx-ingress to be ready and get LoadBalancer IP
data "kubernetes_service" "ingress_nginx" {
count = var.ingress_enabled ? 1 : 0
metadata {
name = "ingress-nginx-controller"
namespace = "ingress-nginx"
}
depends_on = [
helm_release.nginx_ingress
]
}
# Install cert-manager for SSL/TLS (optional)
resource "helm_release" "cert_manager" {
count = var.ssl_enabled ? 1 : 0
name = "cert-manager"
repository = "https://charts.jetstack.io"
chart = "cert-manager"
version = "v1.16.2"
namespace = "cert-manager"
create_namespace = true
set {
name = "crds.enabled"
value = "true"
}
set {
name = "global.leaderElection.namespace"
value = "cert-manager"
}
timeout = 600
}
# ClusterIssuer for Let's Encrypt (production)
resource "kubernetes_manifest" "letsencrypt_prod" {
count = var.ssl_enabled && var.ssl_issuer_email != "" ? 1 : 0
manifest = {
apiVersion = "cert-manager.io/v1"
kind = "ClusterIssuer"
metadata = {
name = "letsencrypt-prod"
}
spec = {
acme = {
server = "https://acme-v02.api.letsencrypt.org/directory"
email = var.ssl_issuer_email
privateKeySecretRef = {
name = "letsencrypt-prod"
}
solvers = [
{
http01 = {
ingress = {
class = "nginx"
}
}
}
]
}
}
}
depends_on = [
helm_release.cert_manager
]
}
# ClusterIssuer for Let's Encrypt (staging) - for testing
resource "kubernetes_manifest" "letsencrypt_staging" {
count = var.ssl_enabled && var.ssl_issuer_email != "" ? 1 : 0
manifest = {
apiVersion = "cert-manager.io/v1"
kind = "ClusterIssuer"
metadata = {
name = "letsencrypt-staging"
}
spec = {
acme = {
server = "https://acme-staging-v02.api.letsencrypt.org/directory"
email = var.ssl_issuer_email
privateKeySecretRef = {
name = "letsencrypt-staging"
}
solvers = [
{
http01 = {
ingress = {
class = "nginx"
}
}
}
]
}
}
}
depends_on = [
helm_release.cert_manager
]
}
# Kubernetes Ingress for Laravel Application
resource "kubernetes_ingress_v1" "app" {
count = var.ingress_enabled ? 1 : 0
metadata {
name = "${var.app_name}-ingress"
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
annotations = merge(
{
"kubernetes.io/ingress.class" = "nginx"
"nginx.ingress.kubernetes.io/rewrite-target" = "/"
"nginx.ingress.kubernetes.io/ssl-redirect" = var.ssl_enabled ? "true" : "false"
},
var.ssl_enabled && var.ingress_host != "" ? {
"cert-manager.io/cluster-issuer" = "letsencrypt-prod"
} : {}
)
}
spec {
dynamic "tls" {
for_each = var.ssl_enabled && var.ingress_host != "" ? [1] : []
content {
hosts = [var.ingress_host]
secret_name = "${var.app_name}-tls"
}
}
rule {
host = var.ingress_host != "" ? var.ingress_host : null
http {
path {
path = "/"
path_type = "Prefix"
backend {
service {
name = kubernetes_service.app.metadata[0].name
port {
number = 80
}
}
}
}
}
}
}
depends_on = [
helm_release.nginx_ingress,
kubernetes_service.app
]
}
@@ -0,0 +1,274 @@
# Kubernetes Namespace
resource "kubernetes_namespace" "app" {
metadata {
name = var.app_namespace
labels = merge(
local.common_labels,
{
name = var.app_namespace
}
)
}
}
# Kubernetes Secret for Database Connection
resource "kubernetes_secret" "db_credentials" {
metadata {
name = "${var.app_name}-db-credentials"
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
}
data = {
# Primary connection uses DB_HOST2 variables (for pgsql_second connection)
DB_CONNECTION2 = "pgsql"
DB_HOST2 = "postgresql.${kubernetes_namespace.app.metadata[0].name}.svc.cluster.local"
DB_PORT2 = "5432"
DB_DATABASE2 = local.postgresql_db_name
DB_USERNAME2 = var.postgresql_admin_username
DB_PASSWORD2 = local.postgresql_admin_pass
# Also set standard DB_ variables for pgsql connection (used by sessions)
DB_CONNECTION = "pgsql"
DB_HOST = "postgresql.${kubernetes_namespace.app.metadata[0].name}.svc.cluster.local"
DB_PORT = "5432"
DB_DATABASE = local.postgresql_db_name
DB_USERNAME = var.postgresql_admin_username
DB_PASSWORD = local.postgresql_admin_pass
}
type = "Opaque"
depends_on = [
kubernetes_service.postgresql
]
}
# Kubernetes Secret for Laravel Application
resource "kubernetes_secret" "app_secrets" {
metadata {
name = "${var.app_name}-secrets"
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
}
data = {
APP_KEY = var.app_key
}
type = "Opaque"
}
# Kubernetes ConfigMap for Laravel Application
resource "kubernetes_config_map" "app_config" {
metadata {
name = "${var.app_name}-config"
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
}
data = {
APP_NAME = var.app_name
APP_ENV = var.app_env
APP_DEBUG = tostring(var.app_debug)
APP_URL = local.app_url
APP_LOCALE = "en"
APP_FALLBACK_LOCALE = "en"
APP_FAKER_LOCALE = "en_US"
LOG_CHANNEL = "stack"
LOG_STACK = "single"
LOG_LEVEL = "info"
SESSION_DRIVER = "database"
SESSION_CONNECTION = "pgsql"
SESSION_LIFETIME = "120"
SESSION_ENCRYPT = "false"
CACHE_STORE = "database"
QUEUE_CONNECTION = "database"
BROADCAST_CONNECTION = "log"
FILESYSTEM_DISK = "local"
MAIL_MAILER = "log"
VITE_APP_NAME = var.app_name
}
}
# Kubernetes Deployment for Laravel Application
resource "kubernetes_deployment" "app" {
metadata {
name = var.app_name
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
}
spec {
replicas = var.app_replicas
selector {
match_labels = {
app = var.app_name
}
}
template {
metadata {
labels = merge(
local.common_labels,
{
version = "latest"
}
)
}
spec {
image_pull_secrets {
name = "acr-secret"
}
container {
name = var.app_name
image = var.docker_image
port {
name = "http"
container_port = 80
protocol = "TCP"
}
env_from {
config_map_ref {
name = kubernetes_config_map.app_config.metadata[0].name
}
}
env_from {
secret_ref {
name = kubernetes_secret.app_secrets.metadata[0].name
}
}
env_from {
secret_ref {
name = kubernetes_secret.db_credentials.metadata[0].name
}
}
resources {
requests = {
cpu = var.app_resources_requests_cpu
memory = var.app_resources_requests_memory
}
limits = {
cpu = var.app_resources_limits_cpu
memory = var.app_resources_limits_memory
}
}
liveness_probe {
exec {
command = ["sh", "-c", "ps aux | grep -v grep | grep -q nginx && ps aux | grep -v grep | grep -q php-fpm"]
}
initial_delay_seconds = 30
period_seconds = 10
timeout_seconds = 5
failure_threshold = 3
}
readiness_probe {
exec {
command = ["sh", "-c", "ps aux | grep -v grep | grep -q nginx && ps aux | grep -v grep | grep -q php-fpm"]
}
initial_delay_seconds = 10
period_seconds = 5
timeout_seconds = 3
failure_threshold = 3
}
}
restart_policy = "Always"
}
}
strategy {
type = "RollingUpdate"
rolling_update {
max_surge = "1"
max_unavailable = "0"
}
}
}
depends_on = [
kubernetes_secret.db_credentials,
kubernetes_secret.app_secrets,
kubernetes_config_map.app_config
]
}
# Kubernetes Service for Laravel Application
resource "kubernetes_service" "app" {
metadata {
name = var.app_name
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
}
spec {
selector = {
app = var.app_name
}
port {
name = "http"
port = 80
target_port = 80
protocol = "TCP"
}
type = "ClusterIP"
}
depends_on = [
kubernetes_deployment.app
]
}
# Horizontal Pod Autoscaler
resource "kubernetes_horizontal_pod_autoscaler_v2" "app" {
metadata {
name = "${var.app_name}-hpa"
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
}
spec {
scale_target_ref {
api_version = "apps/v1"
kind = "Deployment"
name = kubernetes_deployment.app.metadata[0].name
}
min_replicas = var.app_replicas
max_replicas = var.app_replicas * 3
metric {
type = "Resource"
resource {
name = "cpu"
target {
type = "Utilization"
average_utilization = 80
}
}
}
metric {
type = "Resource"
resource {
name = "memory"
target {
type = "Utilization"
average_utilization = 80
}
}
}
}
}
@@ -0,0 +1,40 @@
# Data sources for existing resources
data "azurerm_resource_group" "main" {
name = var.resource_group_name
}
data "azurerm_kubernetes_cluster" "main" {
name = var.aks_cluster_name
resource_group_name = var.resource_group_name
}
data "azurerm_subscription" "current" {}
# Generate random suffix for unique resource names
resource "random_string" "suffix" {
length = 8
special = false
upper = false
}
# Generate random password for PostgreSQL if not provided
resource "random_password" "postgresql_admin_password" {
count = var.postgresql_admin_password == null ? 1 : 0
length = 32
special = true
}
# Local variables
locals {
app_name_safe = replace(var.app_name, "_", "-")
postgresql_server_name = "${local.app_name_safe}-psql-${random_string.suffix.result}"
postgresql_db_name = replace(var.app_name, "-", "_")
postgresql_admin_pass = var.postgresql_admin_password != null ? var.postgresql_admin_password : random_password.postgresql_admin_password[0].result
app_url = var.app_url != "" ? var.app_url : (var.ingress_host != "" ? "https://${var.ingress_host}" : (var.ingress_enabled ? "http://${try(data.kubernetes_service.ingress_nginx[0].status[0].load_balancer[0].ingress[0].ip, "pending")}" : "ingress-not-enabled"))
common_labels = {
app = var.app_name
environment = var.app_env
managed-by = "terraform"
}
}
@@ -0,0 +1,112 @@
output "resource_group_name" {
description = "Name of the resource group"
value = data.azurerm_resource_group.main.name
}
output "aks_cluster_name" {
description = "Name of the AKS cluster"
value = data.azurerm_kubernetes_cluster.main.name
}
output "postgresql_service_name" {
description = "Name of the PostgreSQL service (in-cluster)"
value = kubernetes_service.postgresql.metadata[0].name
}
output "postgresql_service_fqdn" {
description = "Internal FQDN of the PostgreSQL service (in-cluster)"
value = "postgresql.${kubernetes_namespace.app.metadata[0].name}.svc.cluster.local"
}
output "postgresql_database_name" {
description = "Name of the PostgreSQL database"
value = local.postgresql_db_name
}
output "postgresql_admin_username" {
description = "Administrator username for PostgreSQL"
value = var.postgresql_admin_username
sensitive = true
}
output "postgresql_connection_string" {
description = "PostgreSQL connection string (from within cluster)"
value = "postgresql://${var.postgresql_admin_username}:${nonsensitive(local.postgresql_admin_pass)}@postgresql.${kubernetes_namespace.app.metadata[0].name}.svc.cluster.local:5432/${local.postgresql_db_name}"
sensitive = true
}
output "app_namespace" {
description = "Kubernetes namespace for the application"
value = kubernetes_namespace.app.metadata[0].name
}
output "app_service_name" {
description = "Kubernetes service name for the application"
value = kubernetes_service.app.metadata[0].name
}
output "ingress_enabled" {
description = "Whether ingress is enabled"
value = var.ingress_enabled
}
output "ingress_ip" {
description = "IP address of the ingress controller load balancer"
value = var.ingress_enabled ? try(data.kubernetes_service.ingress_nginx[0].status[0].load_balancer[0].ingress[0].ip, "pending") : "not enabled"
}
output "app_url" {
description = "URL of the Laravel application"
value = var.ingress_enabled ? (var.ingress_host != "" ? "https://${var.ingress_host}" : "http://${try(data.kubernetes_service.ingress_nginx[0].status[0].load_balancer[0].ingress[0].ip, "pending")}") : "ingress not enabled"
}
output "ssl_enabled" {
description = "Whether SSL/TLS is enabled"
value = var.ssl_enabled
}
output "db_restore_info" {
description = "Database restore information"
value = "Database restore disabled in Terraform. Use manual restore via kubectl (see db-restore.tf for instructions)"
}
output "deployment_instructions" {
description = "Next steps after deployment"
value = <<-EOT
========================================
Deployment Complete!
========================================
1. Get kubectl credentials:
az aks get-credentials --resource-group ${data.azurerm_resource_group.main.name} --name ${data.azurerm_kubernetes_cluster.main.name}
2. Check application status:
kubectl get pods -n ${kubernetes_namespace.app.metadata[0].name}
kubectl get svc -n ${kubernetes_namespace.app.metadata[0].name}
kubectl get ingress -n ${kubernetes_namespace.app.metadata[0].name}
3. Check database restore job (if enabled):
kubectl get jobs -n ${kubernetes_namespace.app.metadata[0].name}
kubectl logs -n ${kubernetes_namespace.app.metadata[0].name} -l job-type=database-restore
4. Access the application:
${var.ingress_enabled ? (var.ingress_host != "" ? "https://${var.ingress_host}" : "http://${try(data.kubernetes_service.ingress_nginx[0].status[0].load_balancer[0].ingress[0].ip, "pending")}") : "ingress not enabled - use port-forward"}
5. Port-forward (if ingress not ready):
kubectl port-forward -n ${kubernetes_namespace.app.metadata[0].name} svc/${kubernetes_service.app.metadata[0].name} 8080:80
6. View logs:
kubectl logs -n ${kubernetes_namespace.app.metadata[0].name} -l app=${var.app_name} -f
7. Database connection details (in-cluster):
Host: postgresql.${kubernetes_namespace.app.metadata[0].name}.svc.cluster.local
Database: ${local.postgresql_db_name}
Username: ${var.postgresql_admin_username}
8. Restore database manually:
kubectl cp ../backups/backup_backend_20251203_101741.dump ${kubernetes_namespace.app.metadata[0].name}/postgresql-0:/tmp/backup.dump
kubectl exec -it -n ${kubernetes_namespace.app.metadata[0].name} postgresql-0 -- pg_restore -U ${var.postgresql_admin_username} -d ${local.postgresql_db_name} --clean --if-exists /tmp/backup.dump
========================================
EOT
}
@@ -0,0 +1,168 @@
# PostgreSQL in Kubernetes Cluster
# Using StatefulSet with PersistentVolume for data persistence
# Kubernetes Secret for PostgreSQL
resource "kubernetes_secret" "postgresql" {
metadata {
name = "postgresql-credentials"
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
}
data = {
POSTGRES_USER = var.postgresql_admin_username
POSTGRES_PASSWORD = var.postgresql_admin_password
POSTGRES_DB = local.postgresql_db_name
}
type = "Opaque"
}
# PersistentVolumeClaim for PostgreSQL data
resource "kubernetes_persistent_volume_claim" "postgresql" {
metadata {
name = "postgresql-pvc"
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
}
spec {
access_modes = ["ReadWriteOnce"]
resources {
requests = {
storage = "10Gi"
}
}
}
wait_until_bound = false
}
# PostgreSQL StatefulSet
resource "kubernetes_stateful_set" "postgresql" {
metadata {
name = "postgresql"
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
}
spec {
service_name = "postgresql"
replicas = 1
selector {
match_labels = {
app = "postgresql"
}
}
template {
metadata {
labels = merge(
local.common_labels,
{
app = "postgresql"
}
)
}
spec {
container {
name = "postgresql"
image = "postgres:16-alpine"
port {
container_port = 5432
name = "postgresql"
}
env_from {
secret_ref {
name = kubernetes_secret.postgresql.metadata[0].name
}
}
volume_mount {
name = "postgresql-storage"
mount_path = "/var/lib/postgresql/data"
sub_path = "postgres"
}
resources {
requests = {
cpu = "250m"
memory = "512Mi"
}
limits = {
cpu = "1000m"
memory = "1Gi"
}
}
liveness_probe {
exec {
command = ["pg_isready", "-U", var.postgresql_admin_username]
}
initial_delay_seconds = 30
period_seconds = 10
timeout_seconds = 5
failure_threshold = 3
}
readiness_probe {
exec {
command = ["pg_isready", "-U", var.postgresql_admin_username]
}
initial_delay_seconds = 5
period_seconds = 5
timeout_seconds = 3
failure_threshold = 3
}
}
volume {
name = "postgresql-storage"
persistent_volume_claim {
claim_name = kubernetes_persistent_volume_claim.postgresql.metadata[0].name
}
}
}
}
}
depends_on = [
kubernetes_persistent_volume_claim.postgresql,
kubernetes_secret.postgresql
]
}
# PostgreSQL Service
resource "kubernetes_service" "postgresql" {
metadata {
name = "postgresql"
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
}
spec {
selector = {
app = "postgresql"
}
port {
name = "postgresql"
port = 5432
target_port = 5432
protocol = "TCP"
}
type = "ClusterIP"
cluster_ip = "None" # Headless service for StatefulSet
session_affinity = "None"
}
depends_on = [
kubernetes_stateful_set.postgresql
]
}
@@ -0,0 +1,70 @@
# Azure Database for PostgreSQL Flexible Server
resource "azurerm_postgresql_flexible_server" "main" {
name = local.postgresql_server_name
resource_group_name = data.azurerm_resource_group.main.name
location = var.location
administrator_login = var.postgresql_admin_username
administrator_password = local.postgresql_admin_pass
sku_name = var.postgresql_sku_name
version = var.postgresql_version
storage_mb = var.postgresql_storage_mb
backup_retention_days = var.postgresql_backup_retention_days
geo_redundant_backup_enabled = false
# Public access for initial setup (can be restricted later)
# For production, consider using private endpoints or VNet integration
public_network_access_enabled = true
zone = "1"
tags = merge(
local.common_labels,
{
purpose = "database"
}
)
}
# PostgreSQL Firewall Rule - Allow Azure Services
resource "azurerm_postgresql_flexible_server_firewall_rule" "allow_azure_services" {
name = "AllowAzureServices"
server_id = azurerm_postgresql_flexible_server.main.id
start_ip_address = "0.0.0.0"
end_ip_address = "0.0.0.0"
}
# PostgreSQL Firewall Rule - Allow AKS Outbound IPs
# Note: In production, consider using VNet integration or private endpoints
resource "azurerm_postgresql_flexible_server_firewall_rule" "allow_all_temporary" {
name = "AllowAllTemporary"
server_id = azurerm_postgresql_flexible_server.main.id
start_ip_address = "0.0.0.0"
end_ip_address = "255.255.255.255"
# This is a temporary rule for initial setup
# Replace with specific IP ranges or VNet integration in production
}
# PostgreSQL Database
resource "azurerm_postgresql_flexible_server_database" "main" {
name = local.postgresql_db_name
server_id = azurerm_postgresql_flexible_server.main.id
collation = "en_US.utf8"
charset = "utf8"
}
# PostgreSQL Configuration - Optimize for Laravel
resource "azurerm_postgresql_flexible_server_configuration" "max_connections" {
name = "max_connections"
server_id = azurerm_postgresql_flexible_server.main.id
value = "200"
}
resource "azurerm_postgresql_flexible_server_configuration" "timezone" {
name = "timezone"
server_id = azurerm_postgresql_flexible_server.main.id
value = "UTC"
}
@@ -0,0 +1,27 @@
provider "azurerm" {
features {
resource_group {
prevent_deletion_if_contains_resources = false
}
}
subscription_id = var.subscription_id
environment = "public"
use_cli = true
resource_provider_registrations = "none"
}
provider "kubernetes" {
host = data.azurerm_kubernetes_cluster.main.kube_config[0].host
client_certificate = base64decode(data.azurerm_kubernetes_cluster.main.kube_config[0].client_certificate)
client_key = base64decode(data.azurerm_kubernetes_cluster.main.kube_config[0].client_key)
cluster_ca_certificate = base64decode(data.azurerm_kubernetes_cluster.main.kube_config[0].cluster_ca_certificate)
}
provider "helm" {
kubernetes {
host = data.azurerm_kubernetes_cluster.main.kube_config[0].host
client_certificate = base64decode(data.azurerm_kubernetes_cluster.main.kube_config[0].client_certificate)
client_key = base64decode(data.azurerm_kubernetes_cluster.main.kube_config[0].client_key)
cluster_ca_certificate = base64decode(data.azurerm_kubernetes_cluster.main.kube_config[0].cluster_ca_certificate)
}
}
@@ -0,0 +1,29 @@
terraform {
required_version = ">= 1.9.0"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = "~> 2.33"
}
helm = {
source = "hashicorp/helm"
version = "~> 2.16"
}
random = {
source = "hashicorp/random"
version = "~> 3.6"
}
}
# Use local backend for initial deployment
# For production, consider using remote backend (Azure Storage or Terraform Cloud)
# backend "azurerm" {
# # Backend configuration will be provided via backend-config file or CLI
# # Example: terraform init -backend-config=backend.hcl
# }
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,47 @@
# Azure Configuration
subscription_id = "77677a80-2dea-493d-9867-f1c961b80fb3"
resource_group_name = "trusted_ai_demo_rg"
location = "germanywestcentral"
aks_cluster_name = "trai_k8s_cluster"
# Application Configuration
app_name = "laravel-app"
app_namespace = "laravel-app"
app_env = "production"
app_debug = false
app_replicas = 2
# Docker Image
docker_image = "laravelappreg.azurecr.io/laravel-app:v1.0.1"
# Laravel Application Key
app_key = "base64:hcb6PXhQOot3SKMl7USAimUWY3c3OGVaRFtaJkDRiTc="
# PostgreSQL Configuration
postgresql_admin_username = "pgadmin"
postgresql_admin_password = "SecureLaravelPwd2024!"
postgresql_sku_name = "B_Standard_B1ms"
postgresql_storage_mb = 32768
postgresql_version = "16"
postgresql_backup_retention_days = 7
# Ingress Configuration
ingress_enabled = true
ingress_host = "" # Leave empty for IP-based access, or set to your domain
# SSL/TLS Configuration
ssl_enabled = false
ssl_issuer_email = "" # Required if ssl_enabled = true
# Database Restore Configuration
db_restore_enabled = true
db_backup_file_path = "../backups/backup_backend_20251203_101741.dump"
# Resource Limits
app_resources_requests_cpu = "100m"
app_resources_requests_memory = "256Mi"
app_resources_limits_cpu = "500m"
app_resources_limits_memory = "512Mi"
# Alert Configuration
alert_email_address = "your-email@example.com"
@@ -0,0 +1,47 @@
# Azure Configuration
subscription_id = "77677a80-2dea-493d-9867-f1c961b80fb3"
resource_group_name = "trusted_ai_demo_rg"
location = "germanywestcentral"
aks_cluster_name = "trai_k8s_cluster"
# Application Configuration
app_name = "laravel-app"
app_namespace = "laravel-app"
app_env = "production"
app_debug = false
app_replicas = 2
# Docker Image (Update this with your actual image)
docker_image = "myregistry.azurecr.io/laravel-app:latest"
# Laravel Application Key (Generate with: php artisan key:generate --show)
app_key = "base64:YOUR_APP_KEY_HERE"
# PostgreSQL Configuration
postgresql_admin_username = "pgadmin"
postgresql_admin_password = "ChangeThisPassword123!"
postgresql_sku_name = "B_Standard_B1ms"
postgresql_storage_mb = 32768
postgresql_version = "16"
postgresql_backup_retention_days = 7
# Ingress Configuration
ingress_enabled = true
ingress_host = "" # Leave empty for IP-based access, or set to your domain
# SSL/TLS Configuration
ssl_enabled = false
ssl_issuer_email = "" # Required if ssl_enabled = true
# Database Restore Configuration
db_restore_enabled = false
db_backup_file_path = "../backups/backup_backend_20251203_101741.dump"
# Resource Limits
app_resources_requests_cpu = "100m"
app_resources_requests_memory = "256Mi"
app_resources_limits_cpu = "500m"
app_resources_limits_memory = "512Mi"
# Alert Configuration
alert_email_address = "your-email@example.com"
@@ -0,0 +1,180 @@
variable "subscription_id" {
description = "Azure subscription ID"
type = string
default = "77677a80-2dea-493d-9867-f1c961b80fb3"
}
variable "resource_group_name" {
description = "Name of the existing resource group"
type = string
default = "trusted_ai_demo_rg"
}
variable "location" {
description = "Azure region for resources"
type = string
default = "germanywestcentral"
}
variable "aks_cluster_name" {
description = "Name of the existing AKS cluster"
type = string
default = "trai_k8s_cluster"
}
variable "app_name" {
description = "Name of the application"
type = string
default = "laravel-app"
}
variable "app_namespace" {
description = "Kubernetes namespace for the application"
type = string
default = "laravel-app"
}
variable "docker_image" {
description = "Docker image for the Laravel application"
type = string
# Format: <registry>/<image>:<tag>
# Example: "myregistry.azurecr.io/laravel-app:latest"
}
variable "app_replicas" {
description = "Number of application replicas"
type = number
default = 2
}
variable "app_resources_requests_cpu" {
description = "CPU resource requests for application pods"
type = string
default = "100m"
}
variable "app_resources_requests_memory" {
description = "Memory resource requests for application pods"
type = string
default = "256Mi"
}
variable "app_resources_limits_cpu" {
description = "CPU resource limits for application pods"
type = string
default = "500m"
}
variable "app_resources_limits_memory" {
description = "Memory resource limits for application pods"
type = string
default = "512Mi"
}
# PostgreSQL Variables
variable "postgresql_admin_username" {
description = "Administrator username for PostgreSQL"
type = string
default = "pgadmin"
}
variable "postgresql_admin_password" {
description = "Administrator password for PostgreSQL"
type = string
sensitive = true
}
variable "postgresql_sku_name" {
description = "SKU name for PostgreSQL (e.g., B_Standard_B1ms, GP_Standard_D2s_v3)"
type = string
default = "B_Standard_B1ms"
}
variable "postgresql_storage_mb" {
description = "Storage size in MB for PostgreSQL"
type = number
default = 32768 # 32 GB
}
variable "postgresql_version" {
description = "PostgreSQL version"
type = string
default = "16"
}
variable "postgresql_backup_retention_days" {
description = "Backup retention days for PostgreSQL"
type = number
default = 7
}
# Laravel Application Variables
variable "app_key" {
description = "Laravel application key (base64 encoded)"
type = string
sensitive = true
}
variable "app_env" {
description = "Laravel application environment"
type = string
default = "production"
}
variable "app_debug" {
description = "Enable Laravel debug mode"
type = bool
default = false
}
variable "app_url" {
description = "Laravel application URL"
type = string
# Will be set based on ingress if not provided
default = ""
}
# Ingress Variables
variable "ingress_enabled" {
description = "Enable ingress controller"
type = bool
default = true
}
variable "ingress_host" {
description = "Hostname for the ingress (leave empty for IP-based access)"
type = string
default = ""
}
variable "ssl_enabled" {
description = "Enable SSL/TLS (requires cert-manager)"
type = bool
default = false
}
variable "ssl_issuer_email" {
description = "Email for Let's Encrypt certificate issuer"
type = string
default = ""
}
# Database Restore Variables
variable "db_restore_enabled" {
description = "Enable database restore job on deployment"
type = bool
default = false
}
variable "db_backup_file_path" {
description = "Path to the database backup file (local path that will be uploaded)"
type = string
default = "../backups/backup_backend_20251203_101741.dump"
}
# Alert Variables
variable "alert_email_address" {
description = "Email address for alert notifications"
type = string
sensitive = true
}
@@ -0,0 +1,48 @@
# Local .terraform directories
**/.terraform/*
# .tfstate files
*.tfstate
*.tfstate.*
# Crash log files
crash.log
crash.*.log
# Exclude all .tfvars files, which are likely to contain sensitive data
*.tfvars
*.tfvars.json
# Ignore override files as they are usually used to override resources locally
override.tf
override.tf.json
*_override.tf
*_override.tf.json
# Include override files you do wish to add to version control using negation pattern
# !example_override.tf
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
*tfplan*
# Ignore CLI configuration files
.terraformrc
terraform.rc
# Ignore aztfexport generated files (optional, keep if you want version history)
aztfexportResourceMapping.json
aztfexportSkippedResources.txt
# Ignore Mac OS files
.DS_Store
# Ignore editor/IDE files
.vscode/
.idea/
*.swp
*.swo
*~
# Ignore kubeconfig
kubeconfig
*.kubeconfig
@@ -0,0 +1,22 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/azurerm" {
version = "4.33.0"
constraints = "4.33.0"
hashes = [
"h1:3N8/4SkUbJcy+s4W74sx0KCM75T8U0ytUfSv/rCj3ok=",
"zh:1f61ce7671de78f09a8e7532bfe1366eff6e6af47050de0a06217162638b11a0",
"zh:20f103ad60399090c219685ef71d29713f46aba32499c02cc640508f8821b067",
"zh:22ce8ad46b32be74d7bd13c982f30e5ffc0749a42191de468309d4ca1ee427f2",
"zh:23ec8730b2f22701dbef4fd72459b95800bd4f87dfd517898064e291b807af20",
"zh:273202db879542def36a057072ef1b87aa0f1ccced81029c8ede55508d16080e",
"zh:2c5bc87083e7ddf55e49e3159a4836353a24a01288f78a846399453d33375938",
"zh:5dcae547287b377bc4c8e472e313d2178821264ac00cbf4fc6469dffb27a79cd",
"zh:6601669c92bea9b7c6fc7e1e20a957389e5d7c02d06cd2dcda44c6ef62f3d7df",
"zh:8b91e6153a586be514680c90b0d1a4aee7556a39376100e73dde8e9452537671",
"zh:9b6742b8b4a7bc4efa62794bd3425e39166dd3ac53fbdd8efb3214d79f36ffab",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
"zh:f664e54e87c9466d54adc1f0dff41d8cca8d623aca317ff38aab29522b0d2508",
]
}
@@ -0,0 +1,219 @@
# AKS Cluster Terraform Configuration
Dieses Projekt verwaltet einen Azure Kubernetes Service (AKS) Cluster mit vollständigem Monitoring und Alerting über Terraform.
## Projektübersicht
Der AKS Cluster wurde ursprünglich in Azure erstellt und anschließend mit `aztfexport` in Terraform importiert. Die Konfiguration wurde optimiert und um zusätzliche Monitoring-Komponenten erweitert.
## Infrastruktur-Komponenten
### Netzwerk
- **Resource Group**: `trusted_ai_demo_rg` (Germany West Central)
- **Virtual Network**: `trusted_ai_demo_vn` (10.0.0.0/16)
- **Subnet**: `default` (10.0.0.0/24)
### AKS Cluster
- **Name**: `trai_k8s_cluster`
- **Kubernetes Version**: 1.33
- **VM Size**: `Standard_D2as_v6` (2 vCPUs, 8 GB RAM)
- **Node Count**: 2-3 (Auto-Scaling)
- **Availability Zones**: 1, 2
- **Features**:
- OIDC Issuer enabled
- Workload Identity enabled
- Image Cleaner enabled (wöchentlich)
- Automatische Updates (Sonntags)
- Azure CNI Overlay Networking
### Monitoring & Logging
- **Log Analytics Workspace**: `aksloganalyticstraik8scluster`
- SKU: PerGB2018
- Retention: 30 Tage
- **Data Collection Rule**: Container Insights mit:
- Container Logs V2
- Kubernetes Events
- Pod Inventory
- **OMS Agent**: Automatisch auf allen Nodes deployed
### Alerting
- **Action Group**: Email-Benachrichtigungen
- **Metric Alerts**:
- CPU Usage > 95%
- Memory Working Set > 100%
## Projektstruktur
```
.
├── README.md # Diese Datei
├── main.tf # Haupt-Ressourcendefinitionen
├── variables.tf # Variablendefinitionen
├── terraform.tfvars # Aktuelle Variablenwerte
├── outputs.tf # Output-Definitionen
├── provider.tf # Azure Provider-Konfiguration
├── terraform.tf # Terraform-Einstellungen
├── terraform.tfstate # State-Datei (lokal)
├── aztfexportResourceMapping.json # Import-Mapping
├── aztfexportSkippedResources.txt # Übersprungene Ressourcen
└── cluster-status-commands.md # Nützliche Azure CLI Befehle
```
## Verwendung
### Voraussetzungen
- Terraform >= 1.0
- Azure CLI
- kubectl
- Authentifizierung bei Azure (`az login`)
### Initialisierung
```bash
terraform init
```
### Änderungen anzeigen
```bash
terraform plan
```
### Infrastruktur erstellen/aktualisieren
```bash
terraform apply
```
### Infrastruktur löschen
```bash
terraform destroy
```
### Cluster-Zugriff einrichten
```bash
az aks get-credentials --resource-group trusted_ai_demo_rg --name trai_k8s_cluster --overwrite-existing
kubectl get nodes
```
## Konfiguration
### Wichtige Variablen (terraform.tfvars)
```hcl
location = "germanywestcentral"
resource_group_name = "trusted_ai_demo_rg"
aks_cluster_name = "trai_k8s_cluster"
aks_node_vm_size = "Standard_D2as_v6"
aks_node_zones = ["1", "2"]
alert_email_address = "your-email@example.com"
```
### Anpassbare Parameter
| Variable | Beschreibung | Default |
|----------|--------------|---------|
| `aks_node_pool_min_count` | Minimale Anzahl Nodes | 2 |
| `aks_node_pool_max_count` | Maximale Anzahl Nodes | 3 |
| `aks_node_vm_size` | VM-Größe für Nodes | Standard_D2as_v6 |
| `aks_node_zones` | Availability Zones | ["1", "2"] |
## Outputs
Nach dem Apply werden folgende Informationen ausgegeben:
```bash
terraform output
```
- `aks_cluster_fqdn` - Cluster FQDN
- `aks_cluster_id` - Cluster Resource ID
- `aks_oidc_issuer_url` - OIDC Issuer URL
- `log_analytics_workspace_id` - Log Analytics Workspace ID
- Weitere...
## Kostenübersicht
**Monatliche Kosten (geschätzt)**:
- 2x Standard_D2as_v6 Nodes: ~€70/Monat
- Log Analytics Workspace: ~€2-5/Monat (bei geringer Nutzung)
- **Gesamt**: ~€75-80/Monat
**Kostenoptimierung**:
- Ursprünglich Standard_D4d_v4: ~€140/Monat
- **Ersparnis**: ~€60-65/Monat (ca. 50%)
## Import-Historie
Das Projekt wurde mit `aztfexport` erstellt:
```bash
aztfexport resource-group trusted_ai_demo_rg --non-interactive --plain-ui --continue
```
**Importierte Ressourcen**: 9
- Resource Group
- Virtual Network + Subnet
- AKS Cluster
- Monitor Action Group
- 2x Metric Alerts
- Data Collection Rule (nachträglich hinzugefügt)
- Log Analytics Workspace (nachträglich hinzugefügt)
**Übersprungene Ressourcen**: 2
- Maintenance Configurations (automatisch verwaltet)
## Optimierungen
1. **VM-Größe**: Wechsel von Standard_D4d_v4 zu Standard_D2as_v6
- 50% Kostenreduktion
- Moderne AMD EPYC v6 Prozessoren
- Ausreichend für die meisten Workloads
2. **Availability Zones**: Reduziert auf Zonen 1 und 2
- Zone 3 war für das Abonnement nicht verfügbar
3. **Monitoring**: Komplett neu aufgesetzt
- Eigener Log Analytics Workspace (statt shared)
- Container Insights mit modernem V2 Format
- Strukturierte Alerting-Regeln
4. **Variabilisierung**: Alle Werte in variables.tf ausgelagert
- Einfache Anpassung
- Wiederverwendbar
## Nützliche Befehle
Siehe [cluster-status-commands.md](./cluster-status-commands.md) für eine vollständige Liste nützlicher Azure CLI und kubectl Befehle.
## Sicherheitshinweise
- `terraform.tfvars` enthält sensitive Werte (Email-Adresse) und sollte nicht in Version Control eingecheckt werden
- `.gitignore` ist konfiguriert, um State-Dateien und sensitive Daten auszuschließen
- Verwenden Sie Azure Key Vault oder ähnliche Lösungen für Production-Secrets
## Troubleshooting
### Quota-Fehler bei Node Pool Rotation
Wenn Sie VM-Größen ändern und einen Quota-Fehler erhalten:
```bash
terraform destroy
terraform apply
```
### Log Analytics Workspace existiert nicht
Falls der Workspace gelöscht wurde, erstellt Terraform automatisch einen neuen.
## Weiterführende Schritte
- [ ] State zu Azure Blob Storage migrieren (Remote State)
- [ ] Azure Key Vault Integration für Secrets
- [ ] CI/CD Pipeline einrichten
- [ ] Weitere Monitoring Dashboards erstellen
- [ ] Backup-Strategie implementieren
## Kontakt
Für Fragen oder Probleme, siehe die GitHub Issues.
## Lizenz
Projekt für Demo-Zwecke.
@@ -0,0 +1,36 @@
# AKS Cluster Status Befehle
Hier sind die Bash-Befehle, mit denen ich den Cluster-Status geprüft habe:
```bash
# 1. Cluster-Status prüfen
az aks show --resource-group trusted_ai_demo_rg --name trai_k8s_cluster --query "{name:name, powerState:powerState.code, provisioningState:provisioningState, kubernetesVersion:kubernetesVersion, nodeResourceGroup:nodeResourceGroup}" -o table
# 2. Node Pool Status prüfen
az aks nodepool list --resource-group trusted_ai_demo_rg --cluster-name trai_k8s_cluster --query "[].{name:name, count:count, vmSize:vmSize, provisioningState:provisioningState, powerState:powerState.code}" -o table
# 3. Kubeconfig herunterladen (für kubectl Zugriff)
az aks get-credentials --resource-group trusted_ai_demo_rg --name trai_k8s_cluster --overwrite-existing
# 4. Kubernetes Nodes anzeigen
kubectl get nodes
# 5. Alle Pods in allen Namespaces anzeigen
kubectl get pods -A
```
## Zusätzliche nützliche Befehle
```bash
# Detaillierte Cluster-Informationen
az aks show --resource-group trusted_ai_demo_rg --name trai_k8s_cluster -o json
# Cluster-Ressourcen anzeigen
kubectl top nodes
# Spezifische Namespace-Pods anzeigen
kubectl get pods -n kube-system
# Cluster-Events anzeigen
kubectl get events -A --sort-by='.lastTimestamp'
```
@@ -0,0 +1,195 @@
resource "azurerm_resource_group" "main" {
location = var.location
name = var.resource_group_name
}
resource "azurerm_virtual_network" "main" {
address_space = var.vnet_address_space
location = var.location
name = var.vnet_name
resource_group_name = var.resource_group_name
depends_on = [
azurerm_resource_group.main
]
}
resource "azurerm_subnet" "default" {
address_prefixes = var.subnet_address_prefixes
name = var.subnet_name
resource_group_name = var.resource_group_name
virtual_network_name = var.vnet_name
depends_on = [
azurerm_virtual_network.main
]
}
resource "azurerm_log_analytics_workspace" "main" {
name = "aksloganalytics${replace(var.aks_cluster_name, "_", "")}"
location = var.location
resource_group_name = var.resource_group_name
sku = "PerGB2018"
retention_in_days = 30
depends_on = [
azurerm_resource_group.main
]
}
resource "azurerm_kubernetes_cluster" "main" {
automatic_upgrade_channel = "patch"
dns_prefix = var.aks_dns_prefix
image_cleaner_enabled = true
image_cleaner_interval_hours = 168
location = var.location
name = var.aks_cluster_name
oidc_issuer_enabled = true
resource_group_name = var.resource_group_name
workload_identity_enabled = true
default_node_pool {
auto_scaling_enabled = true
max_count = var.aks_node_pool_max_count
min_count = var.aks_node_pool_min_count
name = "agentpool"
vm_size = var.aks_node_vm_size
zones = var.aks_node_zones
temporary_name_for_rotation = "temppool"
upgrade_settings {
max_surge = "10%"
}
}
identity {
type = "SystemAssigned"
}
maintenance_window_auto_upgrade {
day_of_week = "Sunday"
duration = 8
frequency = "Weekly"
interval = 1
start_time = "00:00"
utc_offset = "+00:00"
}
maintenance_window_node_os {
day_of_week = "Sunday"
duration = 8
frequency = "Weekly"
interval = 1
start_time = "00:00"
utc_offset = "+00:00"
}
oms_agent {
log_analytics_workspace_id = azurerm_log_analytics_workspace.main.id
msi_auth_for_monitoring_enabled = true
}
depends_on = [
azurerm_resource_group.main,
azurerm_log_analytics_workspace.main
]
}
resource "azurerm_monitor_data_collection_rule" "aks_monitoring" {
kind = "Linux"
location = var.location
name = "MSCI-${var.location}-${var.aks_cluster_name}"
resource_group_name = var.resource_group_name
data_flow {
destinations = ["ciworkspace"]
streams = ["Microsoft-ContainerLog", "Microsoft-ContainerLogV2", "Microsoft-KubeEvents", "Microsoft-KubePodInventory"]
}
data_sources {
extension {
extension_json = jsonencode({
dataCollectionSettings = {
enableContainerLogV2 = true
interval = "1m"
namespaceFilteringMode = "Off"
}
})
extension_name = "ContainerInsights"
name = "ContainerInsightsExtension"
streams = ["Microsoft-ContainerLog", "Microsoft-ContainerLogV2", "Microsoft-KubeEvents", "Microsoft-KubePodInventory"]
}
}
destinations {
log_analytics {
name = "ciworkspace"
workspace_resource_id = azurerm_log_analytics_workspace.main.id
}
}
depends_on = [
azurerm_resource_group.main,
azurerm_log_analytics_workspace.main
]
}
resource "azurerm_monitor_action_group" "alerts" {
name = "RecommendedAlertRules-AG-c92012"
resource_group_name = var.resource_group_name
short_name = "alertc92012"
email_receiver {
email_address = var.alert_email_address
name = "Email_-EmailAction-"
use_common_alert_schema = true
}
depends_on = [
azurerm_resource_group.main
]
}
resource "azurerm_monitor_metric_alert" "cpu_alert" {
auto_mitigate = false
frequency = "PT5M"
name = "CPU Usage Percentage - ${var.aks_cluster_name}"
resource_group_name = var.resource_group_name
scopes = [azurerm_kubernetes_cluster.main.id]
action {
action_group_id = azurerm_monitor_action_group.alerts.id
}
criteria {
aggregation = "Average"
metric_name = "node_cpu_usage_percentage"
metric_namespace = "Microsoft.ContainerService/managedClusters"
operator = "GreaterThan"
threshold = 95
}
depends_on = [
azurerm_resource_group.main
]
}
resource "azurerm_monitor_metric_alert" "memory_alert" {
auto_mitigate = false
frequency = "PT5M"
name = "Memory Working Set Percentage - ${var.aks_cluster_name}"
resource_group_name = var.resource_group_name
scopes = [azurerm_kubernetes_cluster.main.id]
action {
action_group_id = azurerm_monitor_action_group.alerts.id
}
criteria {
aggregation = "Average"
metric_name = "node_memory_working_set_percentage"
metric_namespace = "Microsoft.ContainerService/managedClusters"
operator = "GreaterThan"
threshold = 100
}
depends_on = [
azurerm_resource_group.main
]
}
@@ -0,0 +1,50 @@
output "resource_group_name" {
description = "Name of the resource group"
value = azurerm_resource_group.main.name
}
output "aks_cluster_name" {
description = "Name of the AKS cluster"
value = azurerm_kubernetes_cluster.main.name
}
output "aks_cluster_id" {
description = "ID of the AKS cluster"
value = azurerm_kubernetes_cluster.main.id
}
output "aks_cluster_fqdn" {
description = "FQDN of the AKS cluster"
value = azurerm_kubernetes_cluster.main.fqdn
}
output "aks_kube_config" {
description = "Kubeconfig for the AKS cluster"
value = azurerm_kubernetes_cluster.main.kube_config_raw
sensitive = true
}
output "aks_oidc_issuer_url" {
description = "OIDC issuer URL of the AKS cluster"
value = azurerm_kubernetes_cluster.main.oidc_issuer_url
}
output "vnet_id" {
description = "ID of the virtual network"
value = azurerm_virtual_network.main.id
}
output "subnet_id" {
description = "ID of the subnet"
value = azurerm_subnet.default.id
}
output "log_analytics_workspace_id" {
description = "ID of the Log Analytics workspace"
value = azurerm_log_analytics_workspace.main.id
}
output "log_analytics_workspace_name" {
description = "Name of the Log Analytics workspace"
value = azurerm_log_analytics_workspace.main.name
}
@@ -0,0 +1,10 @@
provider "azurerm" {
features {
}
subscription_id = var.subscription_id
environment = "public"
use_msi = false
use_cli = true
use_oidc = false
resource_provider_registrations = "none"
}
@@ -0,0 +1,11 @@
terraform {
backend "local" {}
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "4.33.0"
}
}
}
@@ -0,0 +1,28 @@
# Azure Region
location = "germanywestcentral"
# Resource Group
resource_group_name = "trusted_ai_demo_rg"
# Virtual Network
vnet_name = "trusted_ai_demo_vn"
subnet_name = "default"
# AKS Cluster Configuration
aks_cluster_name = "trai_k8s_cluster"
aks_dns_prefix = "traik8scluster"
# AKS Node Pool Configuration
aks_node_vm_size = "Standard_D2as_v6"
aks_node_zones = ["1", "2"]
# Auto-Scaling Configuration
aks_node_pool_min_count = 2
aks_node_pool_max_count = 3
# Alert Configuration
# WICHTIG: Ersetzen Sie diese Email-Adresse mit Ihrer eigenen
alert_email_address = "your-email@example.com"
# Azure Subscription ID (optional, falls abweichend vom Default)
# subscription_id = "your-subscription-id"
@@ -0,0 +1,83 @@
variable "location" {
description = "Azure region for resources"
type = string
default = "germanywestcentral"
}
variable "resource_group_name" {
description = "Name of the resource group"
type = string
default = "trusted_ai_demo_rg"
}
variable "vnet_name" {
description = "Name of the virtual network"
type = string
default = "trusted_ai_demo_vn"
}
variable "vnet_address_space" {
description = "Address space for the virtual network"
type = list(string)
default = ["10.0.0.0/16"]
}
variable "subnet_name" {
description = "Name of the subnet"
type = string
default = "default"
}
variable "subnet_address_prefixes" {
description = "Address prefixes for the subnet"
type = list(string)
default = ["10.0.0.0/24"]
}
variable "aks_cluster_name" {
description = "Name of the AKS cluster"
type = string
default = "trai_k8s_cluster"
}
variable "aks_dns_prefix" {
description = "DNS prefix for the AKS cluster"
type = string
default = "traik8scluster"
}
variable "aks_node_pool_min_count" {
description = "Minimum number of nodes in the AKS node pool"
type = number
default = 2
}
variable "aks_node_pool_max_count" {
description = "Maximum number of nodes in the AKS node pool"
type = number
default = 3
}
variable "aks_node_vm_size" {
description = "VM size for AKS node pool"
type = string
default = "Standard_D2as_v6"
}
variable "aks_node_zones" {
description = "Availability zones for AKS nodes"
type = list(string)
default = ["1", "2"]
}
variable "alert_email_address" {
description = "Email address for alert notifications"
type = string
sensitive = true
}
variable "subscription_id" {
description = "Azure subscription ID"
type = string
default = "77677a80-2dea-493d-9867-f1c961b80fb3"
}
+128
View File
@@ -0,0 +1,128 @@
# Trusted AI Demo - OpenTofu Infrastructure
This project contains OpenTofu/Terraform configuration for the Trusted AI Demo infrastructure on Azure.
## Infrastructure Components
This configuration creates:
- **Resource Group**: Container for all Azure resources
- **Virtual Network**: 10.0.0.0/16 address space
- **Subnet**: 10.0.1.0/24 for VM placement
- **Network Security Group**: With RDP (port 3389) rule for remote access
- **Public IP**: Static public IP for VM access
- **Network Interface**: Connects VM to the virtual network
- **Windows Server 2022 VM**: Standard_B2s (2 vCPUs, 4 GB RAM)
## Prerequisites
- [OpenTofu](https://opentofu.org/) >= 1.0 or [Terraform](https://www.terraform.io/) >= 1.0
- Azure CLI configured with appropriate credentials
- Azure subscription with necessary permissions
## Getting Started
### 1. Authenticate with Azure
```bash
az login
az account set --subscription "<your-subscription-id>"
```
### 2. Initialize OpenTofu
```bash
tofu init
```
Or if using Terraform:
```bash
terraform init
```
### 3. Review the Plan
```bash
tofu plan
```
### 4. Apply the Configuration
```bash
tofu apply
```
## Project Structure
- `main.tf` - Main infrastructure configuration
- `variables.tf` - Input variable definitions
- `outputs.tf` - Output value definitions
- `terraform.tfvars.example` - Example variable values (copy to `terraform.tfvars`)
## Configuration
### Required Configuration
1. Copy the example variables file:
```bash
cp terraform.tfvars.example terraform.tfvars
```
2. Edit `terraform.tfvars` and set your admin password:
```hcl
admin_password = "YourSecurePassword123!"
```
**Important**: The password must be at least 12 characters long and contain uppercase, lowercase, and numbers.
3. **Security Recommendation**: Change `allowed_rdp_source` to your public IP address instead of `"*"`:
```hcl
allowed_rdp_source = "YOUR_PUBLIC_IP/32"
```
You can find your public IP with:
```bash
curl ifconfig.me
```
### Optional Customization
You can also customize:
- `resource_group_name`: Name of the resource group
- `location`: Azure region (default: westeurope)
- `vm_name`: Name of the virtual machine
- `vm_size`: VM size (default: Standard_B2s)
- `vnet_address_space`: Virtual network address space
- `subnet_address_prefix`: Subnet address prefix
## Connecting to the VM
After the infrastructure is created, you can connect to the Windows VM via RDP:
1. Get the public IP address:
```bash
tofu output vm_public_ip
```
2. Connect using Remote Desktop:
- **Windows**: Use the connection string from output:
```bash
tofu output rdp_connection_string
```
- **macOS**: Use Microsoft Remote Desktop app
- **Linux**: Use Remmina or similar RDP client
3. Login credentials:
- Username: The value you set for `admin_username` (default: azureadmin)
- Password: The password you set in `terraform.tfvars`
## Cleanup
To destroy all resources:
```bash
tofu destroy
```
**Warning**: This will permanently delete all resources created by this configuration.
+123
View File
@@ -0,0 +1,123 @@
terraform {
required_version = ">= 1.0"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
}
}
provider "azurerm" {
features {}
}
# Resource Group
resource "azurerm_resource_group" "main" {
name = var.resource_group_name
location = var.location
tags = var.tags
}
# Virtual Network
resource "azurerm_virtual_network" "main" {
name = "${var.resource_group_name}-vnet"
address_space = [var.vnet_address_space]
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
tags = var.tags
}
# Subnet
resource "azurerm_subnet" "main" {
name = "default"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = [var.subnet_address_prefix]
}
# Network Security Group
resource "azurerm_network_security_group" "main" {
name = "${var.vm_name}-nsg"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
security_rule {
name = "SSH"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = var.allowed_ssh_source
destination_address_prefix = "*"
}
tags = var.tags
}
# Public IP
resource "azurerm_public_ip" "main" {
name = "${var.vm_name}-pip"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
allocation_method = "Static"
sku = "Standard"
tags = var.tags
}
# Network Interface
resource "azurerm_network_interface" "main" {
name = "${var.vm_name}-nic"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.main.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.main.id
}
tags = var.tags
}
# Associate NSG with Network Interface
resource "azurerm_network_interface_security_group_association" "main" {
network_interface_id = azurerm_network_interface.main.id
network_security_group_id = azurerm_network_security_group.main.id
}
# Linux Virtual Machine
resource "azurerm_linux_virtual_machine" "main" {
name = var.vm_name
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
size = var.vm_size
admin_username = var.admin_username
admin_password = var.admin_password
disable_password_authentication = false
network_interface_ids = [
azurerm_network_interface.main.id,
]
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "0001-com-ubuntu-server-jammy"
sku = "22_04-lts-gen2"
version = "latest"
}
tags = var.tags
}
+56
View File
@@ -0,0 +1,56 @@
output "resource_group_name" {
description = "Name of the created resource group"
value = azurerm_resource_group.main.name
}
output "resource_group_id" {
description = "ID of the created resource group"
value = azurerm_resource_group.main.id
}
output "location" {
description = "Location of the resource group"
value = azurerm_resource_group.main.location
}
# Network Outputs
output "vnet_name" {
description = "Name of the virtual network"
value = azurerm_virtual_network.main.name
}
output "vnet_id" {
description = "ID of the virtual network"
value = azurerm_virtual_network.main.id
}
output "subnet_id" {
description = "ID of the subnet"
value = azurerm_subnet.main.id
}
# VM Outputs
output "vm_name" {
description = "Name of the virtual machine"
value = azurerm_linux_virtual_machine.main.name
}
output "vm_id" {
description = "ID of the virtual machine"
value = azurerm_linux_virtual_machine.main.id
}
output "vm_private_ip" {
description = "Private IP address of the VM"
value = azurerm_network_interface.main.private_ip_address
}
output "vm_public_ip" {
description = "Public IP address of the VM"
value = azurerm_public_ip.main.ip_address
}
output "ssh_connection_string" {
description = "SSH connection string for the VM"
value = "ssh ${azurerm_linux_virtual_machine.main.admin_username}@${azurerm_public_ip.main.ip_address}"
}
@@ -0,0 +1 @@
{"version":4,"terraform_version":"1.11.1","serial":11,"lineage":"cad35d7f-13a9-933b-a7ef-af99f16a5d08","outputs":{},"resources":[],"check_results":null}
@@ -0,0 +1 @@
{"version":4,"terraform_version":"1.11.1","serial":7,"lineage":"cad35d7f-13a9-933b-a7ef-af99f16a5d08","outputs":{"location":{"value":"austriaeast","type":"string"},"resource_group_id":{"value":"/subscriptions/77677a80-2dea-493d-9867-f1c961b80fb3/resourceGroups/rg-trusted-ai-demo","type":"string"},"resource_group_name":{"value":"rg-trusted-ai-demo","type":"string"},"ssh_connection_string":{"value":"ssh azureadmin@68.210.97.125","type":"string"},"subnet_id":{"value":"/subscriptions/77677a80-2dea-493d-9867-f1c961b80fb3/resourceGroups/rg-trusted-ai-demo/providers/Microsoft.Network/virtualNetworks/rg-trusted-ai-demo-vnet/subnets/default","type":"string"},"vm_id":{"value":"/subscriptions/77677a80-2dea-493d-9867-f1c961b80fb3/resourceGroups/rg-trusted-ai-demo/providers/Microsoft.Compute/virtualMachines/vm-trusted-ai","type":"string"},"vm_name":{"value":"vm-trusted-ai","type":"string"},"vm_private_ip":{"value":"10.0.1.4","type":"string"},"vm_public_ip":{"value":"68.210.97.125","type":"string"},"vnet_id":{"value":"/subscriptions/77677a80-2dea-493d-9867-f1c961b80fb3/resourceGroups/rg-trusted-ai-demo/providers/Microsoft.Network/virtualNetworks/rg-trusted-ai-demo-vnet","type":"string"},"vnet_name":{"value":"rg-trusted-ai-demo-vnet","type":"string"}},"resources":[{"mode":"managed","type":"azurerm_linux_virtual_machine","name":"main","provider":"provider[\"registry.opentofu.org/hashicorp/azurerm\"]","instances":[{"schema_version":0,"attributes":{"additional_capabilities":[],"admin_password":"Hab2009Keins!","admin_ssh_key":[],"admin_username":"azureadmin","allow_extension_operations":true,"availability_set_id":"","boot_diagnostics":[],"bypass_platform_safety_checks_on_user_schedule_enabled":false,"capacity_reservation_group_id":"","computer_name":"vm-trusted-ai","custom_data":null,"dedicated_host_group_id":"","dedicated_host_id":"","disable_password_authentication":false,"disk_controller_type":"SCSI","edge_zone":"","encryption_at_host_enabled":false,"eviction_policy":"","extensions_time_budget":"PT1H30M","gallery_application":[],"id":"/subscriptions/77677a80-2dea-493d-9867-f1c961b80fb3/resourceGroups/rg-trusted-ai-demo/providers/Microsoft.Compute/virtualMachines/vm-trusted-ai","identity":[],"license_type":"","location":"austriaeast","max_bid_price":-1,"name":"vm-trusted-ai","network_interface_ids":["/subscriptions/77677a80-2dea-493d-9867-f1c961b80fb3/resourceGroups/rg-trusted-ai-demo/providers/Microsoft.Network/networkInterfaces/vm-trusted-ai-nic"],"os_disk":[{"caching":"ReadWrite","diff_disk_settings":[],"disk_encryption_set_id":"","disk_size_gb":30,"name":"vm-trusted-ai_OsDisk_1_26ed4d6fa684410abb7d858ef85be362","secure_vm_disk_encryption_set_id":"","security_encryption_type":"","storage_account_type":"Standard_LRS","write_accelerator_enabled":false}],"os_image_notification":[],"patch_assessment_mode":"ImageDefault","patch_mode":"ImageDefault","plan":[],"platform_fault_domain":-1,"priority":"Regular","private_ip_address":"10.0.1.4","private_ip_addresses":["10.0.1.4"],"provision_vm_agent":true,"proximity_placement_group_id":"","public_ip_address":"68.210.97.125","public_ip_addresses":["68.210.97.125"],"reboot_setting":"","resource_group_name":"rg-trusted-ai-demo","secret":[],"secure_boot_enabled":false,"size":"Standard_B2ats_v2","source_image_id":"","source_image_reference":[{"offer":"0001-com-ubuntu-server-jammy","publisher":"Canonical","sku":"22_04-lts-gen2","version":"latest"}],"tags":{"Environment":"dev","ManagedBy":"OpenTofu","Project":"trusted-ai-demo"},"termination_notification":null,"timeouts":null,"user_data":"","virtual_machine_id":"c0bc058a-065f-44e0-9bf7-e9343e91e666","virtual_machine_scale_set_id":"","vm_agent_platform_updates_enabled":false,"vtpm_enabled":false,"zone":""},"sensitive_attributes":[[{"type":"get_attr","value":"admin_password"}],[{"type":"get_attr","value":"custom_data"}]],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoyNzAwMDAwMDAwMDAwLCJkZWxldGUiOjI3MDAwMDAwMDAwMDAsInJlYWQiOjMwMDAwMDAwMDAwMCwidXBkYXRlIjoyNzAwMDAwMDAwMDAwfX0=","dependencies":["azurerm_network_interface.main","azurerm_public_ip.main","azurerm_resource_group.main","azurerm_subnet.main","azurerm_virtual_network.main"]}]},{"mode":"managed","type":"azurerm_network_interface","name":"main","provider":"provider[\"registry.opentofu.org/hashicorp/azurerm\"]","instances":[{"schema_version":0,"attributes":{"accelerated_networking_enabled":false,"applied_dns_servers":[],"auxiliary_mode":"","auxiliary_sku":"","dns_servers":[],"edge_zone":"","enable_accelerated_networking":false,"enable_ip_forwarding":false,"id":"/subscriptions/77677a80-2dea-493d-9867-f1c961b80fb3/resourceGroups/rg-trusted-ai-demo/providers/Microsoft.Network/networkInterfaces/vm-trusted-ai-nic","internal_dns_name_label":"","internal_domain_name_suffix":"cu22vk1awgdetoispofbty41oa.viex.internal.cloudapp.net","ip_configuration":[{"gateway_load_balancer_frontend_ip_configuration_id":"","name":"internal","primary":true,"private_ip_address":"10.0.1Line truncated
@@ -0,0 +1,23 @@
# Copy this file to terraform.tfvars and customize as needed
# Resource Group Configuration
resource_group_name = "rg-trusted-ai-demo"
location = "austriaeast"
# Network Configuration
vnet_address_space = "10.0.0.0/16"
subnet_address_prefix = "10.0.1.0/24"
allowed_ssh_source = "*" # Change to your public IP for better security, e.g., "1.2.3.4/32"
# Virtual Machine Configuration
vm_name = "vm-trusted-ai"
vm_size = "Standard_B2ats_v2"
admin_username = "azureadmin"
admin_password = "Hab2009Keins!"
# Tags
tags = {
Environment = "dev"
Project = "trusted-ai-demo"
ManagedBy = "OpenTofu"
}
@@ -0,0 +1,23 @@
# Copy this file to terraform.tfvars and customize as needed
# Resource Group Configuration
resource_group_name = "rg-trusted-ai-demo"
location = "westus"
# Network Configuration
vnet_address_space = "10.0.0.0/16"
subnet_address_prefix = "10.0.1.0/24"
allowed_rdp_source = "*" # Change to your public IP for better security, e.g., "1.2.3.4/32"
# Virtual Machine Configuration
vm_name = "vm-trusted-ai"
vm_size = "Standard_B2s"
admin_username = "azureadmin"
admin_password = "YourSecurePassword123!" # IMPORTANT: Change this! Min 12 characters, must include upper, lower, number
# Tags
tags = {
Environment = "dev"
Project = "trusted-ai-demo"
ManagedBy = "OpenTofu"
}
@@ -0,0 +1,65 @@
variable "resource_group_name" {
description = "Name of the resource group"
type = string
default = "rg-trusted-ai-demo"
}
variable "location" {
description = "Azure region for resources"
type = string
default = "austriaeast"
}
variable "tags" {
description = "Tags to apply to all resources"
type = map(string)
default = {
Environment = "dev"
Project = "trusted-ai-demo"
ManagedBy = "OpenTofu"
}
}
# Network Configuration
variable "vnet_address_space" {
description = "Address space for the virtual network"
type = string
default = "10.0.0.0/16"
}
variable "subnet_address_prefix" {
description = "Address prefix for the subnet"
type = string
default = "10.0.1.0/24"
}
variable "allowed_ssh_source" {
description = "Source IP address or range allowed to SSH to the VM (use your public IP or '*' for any - not recommended)"
type = string
default = "*"
}
# Virtual Machine Configuration
variable "vm_name" {
description = "Name of the virtual machine"
type = string
default = "vm-trusted-ai"
}
variable "vm_size" {
description = "Size of the virtual machine"
type = string
default = "Standard_B2s"
}
variable "admin_username" {
description = "Admin username for the virtual machine"
type = string
default = "azureadmin"
}
variable "admin_password" {
description = "Admin password for the virtual machine (use strong password, min 12 characters)"
type = string
sensitive = true
}
@@ -0,0 +1,36 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/28.0.6 Chrome/138.0.7204.100 Electron/37.2.3 Safari/537.36" version="28.0.6">
<diagram name="Seite-1" id="13kzIe54gCjrgZH2jZoa">
<mxGraphModel dx="3433" dy="2120" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1654" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" value="Beschriftung Blatt" style="" parent="0" />
<mxCell id="mBbMmTsdGeR7BbYYs1AZ-6" value="&quot;Landkarte&quot; Sopra Steria Trusted AI Platform auf Azure zur Übersicht und Abstimmung" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=20;fontFamily=Tahoma;" vertex="1" parent="1">
<mxGeometry x="140" y="120" width="790" height="30" as="geometry" />
</mxCell>
<mxCell id="mBbMmTsdGeR7BbYYs1AZ-7" value="" style="shape=image;verticalLabelPosition=bottom;labelBackgroundColor=default;verticalAlign=top;aspect=fixed;imageAspect=0;editableCssRules=.*;image=data:image/svg+xml,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjIuMDA2Mjg5OTU4OTUzODU3NCAyLjAxODg0MDA3NDUzOTE4NDYgNTI1Ljk4NzczMTkzMzU5MzggNjYuOTYyMzY0MTk2Nzc3MzQiIGhlaWdodD0iNjYuOTYyMzY0MTk2Nzc3MzQiIHdpZHRoPSI1MjUuOTg3NzMxOTMzNTkzOCI+JiN4YTs8cGF0aCBmaWxsPSIjRjY3MjAwIiBkPSJNMjM4LjM0OSAxMS43NzYxQzIzMy4xNzYgMTEuNjkwNCAyMjkuMTI2IDEzLjEwMDQgMjI4LjAwOSAxNi43NjU0QzIyNS42OTkgMjQuMzM4NSAyNDAuNjQ1IDMyLjQ2NTMgMjQ3LjY5IDM2LjMzODlDMjQ5LjIwNCAzNy4xNjY4IDI0OS44NTIgMzYuNjUwMiAyNDguODk0IDM1LjU0MThDMjQ0LjQ0MiAzMC40MTE0IDIzOC4xMSAyMC4zMDgzIDI0Ny4wNDYgMTQuMzc5QzI0Ny40ODEgMTQuMDkyIDI0OC4wMTEgMTMuNzY1NyAyNDguNDg2IDEzLjQ4ODRMMjQ4LjYyOSAxMy40MDk4TDI0OC40ODYgMTMuMzg0NkMyNDQuOTYzIDEyLjQxNzUgMjQxLjQ1MiAxMS44MjcgMjM4LjM0OSAxMS43NzU2VjExLjc3NjFaTTI4Ni40MTMgMzQuMjEzMkMyODUuNjM4IDM0LjA2MTEgMjg1LjQ0OCAzNC41NTc5IDI4Ni4xNzIgMzUuMzg5MkMyOTAuNjE3IDQwLjUxODkgMjk2Ljk2IDUwLjYxOTUgMjg4LjAxNSA1Ni41NTJWNTYuNTQ3QzI4Ny41ODggNTYuODM0IDI4Ny4wNjggNTcuMTYxOSAyODYuNTg1IDU3LjQ0MjVMMjg2LjQzOCA1Ny41MjYxTDI4Ni41ODUgNTcuNTQ2M0MyOTUuOTczIDYwLjEyNTIgMzA1LjI2NSA2MC4wMjgzIDMwNy4wNTIgNTQuMTYxQzMwOS4zNjMgNDYuNTg3OSAyOTQuNDI0IDM4LjQ2MjggMjg3LjM3MSAzNC41OTI0QzI4Ni45OTUgMzQuMzg1NCAyODYuNjcyIDM0LjI2NDMgMjg2LjQxMyAzNC4yMTM2TDI4Ni40MTMgMzQuMjEzMloiLz4mI3hhOzxwYXRoIGZpbGw9IiMyMzFGMjAiIGQ9Ik00NzQuNzg5IDIuMDE4ODRDNDcxLjk0NyAyLjAxODg0IDQ2OS42NDQgNC4zMjU1IDQ2OS42NDQgNy4xNjU2MkM0NjkuNjQ0IDEwLjAwNjUgNDcxLjk0NyAxMi4zMTI0IDQ3NC43ODkgMTIuMzEyNEM0NzcuNjIzIDEyLjMxMjQgNDc5LjkxOSAxMC4wMDY1IDQ3OS45MTkgNy4xNjU2MkM0NzkuOTE5IDQuMzI1NSA0NzcuNjIzIDIuMDE4ODQgNDc0Ljc4OSAyLjAxODg0Wk0zNjguOTY1IDYuODY1NDdWMTYuNzA2M0gzNjEuMDU4VjIzLjMzOTFIMzY4Ljk2NVY0NC4yMTY1QzM2OC45NjUgNDguOTk3IDM2OS45MDUgNTcuNzEzMyAzODEuOTgyIDU3LjcxMzNDMzg1LjAwOSA1Ny43MTMzIDM4Ni45NDkgNTcuNTA0NCAzODkuNjEzIDU3LjE0MjVWNTAuMjI5M0MzODkuNjEzIDUwLjIyOTMgMzg2Ljg2MiA1MC45MzI5IDM4NC40MTQgNTAuOTMyOUMzNzguMDMgNTAuOTMyOSAzNzYuNjM1IDQ4LjMxMSAzNzYuNjM1IDQzLjMxNjFWMjMuMzM5MUgzODkuMjZWMTYuNzA2M0gzNzYuNjM1VjYuODY1NDdIMzY4Ljk2NVpNNDEzLjMzNCAxNS44NzQ4QzQwMC42NDUgMTUuODc0OCAzOTEuMTQ3IDI0LjEzNzcgMzkxLjE0NyAzNy4wMDgxVjM3LjMzMjhDMzkxLjE0NyA0OS44ODU2IDQwMC42OTYgNTcuOTg4OCA0MTQuNTUzIDU3Ljk4ODhDNDIxLjIxMSA1Ny45ODg4IDQyNy40MzQgNTYuMzIyMSA0MzMuMTQyIDUwLjgzOTRMNDI3LjUxMSA0NS44ODk1QzQyNy41MTEgNDUuODg5NSA0MjIuNjgzIDUwLjkzNzggNDE0LjU0MyA1MC45Mzc4QzQwNi45ODMgNTAuOTM3OCAzOTkuNjU1IDQ2LjE0MzEgMzk5LjMwOSAzOS43ODgxTDQzNC40MyAzOS42NDA1QzQzNC42MDYgMzguMDQ5OSA0MzQuNjA2IDM2LjI5OTUgNDM0LjYwNiAzNi4yOTk1QzQzNC42MDYgMjUuMDk4NyA0MjUuOTQxIDE1Ljg3NDggNDEzLjMzMyAxNS44NzQ4TDQxMy4zMzQgMTUuODc0OFpNNTA1Ljc3MiAxNi4xMjU3QzQ5Ny4xMDEgMTYuMTI1NyA0ODQuNjAzIDIxLjM3ODcgNDg0LjYwMyAzNi44NTA2QzQ4NC42MDMgNTIuMTc2NiA0OTUuODQ1IDU3LjkwNTEgNTA1LjY4NCA1Ny45MDUxQzUxNS40OSA1Ny45MDUxIDUyMC40MDYgNTIuNDQ4NCA1MjAuNDA2IDUyLjQ0ODRMNTIwLjgwNSA1Ny44OTUzSDUyNy45OTRWMTYuNjcxOUg1MjAuODE5TDUyMC40MDYgMjEuNzg0MkM1MjAuNDA2IDIxLjc4NDIgNTE1LjYzNSAxNi4xMjU3IDUwNS43NzIgMTYuMTI1N1pNMzM3LjMxMyAxNi4xNTUyQzMyOS4wMjggMTYuMTU1MiAzMjAuMTMzIDE5LjI5MzQgMzIwLjEzMyAyNy42OTg1QzMyMC4xMzMgMzQuOTc1OCAzMjYuNzQzIDM3LjIzOTUgMzM3LjY1MiAzOS4yOTZDMzQ0LjkzOSA0MC42NjU3IDM1MS42NjIgNDEuMzYyNCAzNTEuNjYyIDQ1LjI5ODlDMzUxLjY2MiA0Ny43ODAzIDM0OC4zNTMgNTAuOTYyMyAzNDAuMDg1IDUwLjk2MjNDMzM0LjIxNSA1MC45NjIzIDMyOC4yODkgNDkuNzI4IDMyNi40NzggNDUuNTRMMzE5LjQxMSA0OC41MTJDMzIyLjMxIDU0Ljk3NjYgMzI5Ljk5NyA1OC4zMjMzIDMzOC45MSA1OC4zMjMzQzM1Ni43MTEgNTguMzIzMyAzNjAuMTQ5IDQ5Ljg1MDEgMzYwLjE0OSA0NS4wMzgxQzM2MC4xNDkgMzcuMDI0MSAzNTIuMTg0IDM0LjcyMzQgMzQ0LjIzNyAzMy4zMDI5QzMzNi4zMzEgMzEuODg4OSAzMjguNTU2IDMwLjkwMiAzMjguNTU2IDI3LjIxMTRDMzI4LjU1NiAyNC44MDgyIDMzMC45NDggMjIuNjg0NiAzMzcuODY0IDIyLjY4NDZDMzQzLjAwOCAyMi42ODQ2IDM0OC45NDEgMjMuODgxNyAzNTAuNTUyIDI3LjUzMTJMMzU3LjgzOSAyNC40NjA5QzM1NS4wNTMgMTguODUyNCAzNDYuNzk3IDE2LjE1NTIgMzM3LjMxMyAxNi4xNTUyWk00NjIuMzE3IDE2LjYyNzVDNDU2LjAyMyAxNi41Njk2IDQ1MS4zOTMgMTguNDc3NCA0NDcuNjczIDIyLjM1OThMNDQ3LjI2MSAxNi42ODY2SDQzOS44MTZWNTcuODcwNkg0NDcuNjczVjM2LjUyNThDNDQ3LjY3MyAzMC41NzQ3IDQ1Mi40NjIgMjMuMDI5IDQ2NS4xMTggMjMuNzM3NlYxNi43NzAyQzQ2NC4xNDkgMTYuNjgxNiA0NjMuMjE2IDE2LjYzNiA0NjIuMzE3IDE2LjYyNzZWMTYuNjI3NVpNNDcwLjg1MyAxNi42NjIxVjU3LjgxMTdINDc4LjcxMVYxNi42NjIxSDQ3MC44NTNaTTUwNi4xMDIgMjMuMDA0NUM1MTMuNzE4IDIzLjAwNDUgNTIwLjQwNiAyNy4zMjk0IDUyMC40MDYgMzYuNzc2OEM1MjAuNDA2IDQ2LjIxNzggNTE0LjUyMSA1MC45Mzc4IDUwNi4xOCA1MC45Mzc4QzUwMS44MDggNTAuOTM3OCA0OTIuNTkzIDQ4LjE0NjUgNDkyLjU5MyAzNi45MzkyQzQ5Mi41OTMgMjUuNTUyMSA1MDEuNzg2IDIzLjAwNDUgNTA2LjEwMiAyMy4wMDQ1Wk00MTMuNDM3IDIzLjIyMDlDNDIwLjM0NSAyMy4yMjA5IDQyNS45NzMgMjcuODg0NCA0MjUuOTczIDMzLjQ4SDM5OS40MzdDMzk5LjkyOCAyNy43OTI1IDQwNi4wMzggMjMuMjIwOSA0MTMuNDM3IDIzLjIyMDlaIi8+JiN4YTs8cGF0aCBmaWxsPSIjMjMxRjIwIiBkPSJNNjguODMyOCAxNi4xMjA4QzU4LjMyNTkgMTYuMTIwOCA0NS44ODQxIDIxLjM4MDQgNDUuODg0MSAzNi44NTU1QzQ1Ljg4NDEgNTIuMTc4MyA1Ny4wNzggNTguMTMxNSA2OC44MzI4IDU4LjEzMTVDODAuNTk1NiA1OC4xMzE1IDkxLjc4NjQgNTIuMTc4MyA5MS43ODY0IDM2Ljg1NTVDOTEuNzg2NCAyMS4zODA0IDc5LjM0NzcgMTYuMTIwOCA2OC44MzI4IDE2LjEyMDhaTTELine truncated
<mxGeometry x="160" y="160" width="167.01" height="21.27" as="geometry" />
</mxCell>
<mxCell id="mBbMmTsdGeR7BbYYs1AZ-8" value="" style="shape=image;verticalLabelPosition=bottom;labelBackgroundColor=default;verticalAlign=top;aspect=fixed;imageAspect=0;editableCssRules=.*;image=data:image/svg+xml,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAuMTk3NTg5ODc0MjY3NTc4MTIgOS41MzY3NDMxNjQwNjI1ZS03IDQyNC44MDE2MDUyMjQ2MDk0IDU5LjUyNzU2NTAwMjQ0MTQwNiIgaWQ9ImEiIHdpZHRoPSI0MjQuODAxNjA1MjI0NjA5NCIgaGVpZ2h0PSI1OS41Mjc1NjUwMDI0NDE0MDYiPjxwYXRoIHN0cm9rZS13aWR0aD0iMCIgZmlsbD0iI2VmN2QwMCIgZD0ibTYwLjI5Mzk4NDYwNzg4NjE1OSw1MC43NjkyOTMwMTMxMzA2NjRjOC45MjIwODUyNDQwODU3OTMtNS45MDg5NDExMjUxMDQzMiwyLjU5NzUxMDExNTM2ODA5NS0xNS45NjgwMTUxMzE5NDI1OTMtMS44NDE4MzIwMDA0NDAyNjMtMjEuMDgwNTAyMjg5NzcwMjY2LS45NjIzMDUyMDc3MDQwNDgtMS4xMDQ3MDE3NDYxMTQxODgtLjMwNzA5NDY3MTA5NTAwMS0xLjYyMDQ4NDM4MzM4MTE1NCwxLjE5ODY2Nzc1OTU1NTk3NC0uNzk0NTE1NzY0OTAxOTE3LDcuMDMyODUzMTU1NDA5NjEyLDMuODU3MTIwODQ1NTM0MTU1LDIxLjkzMjIwNzI5MTU4MjkyNywxMS45NTEyMjU2NjYxNjkxOTQsMTkuNjI5NzQ1NTUxNTgzMjU1LDE5LjQ5NjE4MTMyNzc3Njg2Ny0xLjc3OTEyMjU2NjkxMTYxLDUuODQzODAyODA1MDcxMzkxLTExLjA1MzM0NzI4NjQ2NjMwNSw1Ljk0MDI5NTg0MTg2MTM3MS0yMC40MjAwMTY4OTg2MzkwMDUsMy4zNjg0OTc1NzU1ODU5MzRsLS4xNDU1MTIzODI3MDQ1MS0uMDE2ODc5NTM0NTI1Mjg3LjE0NTUxMjM4MjcwNDUxLS4wODQ0MjIyMDY4NjA4MzZjLjQ3NzU1ODM0MjUwMzQ3MS0uMjc0OTU0ODU5NzIyMTI5LDEuMDAwMTEyNDIwOTUyMDY0LS42MDIxNDMwNDY0OTcwNzYsMS40MzM0MzU1ODc5NDAwMzktLjg4ODM1OTEwNzMwNDQ5NWgwWiIvPjxwYXRoIHN0cm9rZS13aWR0aD0iMCIgZmlsbD0iI2NmMDIyYiIgZD0ibTU4LjcyMzg5MzQ4NjAyNzkxOSw1MS43MzgwNTA3MTczMjIwMzlzLTExLjc5Mjk1NTQ5NTcxNzI1MSw3LjQxMjI3NDY2OTI0ODI5MS0zMi42MDUyNzQzNjY5NjA2NTcsNy40MTIyNzQ2NjkyNDgyOTFjLTguMDYzNDg2MTMwMDgyMzEsMC0xNC44NTE5Mjk1MTM3MDIwODktMS4yMzQ4MDY2NDY3MDIwNTQtMTcuNzIyNzk5NzY1MzI4MDkxLTQuMDU5MDYxOTA0NzEyNTA3LTMuMDIzNTk1NjkxMjUxMTAzLTIuOTczNzY2NzE2NDk3MjY2LTQuNjYzNjMzODM3NzMwMjMxLTcuOTgzODk3MTYyMDQxMTAzLTQuNjYzNjMzODM3NzMwMjMxLTEyLjU5MDQ2NDQzMzg5NTI0OSwwLTMuOTQ3MzMzMTI1MjgxMTQ4LDEuNjQwMDM4MTQ2NDc5MTI4LTcuMjY1OTc3MTkxOTE3MDQ1LDUuMDU2NzY5OTczMzY4MzE4LTcuMjY1OTc3MTkxOTE3MDQ1LDguNzc2NTcyODYxMzg0OTIxLDAsMzYuMTEwNDI3NDc2NDc1NzA2LDEzLjkwMzI4OTg1OTM4ODY3OCw0OS45MzQ5Mzc5OTY2NTA2NiwxNi41MDMyMjg4NjEyNzY1MTFoMFoiLz48cGF0aCBzdHJva2Utd2lkdGg9IjAiIGZpbGw9IiNlZjdkMDAiIGQ9Im0xOS40MjI2MjA2MjgwNTM2NjQsOC43NTgxNDMzNzA5NTAxNjVjLTguOTIyMDg1MjQ0MDkzOTc4LDUuOTA4NTk3NjQ2MjA5MjczLTIuNTk2NzAwNDg2NTQ4Nzk4LDE1Ljk2ODAxNTEzMTkzMjU4OSwxLjg0MTgzMjAwMDQzMjA3OCwyMS4wODA2MDA0MjY2MTE0NTQuOTYyMzA1MjA3Njk5NTAxLDEuMTA0NjAzNjA5MjY2NjMzLjMwNzkwNDI5OTk0MzQwMiwxLjYyMDQxMDc4MDc0NjE3LTEuMTk3ODU4MTMwNzE2NjY4Ljc5NDUxNTc2NDg4NTU0NkMxMy4wMzM3NDEzNDIzNDk0NTgsMjYuNzc2MDQwNTgwMDkwMDEyLTEuODY1NjEyNzkzODA1NjY3LDE4LjY4MTY5MDQxNzM4NDc0My40MzY4NDg5NDYxODU4MTksMTEuMTM2OTgwMDk3ODUwMDI4YzEuNzc5MTIyNTY2OTA2MTUzLTUuODQzNDgzODYwMzgwNzI5LDExLjA1MzMyMjc1MjI2NjQ2Ny01Ljk0MDA1MDQ5OTc5MDIzMiwyMC40MTkyMDcyNjk3OTk2OTktMy4zNjg4MTY1MjAyODQ3ODFsLjE0NjI5NzQ3NzMzMzk3NC4wMTcxOTg0NzkyMjUwNDQtLjE0NjI5NzQ3NzMzMzk3NC4wODQ4MzkyODgzNzcyMjVjLS40NzY3NDg3MTM2NzUwNzkuMjc0NzU4NTg2MDcyNDk0LTEuMDAwMTEyNDIwOTU1NzAyLjYwMTQwNzAyMDI4MTg0LTEuNDMzNDM1NTg3OTMxODU0Ljg4Nzk0MjAyNTc4MjY1aDBaIi8+PHBhdGggc3Ryb2tlLXdpZHRoPSIwIiBmaWxsPSIjY2YwMjJiIiBkPSJtMjAuOTkyNzExNzQ5OTAxOSw3Ljc4OTMxMjA2NDE0MzgxNFMzMi43ODU2NjcyNDU2MzE4ODUuMzc3MjMzNjY4NTUwNjE2LDUzLjU5ODc5NTc0NTcwMjc3My4zNzcyMzM2Njg1NTA2MTZjOC4wNjM0ODYxMzAwNzc3NjMsMCwxNC44NTE5Mjk1MTM3MDM5MDgsMS4yMzQ5NTM4NTE5NDY1NTcsMTcuNzIyNzc1MjMxMTMxODkxLDQuMDU4OTM5MjMzNjc3ODQ3LDMuMDIzNjIwMjI1NDQ0NTc0LDIuOTczOTEzOTIxNzI4MTI2LDQuNjYzNjU4MzcxOTI3MzQsNy45ODM2NTE4MTk5NjI2ODgsNC42NjM2NTgzNzE5MjczNCwxMi41OTA2MTE2MzkxMzc5MzMsMCwzLjk0NzQwNjcyNzg5NzAzMi0xLjY0MDAzODE0NjQ4Mjc2Niw3LjI2NTk3NzE5MTkxNTIyNi01LjA1Njc2OTk3MzM3MTA0Nyw3LjI2NTk3NzE5MTkxNTIyNi04Ljc3NjU3Mjg2MTM4NDkyMSwwLTM2LjExMTIzNzEwNTMxNDEwMy0xMy45MDMyMTYyNTY3NzAwNjUtNDkuOTM1NzQ3NjI1NDg5MDU3LTE2LjUwMzQ0OTY2OTEzNzgwOGgwWiIvPjxwYXRoIHN0cm9rZS13aWR0aD0iMCIgZmlsbD0iIzFkMWQxYiIgZD0ibTE3NS40NjczMDkzNDQyMzI0OSwyOS45MjE2NzM5OTIwMzg0NWMtNy4wNTgyOTE5MTU2MDg2MDYsMC0xMC41NTUzNjkxOTg3Nzc5NTMtNC40ODUzMjg2Mjk3MzAyNDctMTAuNTU1MzY5MTk4Nzc3OTUzLTQuNDg1MzI4NjI5NzMwMjQ3djEyLjQxODA0MTk4NjIwMjI5N2gtNS40Mzk1MDUwODA0NTA1NDRWLjM4OTQyNzM4MTExMmg1LjE0NTkxNzc1MzE3MDU3OWwuMjkzNTg3MzI3Mjc5OTY1LDMuNjY0NTUwNDU3ODc3MzRTMTY4LjMzNTYyMDU5NjgxNTcxNi4wMDExMTExMzc5MDg5OTMsMTc1LjQwNjYyODg2ODQ3ODk0Ny4wMDExMTExMzc5MDg5OTNjNi4yMjE0NDYzMzY4NDM2NTUsMCwxNS4xNzkzOTYwNTg4MjExMTIsMy4xNzE4NzU0MzY4Njg1MDQsMTUuMTc5Mzk2MDU4ODIxMTEyLDE0Ljg0NTY0OTAzMjg5MDgzMywwLDExLjY3MzIwOTIwODQ5OTQyOS04LjA1OTg0MTY0Mjg0MjkxMiwxNS4wNzQ5MTM4MjEyMzg2MjQtMTUuMTE4NzE1NTgzMDY3NTY5LDE1LjA3NDkxMzgyMTIzODYyNGgwWm0tLjI5NDc0MjU1NzkzNzc1Mi0yNC45OTE3NjY3MzkzMTI4OGMtNS40NjMyMDA1MzcyNzE0MDUsMC0xMC4yNjA2MjY2NDA4NDAyMDEsMy4wOTczNzYyODU3MDM4MzEtMTAuMjYwNjI2NjQwODQwMjAxLDkuODU5ODg1MDUzODkwMTM5LDAsNi43NjIyNjE4NDg2NTU3MjYsNC4yMTk0OTMyOTQ0OTc2MjQsMTAuMTQzNzM2Njk2NjI0NzI4LDEwLjIwMjI0NzgwNzg4MDY2NywxMC4xNDM3MzY2OTY2MjQ3MjgsMy4xMzM1NTg4MTYxNTU1MjgsMCw5Ljc0Nzk5NTIzMDI1NTU4My0xLjI3MTQ0MTU5NzY3NDMxMSw5Ljc0Nzk5NTIzMDI1NTU4My0xMC4wMjgwNTQ4OTQ0MTkyNTYsMC04Ljc1NzA1NDIyNDQ3NjYzMy02LjU5NDIxNTQ2Nzg3OTYyMS05Ljk3NTU2Njg1NjA5NTYxMS05LjY4OTYxNjM5NzI5NjALine truncated
<mxGeometry x="360" y="158.14" width="177.08" height="25" as="geometry" />
</mxCell>
<mxCell id="mBbMmTsdGeR7BbYYs1AZ-9" value="" style="shape=image;verticalLabelPosition=bottom;labelBackgroundColor=default;verticalAlign=top;aspect=fixed;imageAspect=0;image=data:image/png,iVBORw0KGgoAAAANSUhEUgAAAZQAAAAyCAYAAAB79y3nAAAABGdBTUEAALGPC/xhBQAACklpQ0NQc1JHQiBJRUM2MTk2Ni0yLjEAAEiJnVN3WJP3Fj7f92UPVkLY8LGXbIEAIiOsCMgQWaIQkgBhhBASQMWFiApWFBURnEhVxILVCkidiOKgKLhnQYqIWotVXDjuH9yntX167+3t+9f7vOec5/zOec8PgBESJpHmomoAOVKFPDrYH49PSMTJvYACFUjgBCAQ5svCZwXFAADwA3l4fnSwP/wBr28AAgBw1S4kEsfh/4O6UCZXACCRAOAiEucLAZBSAMguVMgUAMgYALBTs2QKAJQAAGx5fEIiAKoNAOz0ST4FANipk9wXANiiHKkIAI0BAJkoRyQCQLsAYFWBUiwCwMIAoKxAIi4EwK4BgFm2MkcCgL0FAHaOWJAPQGAAgJlCLMwAIDgCAEMeE80DIEwDoDDSv+CpX3CFuEgBAMDLlc2XS9IzFLiV0Bp38vDg4iHiwmyxQmEXKRBmCeQinJebIxNI5wNMzgwAABr50cH+OD+Q5+bk4eZm52zv9MWi/mvwbyI+IfHf/ryMAgQAEE7P79pf5eXWA3DHAbB1v2upWwDaVgBo3/ldM9sJoFoK0Hr5i3k4/EAenqFQyDwdHAoLC+0lYqG9MOOLPv8z4W/gi372/EAe/tt68ABxmkCZrcCjg/1xYW52rlKO58sEQjFu9+cj/seFf/2OKdHiNLFcLBWK8ViJuFAiTcd5uVKRRCHJleIS6X8y8R+W/QmTdw0ArIZPwE62B7XLbMB+7gECiw5Y0nYAQH7zLYwaC5EAEGc0Mnn3AACTv/mPQCsBAM2XpOMAALzoGFyolBdMxggAAESggSqwQQcMwRSswA6cwR28wBcCYQZEQAwkwDwQQgbkgBwKoRiWQRlUwDrYBLWwAxqgEZrhELTBMTgN5+ASXIHrcBcGYBiewhi8hgkEQcgIE2EhOogRYo7YIs4IF5mOBCJhSDSSgKQg6YgUUSLFyHKkAqlCapFdSCPyLXIUOY1cQPqQ28ggMor8irxHMZSBslED1AJ1QLmoHxqKxqBz0XQ0D12AlqJr0Rq0Hj2AtqKn0UvodXQAfYqOY4DRMQ5mjNlhXIyHRWCJWBomxxZj5Vg1Vo81Yx1YN3YVG8CeYe8IJAKLgBPsCF6EEMJsgpCQR1hMWEOoJewjtBK6CFcJg4Qxwicik6hPtCV6EvnEeGI6sZBYRqwm7iEeIZ4lXicOE1+TSCQOyZLkTgohJZAySQtJa0jbSC2kU6Q+0hBpnEwm65Btyd7kCLKArCCXkbeQD5BPkvvJw+S3FDrFiOJMCaIkUqSUEko1ZT/lBKWfMkKZoKpRzame1AiqiDqfWkltoHZQL1OHqRM0dZolzZsWQ8ukLaPV0JppZ2n3aC/pdLoJ3YMeRZfQl9Jr6Afp5+mD9HcMDYYNg8dIYigZaxl7GacYtxkvmUymBdOXmchUMNcyG5lnmA+Yb1VYKvYqfBWRyhKVOpVWlX6V56pUVXNVP9V5qgtUq1UPq15WfaZGVbNQ46kJ1Bar1akdVbupNq7OUndSj1DPUV+jvl/9gvpjDbKGhUaghkijVGO3xhmNIRbGMmXxWELWclYD6yxrmE1iW7L57Ex2Bfsbdi97TFNDc6pmrGaRZp3mcc0BDsax4PA52ZxKziHODc57LQMtPy2x1mqtZq1+rTfaetq+2mLtcu0W7eva73VwnUCdLJ31Om0693UJuja6UbqFutt1z+o+02PreekJ9cr1Dund0Uf1bfSj9Rfq79bv0R83MDQINpAZbDE4Y/DMkGPoa5hpuNHwhOGoEctoupHEaKPRSaMnuCbuh2fjNXgXPmasbxxirDTeZdxrPGFiaTLbpMSkxeS+Kc2Ua5pmutG003TMzMgs3KzYrMnsjjnVnGueYb7ZvNv8jYWlRZzFSos2i8eW2pZ8ywWWTZb3rJhWPlZ5VvVW16xJ1lzrLOtt1ldsUBtXmwybOpvLtqitm63Edptt3xTiFI8p0in1U27aMez87ArsmuwG7Tn2YfYl9m32zx3MHBId1jt0O3xydHXMdmxwvOuk4TTDqcSpw+lXZxtnoXOd8zUXpkuQyxKXdpcXU22niqdun3rLleUa7rrStdP1o5u7m9yt2W3U3cw9xX2r+00umxvJXcM970H08PdY4nHM452nm6fC85DnL152Xlle+70eT7OcJp7WMG3I28Rb4L3Le2A6Pj1l+s7pAz7GPgKfep+Hvqa+It89viN+1n6Zfgf8nvs7+sv9j/i/4XnyFvFOBWABwQHlAb2BGoGzA2sDHwSZBKUHNQWNBbsGLww+FUIMCQ1ZH3KTb8AX8hv5YzPcZyya0RXKCJ0VWhv6MMwmTB7WEY6GzwjfEH5vpvlM6cy2CIjgR2yIuB9pGZkX+X0UKSoyqi7qUbRTdHF09yzWrORZ+2e9jvGPqYy5O9tqtnJ2Z6xqbFJsY+ybuIC4qriBeIf4RfGXEnQTJAntieTE2MQ9ieNzAudsmjOc5JpUlnRjruXcorkX5unOy553PFk1WZB8OIWYEpeyP+WDIEJQLxhP5aduTR0T8oSbhU9FvqKNolGxt7hKPJLmnVaV9jjdO31D+miGT0Z1xjMJT1IreZEZkrkj801WRNberM/ZcdktOZSclJyjUg1plrQr1zC3KLdPZisrkw3keeZtyhuTh8r35CP5c/PbFWyFTNGjtFKuUA4WTC+oK3hbGFt4uEi9SFrUM99m/ur5IwuCFny9kLBQuLCz2Lh4WfHgIr9FuxYji1MXdy4xXVK6ZHhp8NJ9y2jLspb9UOJYUlXyannc8o5Sg9KlpUMrglc0lamUycturvRauWMVYZVkVe9ql9VbVn8qF5VfrHCsqK74sEa45uJXTl/VfPV5bdra3kq3yu3rSOuk626s91m/r0q9akHV0IbwDa0b8Y3lG19tSt50oXpq9Y7NtM3KzQM1YTXtW8y2rNvyoTaj9nqdf13LVv2tq7e+2Sba1r/dd3vzDoMdFTve75TsvLUreFdrvUV99W7S7oLdjxpiG7q/5n7duEd3T8Wej3ulewf2Re/ranRvbNyvv7+yCW1SNo0eSDpw5ZuAb9qb7Zp3tXBaKg7CQeXBJ9+mfHvjUOihzsPcw83fmX+39QjrSHkr0jq/dawto22gPaG97+iMo50dXh1Hvrf/fu8x42N1xzWPV56gnSg98fnkgpPjp2Snnp1OPz3Umdx590z8mWtdUV29Z0PPnj8XdO5Mt1/3yfPe549d8Lxw9CL3Ytslt0utPa49R35w/eFIr1tv62X3y+1XPK509E3rO9Hv03/6asDVc9f41y5dn3m978bsG7duJt0cuCW69fh29u0XdwruTNxdeo94r/y+2v3qB/oP6n+0/rFlwG3g+GDAYM/DWQ/vDgmHnv6U/9OH4dJHzEfVI0YjjY+dHx8bDRq98mTOk+GnsqcTz8p+Vv9563Or59/94vtLz1j82PAL+YvPv655qfNy76uprzrHI8cfvM55PfGm/K3O233vuO+638e9H5ko/ED+UPPR+mPHp9BP9z7nfP78L/eE8/stRzjPAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAJcEhZcwAADsQAAA7EAZUrDhsAABSwSURBVHic7Z152F7TuYfvJ74kYkramiJFcuKYQg2tFqVmQcycoqoXSqihphKOGNI6pDUdreJU65QaT44WNdZMTDUlwTHVTA4xx0ySX/94duLLl/3ttfd+9/B+yb6va/3xvnvttZ49rr3WM5kkysTMlgE2A+YH7pE0odQOS8bMFgI2AL4LrBCVxYAFo/Iu8AnwIvAs8ChwFzBJ0vQaRG5IiZl1AN8G1sGv678CCwNfAaYDU4G38ev6JDAev67lPkQNDT0EK/NZMLNRwElAR6e/LwP2lvRpaR0XjJktAOwI7AFszOzHk5YpwDjgYkn3FyheEDPrA2wBDAX6VNl3BqYC4yU9VmWnZjYfMBz4ETACWChjE28BVwIXSbq3YPFmw8y2BrbBB7giWAQYjH/sfQC8ABT1XL4KXCHpgYLam4WZDQQ2AZYBlgQWB3oV3M004GXgkqrvyR6NpFIKsDOgbspZZfVb8DEMAI7DXxrdHUuech+wA9GAXvIxrARMLFj+MsuFQO8KzktfYD/guQJlfwj/8Cj0uuIvy8va4NrkKScUdA76AAcAD+CzxarknwYcWPe7qKeUsh7W+YGXAhdpWN0HnyB/r+hl83bJN+tdwBolHkc/fGmm7pdK1jK25Ou7Ucnn5SFgrQLlPawNrkkrZZMWj38Xih34s5bplPiczk2lrAf2yBQX6Zq6D74b2ZcF7qnwZv0COAHoKOFY9myDl0me8gHQt4TzsQBwQYXX9TigVwFyP9sG16SVclHO4+4NnNsG8gs4s+53U08oRa87YmYDgKNTVN3GzDYquv9WMLMRwCPAuhV22wGcCNxqZosW3PbyBbdXFQsBg4ps0MyGAH8H9iqy3QQ6gJ8DN5pZ/xbbGliAPHWSWX4z6wfcBOxfvDi5WKpuAXoChQ8owLHAV1PWHWtmVoIMmTGzHwNXk172ovkecJ+Z/UuBbb5eYFtV8gXwZlGNmdkwfHlxWFFtZmAzYLyZtTJAPlOUMDXxdJbK0TvhAnxpsl3o6degGgpeUhgEfEy2qeROdU/TgIOAGRnlLqs8QUFKafyr6qM2OKas5fICr+1y+MBa9zE9Ayye8xj2aAP585ZPgZUzHu+oNpC7c/kAWKbu91RLine truncated
<mxGeometry x="560" y="160.64" width="161.6" height="20" as="geometry" />
</mxCell>
<mxCell id="mBbMmTsdGeR7BbYYs1AZ-1" value="Data Center" style="" parent="0" />
<mxCell id="mBbMmTsdGeR7BbYYs1AZ-10" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=none;dashed=1;arcSize=2;" vertex="1" parent="mBbMmTsdGeR7BbYYs1AZ-1">
<mxGeometry x="580" y="240" width="170" height="320" as="geometry" />
</mxCell>
<mxCell id="mBbMmTsdGeR7BbYYs1AZ-11" value="" style="shape=image;verticalLabelPosition=bottom;labelBackgroundColor=default;verticalAlign=top;aspect=fixed;imageAspect=0;editableCssRules=.*;image=data:image/svg+xml,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjQuMDAzNTE2MTk3MjA0NTkgNi41NDMwMDAyMjEyNTI0NDEgODcuOTkzMjU1NjE1MjM0MzggODIuOTEzMDAyMDE0MTYwMTYiIGhlaWdodD0iMTI5LjU1MTU2NTY0NzEyNTI0IiB3aWR0aD0iMTM3LjQ4OTQ2MTg5ODgwMzciPiYjeGE7ICAgIDxkZWZzPiYjeGE7ICAgICAgICA8bGluZWFyR3JhZGllbnQgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgLTEgMTA3NSAxNTgpIiB5Mj0iNjUuNDI2IiB5MT0iMTQ1LjMxMiIgeDI9Ii0xMDU5LjIxMyIgeDE9Ii0xMDMyLjE3MiIgaWQ9ImUzOTljMTlmLWI2OGYtNDI5ZC1iMTc2LTE4YzIxMTdmZjczYyI+JiN4YTsgICAgICAgICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjMTE0YThiIiBvZmZzZXQ9IjAiLz4mI3hhOyAgICAgICAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiMwNjY5YmMiIG9mZnNldD0iMSIvPiYjeGE7ICAgICAgICA8L2xpbmVhckdyYWRpZW50PiYjeGE7ICAgICAgICA8bGluZWFyR3JhZGllbnQgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgLTEgMTA3NSAxNTgpIiB5Mj0iMTA1Ljk2OCIgeTE9IjEwOC4wODMiIHgyPSItMTAyOS45OCIgeDE9Ii0xMDIzLjcyNSIgaWQ9ImFjMmE2ZmMyLWNhNDgtNDMyNy05YTNjLWQ0ZGNjMzI1NmUxNSI+JiN4YTsgICAgICAgICAgICA8c3RvcCBzdG9wLW9wYWNpdHk9Ii4zIiBvZmZzZXQ9IjAiLz4mI3hhOyAgICAgICAgICAgIDxzdG9wIHN0b3Atb3BhY2l0eT0iLjIiIG9mZnNldD0iLjA3MSIvPiYjeGE7ICAgICAgICAgICAgPHN0b3Agc3RvcC1vcGFjaXR5PSIuMSIgb2Zmc2V0PSIuMzIxIi8+JiN4YTsgICAgICAgICAgICA8c3RvcCBzdG9wLW9wYWNpdHk9Ii4wNSIgb2Zmc2V0PSIuNjIzIi8+JiN4YTsgICAgICAgICAgICA8c3RvcCBzdG9wLW9wYWNpdHk9IjAiIG9mZnNldD0iMSIvPiYjeGE7ICAgICAgICA8L2xpbmVhckdyYWRpZW50PiYjeGE7ICAgICAgICA8bGluZWFyR3JhZGllbnQgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgLTEgMTA3NSAxNTgpIiB5Mj0iNjguNTYxIiB5MT0iMTQ3LjY0MiIgeDI9Ii05OTcuNDgyIiB4MT0iLTEwMjcuMTY1IiBpZD0iYTdmZWU5NzAtYTc4NC00YmIxLWFmOGQtNjNkMThlNWY3ZGI5Ij4mI3hhOyAgICAgICAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiMzY2NiZjQiIG9mZnNldD0iMCIvPiYjeGE7ICAgICAgICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzI4OTJkZiIgb2Zmc2V0PSIxIi8+JiN4YTsgICAgICAgIDwvbGluZWFyR3JhZGllbnQ+JiN4YTsgICAgPC9kZWZzPiYjeGE7ICAgIDxwYXRoIGQ9Ik0zMy4zMzggNi41NDRoMjYuMDM4bC0yNy4wMyA4MC4wODdhNC4xNTIgNC4xNTIgMCAwIDEtMy45MzMgMi44MjRIOC4xNDlhNC4xNDUgNC4xNDUgMCAwIDEtMy45MjgtNS40N0wyOS40MDQgOS4zNjhhNC4xNTIgNC4xNTIgMCAwIDEgMy45MzQtMi44MjV6IiBmaWxsPSJ1cmwoI2UzOTljMTlmLWI2OGYtNDI5ZC1iMTc2LTE4YzIxMTdmZjczYykiLz4mI3hhOyAgICA8cGF0aCBkPSJNNzEuMTc1IDYwLjI2MWgtNDEuMjlhMS45MTEgMS45MTEgMCAwIDAtMS4zMDUgMy4zMDlsMjYuNTMyIDI0Ljc2NGE0LjE3MSA0LjE3MSAwIDAgMCAyLjg0NiAxLjEyMWgyMy4zOHoiIGZpbGw9IiMwMDc4ZDQiLz4mI3hhOyAgICA8cGF0aCBkPSJNMzMuMzM4IDYuNTQ0YTQuMTE4IDQuMTE4IDAgMCAwLTMuOTQzIDIuODc5TDQuMjUyIDgzLjkxN2E0LjE0IDQuMTQgMCAwIDAgMy45MDggNS41MzhoMjAuNzg3YTQuNDQzIDQuNDQzIDAgMCAwIDMuNDEtMi45bDUuMDE0LTE0Ljc3NyAxNy45MSAxNi43MDVhNC4yMzcgNC4yMzcgMCAwIDAgMi42NjYuOTcySDgxLjI0TDcxLjAyNCA2MC4yNjFsLTI5Ljc4MS4wMDdMNTkuNDcgNi41NDR6IiBmaWxsPSJ1cmwoI2FjMmE2ZmMyLWNhNDgtNDMyNy05YTNjLWQ0ZGNjMzI1NmUxNSkiLz4mI3hhOyAgICA8cGF0aCBkPSJNNjYuNTk1IDkuMzY0YTQuMTQ1IDQuMTQ1IDAgMCAwLTMuOTI4LTIuODJIMzMuNjQ4YTQuMTQ2IDQuMTQ2IDAgMCAxIDMuOTI4IDIuODJsMjUuMTg0IDc0LjYyYTQuMTQ2IDQuMTQ2IDAgMCAxLTMuOTI4IDUuNDcyaDI5LjAyYTQuMTQ2IDQuMTQ2IDAgMCAwIDMuOTI3LTUuNDcyeiIgZmlsbD0idXJsKCNhN2ZlZTk3MC1hNzg0LTRiYjEtYWY4ZC02M2QxOGU1ZjdkYjkpIi8+JiN4YTs8L3N2Zz4=;" vertex="1" parent="mBbMmTsdGeR7BbYYs1AZ-1">
<mxGeometry x="590" y="580" width="42.15" height="40" as="geometry" />
</mxCell>
<mxCell id="mBbMmTsdGeR7BbYYs1AZ-12" value="Microsoft Azure" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Tahoma;fontSize=16;" vertex="1" parent="mBbMmTsdGeR7BbYYs1AZ-1">
<mxGeometry x="640" y="585" width="130" height="30" as="geometry" />
</mxCell>
<mxCell id="mBbMmTsdGeR7BbYYs1AZ-2" value="Layer" parent="0" />
<mxCell id="mBbMmTsdGeR7BbYYs1AZ-3" value="Komponenten" parent="0" />
<mxCell id="mBbMmTsdGeR7BbYYs1AZ-4" value="Gruppen" parent="0" />
<mxCell id="mBbMmTsdGeR7BbYYs1AZ-5" value="Zuständigkeiten" parent="0" />
</root>
</mxGraphModel>
</diagram>
</mxfile>
+11
View File
@@ -0,0 +1,11 @@
Durchsuchen von Azure-Architekturen
https://learn.microsoft.com/de-de/azure/architecture/browse/
Baselinearchitektur für einen AKS-Cluster (Azure Kubernetes Service)
https://learn.microsoft.com/de-de/azure/architecture/reference-architectures/containers/aks/baseline-aks
Microsoft AI Tour
https://aitour.microsoft.com/flow/microsoft/aitour/landing/page/home?wt.mc_ID=AITourFY26-Tier1_GMEE_corp_bn_oo_bn_MSLearn
Erstellen ausgezeichneter Lösungen mit dem Microsoft Azure Well-Architected Framework
https://learn.microsoft.com/de-de/training/paths/azure-well-architected-framework/?source=recommendations
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

@@ -0,0 +1,26 @@
<svg width="96" height="96" viewBox="0 0 96 96" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_98_3132)">
<g clip-path="url(#clip1_98_3132)">
<rect x="12.05" y="0.05" width="71.9" height="95.9" rx="3.95" stroke="white" stroke-width="0.1"/>
<rect x="0.05" y="83.95" width="71.9" height="95.9" rx="3.95" transform="rotate(-90 0.05 83.95)" stroke="white" stroke-width="0.1"/>
<rect x="6.05" y="89.95" width="83.9" height="83.9" rx="3.95" transform="rotate(-90 6.05 89.95)" stroke="white" stroke-width="0.1"/>
<circle cx="48" cy="48" r="23.95" stroke="white" stroke-width="0.1"/>
<circle cx="48" cy="48" r="47.95" stroke="white" stroke-width="0.1"/>
<path d="M48 0V96" stroke="white" stroke-width="0.1"/>
<path d="M96 47.9999L0 47.9999" stroke="white" stroke-width="0.1"/>
<path d="M0 6.10352e-05L96 96.0001" stroke="white" stroke-width="0.1"/>
<path d="M0 96.0001L96 5.62289e-05" stroke="white" stroke-width="0.1"/>
<path d="M25.6416 90.4728C27.0797 90.4644 28.4659 90.1346 29.4945 89.5368L59.8103 71.5187C63.2057 69.563 65.9594 65.2917 65.9594 61.976V33.5368C65.9594 26.8761 64.5079 20.922 62.0167 16.4448C73.5834 19.878 81.7427 28.1929 81.7427 37.908V84.1749C81.7427 87.6859 78.0767 90.5367 73.5439 90.5367H26.8083C26.4122 90.5367 26.0227 90.5149 25.6416 90.4728Z" stroke="black" stroke-width="4"/>
<path d="M18.6128 64.2749C19.261 64.091 19.9526 63.7767 20.6707 63.3246L37.1189 53.216C41.7761 50.3538 44.6384 45.1107 44.6384 39.4421V22.9964C44.6384 17.5879 43.7219 13.256 42.1194 10.3192C42.1754 10.2866 42.2315 10.2542 42.2876 10.2218C55.3597 2.69704 65.9603 15.5367 65.9603 33.5368V61.976C65.9603 65.2917 63.2066 69.563 59.8111 71.5187L29.4954 89.5368C26.0538 91.5368 18.6104 90.5368 18.6104 84.5368L18.6128 64.2749Z" stroke="black" stroke-width="4"/>
<path d="M33.2387 6.50703C23.3322 10.1545 14.0049 26.5433 14.0049 44.4012L14 60.4046C14 64.3366 16.9871 65.6438 20.6705 63.3246L37.1187 53.216C41.7759 50.3538 44.6382 45.1107 44.6382 39.4421V22.9964C44.6382 10.7625 39.9484 4.03662 33.2387 6.50703Z" stroke="black" stroke-width="4"/>
</g>
</g>
<defs>
<clipPath id="clip0_98_3132">
<rect width="96" height="96" fill="white"/>
</clipPath>
<clipPath id="clip1_98_3132">
<rect width="96" height="96" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="uuid-224e3580-d59f-48a8-9bb3-c822840f911d" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
<path d="m17.558,9.638L10.436,1.632c-.358-.402-.881-.632-1.435-.632h0c-.554,0-1.078.231-1.435.632L.442,9.638c-.346.389-.5.9-.423,1.403.077.503.379.952.827,1.231l7.123,4.436c.313.195.672.293,1.031.293s.718-.098,1.031-.293l7.123-4.436c.448-.279.75-.728.827-1.231.077-.503-.077-1.014-.423-1.403Zm-8.557,2.564l-3.47-2.161,3.47-3.9,3.47,3.9-3.47,2.161Zm-4.821-1.975l3.995,2.489-1.137.708-.016.01c-.394.25-.854.382-1.33.382-.528,0-1.059-.214-1.38-.413l-2.969-1.849c-.235-.147-.387-.373-.428-.637-.04-.264.037-.521.219-.725L8.257,2.186c.185-.208.456-.327.743-.328.287,0,.558.119.743.328l1.576,1.771c-.009,0-.018,0-.028,0-.856,0-1.668.313-2.278.866l-4.833,5.404Zm12.905.69c-.041.264-.192.49-.428.637l-7.123,4.436c-.325.202-.744.202-1.068,0l-2.192-1.365c.451-.076.88-.238,1.264-.484l6.259-3.898-4.197-4.759c.448-.425,1.053-.667,1.692-.667.335,0,.661.07.97.201l4.605,5.175c.181.204.259.461.219.725Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
<g id="uuid-81cf057c-ff75-4803-9a10-fe44c632e0c8" />
<g id="uuid-b8784509-f923-44ee-a3b9-d40f96b60fd9">
<g>
<path d="M18,9c0-1.574-.406-3.052-1.117-4.34,.387-.44,.629-1.011,.629-1.643,0-1.381-1.119-2.5-2.5-2.5-.628,0-1.196,.24-1.635,.623-1.296-.724-2.788-1.14-4.378-1.14s-3.082,.416-4.378,1.14c-.439-.383-1.007-.623-1.635-.623C1.606,.517,.487,1.636,.487,3.017c0,.632,.242,1.203,.63,1.643-.71,1.287-1.116,2.766-1.116,4.34,0,1.594,.418,3.089,1.146,4.388-.405,.444-.659,1.03-.659,1.679,0,1.381,1.119,2.5,2.5,2.5,.656,0,1.247-.258,1.693-.671,1.282,.703,2.754,1.104,4.32,1.104s3.037-.401,4.32-1.104c.446,.413,1.038,.671,1.693,.671,1.381,0,2.5-1.119,2.5-2.5,0-.649-.253-1.234-.659-1.678,.727-1.299,1.146-2.794,1.146-4.388ZM13.617,2.478c.125-.324,.36-.589,.658-.759,.219-.125,.468-.202,.738-.202,.827,0,1.5,.673,1.5,1.5,0,.272-.078,.523-.205,.743-.172,.297-.438,.53-.762,.654-.166,.064-.344,.102-.533,.102-.827,0-1.5-.673-1.5-1.5,0-.19,.039-.371,.104-.539ZM2.987,1.517c.269,0,.519,.077,.738,.202,.298,.17,.533,.436,.658,.759,.065,.168,.104,.348,.104,.539,0,.827-.673,1.5-1.5,1.5-.188,0-.366-.039-.532-.102-.324-.124-.591-.357-.762-.654-.127-.22-.205-.472-.205-.744,0-.827,.673-1.5,1.5-1.5Zm1.417,14.02c-.11,.33-.327,.608-.615,.792-.233,.148-.507,.237-.802,.237-.827,0-1.5-.673-1.5-1.5,0-.291,.087-.561,.231-.792,.181-.29,.458-.509,.787-.622,.152-.052,.312-.086,.482-.086,.827,0,1.5,.673,1.5,1.5,0,.165-.033,.322-.083,.471Zm10.609,1.029c-.296,0-.57-.089-.802-.237-.288-.184-.505-.462-.615-.792-.05-.149-.083-.306-.083-.471,0-.827,.673-1.5,1.5-1.5,.17,0,.33,.034,.482,.087,.328,.113,.605,.332,.787,.622,.144,.23,.231,.5,.231,.792,0,.827-.673,1.5-1.5,1.5Zm0-4c-1.381,0-2.5,1.119-2.5,2.5,0,.359,.079,.698,.215,1.007-1.114,.59-2.382,.927-3.728,.927s-2.613-.338-3.728-.927c.136-.308,.215-.648,.215-1.006,0-1.381-1.119-2.5-2.5-2.5-.368,0-.714,.084-1.028,.226-.611-1.129-.959-2.421-.959-3.793,0-1.346,.337-2.613,.927-3.727,.323,.152,.68,.244,1.06,.244,1.381,0,2.5-1.119,2.5-2.5,0-.386-.095-.746-.25-1.073,1.123-.601,2.403-.945,3.764-.945s2.641,.343,3.763,.944c-.156,.326-.25,.687-.25,1.073,0,1.381,1.119,2.5,2.5,2.5,.381,0,.737-.092,1.06-.244,.589,1.114,.927,2.381,.927,3.727,0,1.372-.348,2.663-.959,3.793-.314-.143-.661-.227-1.029-.227Z" fill="#212121" />
<g>
<path d="M11.874,10.037H6.125c-.621,0-1.124,.503-1.124,1.124v.289c0,.446,.159,.878,.449,1.217,.783,.917,1.976,1.369,3.548,1.369s2.765-.452,3.55-1.369c.291-.34,.45-.772,.45-1.219v-.288c0-.621-.503-1.124-1.124-1.124Z" fill="#212121" />
<path d="M8.998,9.04c1.38,0,2.499-1.119,2.499-2.499s-1.119-2.499-2.499-2.499-2.499,1.119-2.499,2.499,1.119,2.499,2.499,2.499Z" fill="#212121" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="uuid-af471f8d-f5bf-4123-94c3-4139b0ba56d8" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
<path d="m17.679,10.013c-.013-.015-3.337-3.818-3.334-3.806-.54-.751-1.484-1.224-2.511-1.224-.028,0-.055.003-.082.004-.856.022-1.553.463-2.085,1.031l3.701,4.182h0s-6.159,3.855-6.159,3.855c0,0-1.168.856-2.495.541.109.068,3.474,2.169,3.474,2.169.499.313,1.146.313,1.645,0,0,0,7.339-4.596,7.489-4.687.826-.501.838-1.512.357-2.066Z"/>
<path d="m10.113,1.467c-.525-.577-1.598-.683-2.248.043-.189.211-7.325,8.262-7.526,8.489-.568.638-.403,1.615.353,2.081,0,0,1.751,1.097,1.865,1.169.696.436,2.571,1.036,4.454-.096l1.179-.738-3.536-2.213s4.461-5.039,4.467-5.047c1.294-1.416,2.987-1.032,3.613-.735.002.001-2.607-2.937-2.621-2.951Z"/>
</svg>

After

Width:  |  Height:  |  Size: 825 B

@@ -0,0 +1,7 @@
<svg id="uuid-13cc8fd5-c6d0-4916-a4e6-c8d153fb7667" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
<g>
<path d="m10.775,15.071c-.81.308-1.687.479-2.603.479-2.353,0-4.45-1.115-5.795-2.845l.026-.099c.192-.733.396-1.507.672-2.288.28.103.58.161.895.161.472,0,.914-.128,1.297-.348.616.526,1.27,1.005,2.088,1.482-.113.255-.176.536-.176.832,0,1.139.925,2.065,2.062,2.065.436,0,.84-.137,1.174-.369-.068-.271-.108-.55-.108-.836v-.233c-.215.366-.612.612-1.066.612-.682,0-1.237-.556-1.237-1.239s.555-1.239,1.237-1.239c.454,0,.85.247,1.066.612v-1.138c-.311-.189-.675-.3-1.066-.3-.541,0-1.033.212-1.401.554-.739-.432-1.373-.884-1.917-1.34.408-.462.659-1.067.659-1.731,0-.709-.284-1.352-.744-1.824.613-.55,1.317-1.036,2.11-1.463.968,1.058,2.027,2.031,3.164,2.905-.14.278-.22.591-.22.924,0,.548.215,1.045.564,1.415.461-.059.736-.17.959-.302-.413-.201-.698-.624-.698-1.113,0-.683.555-1.239,1.237-1.239s1.237.556,1.237,1.239c0,.149-.028.292-.076.424.071-.004.144-.006.222-.006.243,0,.447.019.624.051.035-.151.056-.308.056-.47,0-1.139-.925-2.065-2.062-2.065-.508,0-.972.185-1.332.491-1.039-.797-2.01-1.68-2.904-2.637,1.281-.586,2.774-1.036,4.493-1.357,1.42,1.343,2.309,3.244,2.309,5.351,0,.285-.018.565-.049.842.201.09.359.2.515.309.082.057.164.114.252.167.07-.429.107-.869.107-1.318C16.345,3.673,12.679,0,8.172,0S0,3.673,0,8.188s3.666,8.188,8.172,8.188c1.077,0,2.106-.212,3.049-.593-.165-.226-.316-.464-.446-.712ZM8.172.826c1.565,0,3.016.494,4.209,1.333-1.677.358-3.076.831-4.246,1.387-.097-.112-.195-.223-.29-.336-.566-.672-1.077-1.391-1.528-2.146.593-.155,1.214-.238,1.855-.238Zm-2.657.5c.496.852,1.065,1.663,1.699,2.416.054.065.111.128.166.192-.881.487-1.616,1.026-2.233,1.598-.354-.18-.753-.284-1.177-.284-.366,0-.714.076-1.03.213-.338-.965-.389-1.71-.395-1.999.789-.942,1.809-1.682,2.971-2.136Zm-2.941,5.422c.179-.224.411-.404.677-.522.22-.097.462-.152.718-.152.193,0,.379.032.553.089.277.091.525.247.724.451.315.323.51.763.51,1.249,0,.452-.17.864-.447,1.179-.188.214-.427.383-.697.488-.2.078-.417.122-.644.122-.21,0-.41-.038-.597-.105-.271-.097-.512-.256-.705-.462-.3-.32-.486-.749-.486-1.222,0-.422.147-.809.392-1.116Zm-.808,5.038c-.598-1.065-.941-2.292-.941-3.599,0-1.347.364-2.609.997-3.696.073.406.194.894.397,1.436-.528.479-.862,1.168-.862,1.936,0,.827.386,1.563.986,2.043-.232.642-.414,1.275-.577,1.88Z"/>
<path d="m14.337,10.018c.536,0,.68.101.967.301.361.252.835.583,1.871.698v2.288c0,1.673-2.027,3.209-2.84,3.758-.377-.252-.981-.693-1.54-1.262-.592-.603-1.297-1.525-1.297-2.495v-2.288c1.035-.115,1.51-.446,1.871-.698.287-.2.431-.301.968-.301m0-.826c-1.696,0-1.175.978-3.438,1.037-.124.002-.223.102-.225.226v2.85c0,2.368,2.91,4.278,3.543,4.662.037.022.079.034.121.034s.084-.011.121-.034c.633-.387,3.543-2.294,3.543-4.662v-2.85c-.002-.124-.101-.224-.225-.226-2.264-.06-1.742-1.037-3.438-1.037h0Z"/>
</g>
<path d="m16.727,13.453c-.016-.526-.41-.963-.932-1.032-.032-.74-.653-1.318-1.394-1.295-.59-.011-1.122.352-1.327.905-.629.076-1.109.601-1.127,1.235.028.716.63,1.274,1.346,1.249.04,0,.081-.002.118-.005h2.18c.019,0,.039-.003.057-.009.582-.004,1.057-.466,1.078-1.048Z"/>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

@@ -0,0 +1,5 @@
<svg id="uuid-4ac2bde4-e4f4-4501-bf11-e537e78bc3b0" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
<path d="m10.775,15.071c-.81.308-1.687.479-2.603.479-2.353,0-4.45-1.115-5.795-2.845l.026-.099c.192-.733.396-1.507.672-2.288.28.103.58.161.895.161.472,0,.914-.128,1.297-.348.616.526,1.27,1.005,2.088,1.482-.113.255-.176.536-.176.832,0,1.139.925,2.065,2.062,2.065.436,0,.84-.137,1.174-.369-.068-.271-.108-.55-.108-.836v-.233c-.215.366-.612.612-1.066.612-.682,0-1.237-.556-1.237-1.239s.555-1.239,1.237-1.239c.454,0,.85.247,1.066.612v-1.138c-.311-.189-.675-.3-1.066-.3-.541,0-1.033.212-1.401.554-.739-.432-1.373-.884-1.917-1.34.408-.462.659-1.067.659-1.731,0-.709-.284-1.352-.744-1.824.613-.55,1.317-1.036,2.11-1.463.968,1.058,2.027,2.031,3.164,2.905-.14.278-.22.591-.22.924,0,.548.215,1.045.564,1.415.461-.059.736-.17.959-.302-.413-.201-.698-.624-.698-1.113,0-.683.555-1.239,1.237-1.239s1.237.556,1.237,1.239c0,.149-.028.292-.076.424.071-.004.144-.006.222-.006.243,0,.447.019.624.051.035-.151.056-.308.056-.47,0-1.139-.925-2.065-2.062-2.065-.508,0-.972.185-1.332.491-1.039-.797-2.01-1.68-2.904-2.637,1.281-.586,2.774-1.036,4.493-1.357,1.42,1.343,2.309,3.244,2.309,5.351,0,.285-.018.565-.049.842.201.09.359.2.515.309.082.057.164.114.252.167.07-.429.107-.869.107-1.318C16.345,3.673,12.679,0,8.172,0S0,3.673,0,8.188s3.666,8.188,8.172,8.188c1.077,0,2.106-.212,3.049-.593-.165-.226-.316-.464-.446-.712ZM8.172.826c1.565,0,3.016.494,4.209,1.333-1.677.358-3.076.831-4.246,1.387-.097-.112-.195-.223-.29-.336-.566-.672-1.077-1.391-1.528-2.146.593-.155,1.214-.238,1.855-.238Zm-2.657.5c.496.852,1.065,1.663,1.699,2.416.054.065.111.128.166.192-.881.487-1.616,1.026-2.233,1.598-.354-.18-.753-.284-1.177-.284-.366,0-.714.076-1.03.213-.338-.965-.389-1.71-.395-1.999.789-.942,1.809-1.682,2.971-2.136Zm-2.941,5.422c.179-.224.411-.404.677-.522.22-.097.462-.152.718-.152.193,0,.379.032.553.089.277.091.525.247.724.451.315.323.51.763.51,1.249,0,.452-.17.864-.447,1.179-.188.214-.427.383-.697.488-.2.078-.417.122-.644.122-.21,0-.41-.038-.597-.105-.271-.097-.512-.256-.705-.462-.3-.32-.486-.749-.486-1.222,0-.422.147-.809.392-1.116Zm-.808,5.038c-.598-1.065-.941-2.292-.941-3.599,0-1.347.364-2.609.997-3.696.073.406.194.894.397,1.436-.528.479-.862,1.168-.862,1.936,0,.827.386,1.563.986,2.043-.232.642-.414,1.275-.577,1.88Z"/>
<path d="m14.337,10.018c.536,0,.68.101.967.301.361.252.835.583,1.871.698v2.288c0,1.673-2.027,3.209-2.84,3.758-.377-.252-.981-.693-1.54-1.262-.592-.603-1.297-1.525-1.297-2.495v-2.288c1.035-.115,1.51-.446,1.871-.698.287-.2.431-.301.968-.301m0-.826c-1.696,0-1.175.978-3.438,1.037-.124.002-.223.102-.225.226v2.85c0,2.368,2.91,4.278,3.543,4.662.037.022.079.034.121.034s.084-.011.121-.034c.633-.387,3.543-2.294,3.543-4.662v-2.85c-.002-.124-.101-.224-.225-.226-2.264-.06-1.742-1.037-3.438-1.037h0Z"/>
<path d="m15.789,12.926l.002-.002c-.027-.024-.063-.038-.099-.038h-.221v-.684c.002-.322-.116-.633-.331-.872-.206-.24-.508-.376-.824-.371-.315-.004-.617.132-.823.371-.217.238-.335.55-.331.872v.684h-.179c-.01,0-.018.004-.027.006-.008.002-.016.002-.024.005-.059.022-.102.076-.103.143v1.766c0,.016.005.03.01.044,0,0,0,0,0,0,.002.007.004.014.007.02.009.024.024.046.044.062l.007-.005c.025.018.054.03.087.031h2.702c.035,0,.066-.014.092-.034l.012.008c.034-.029.055-.071.055-.116v-1.776c0-.046-.022-.086-.055-.115Zm-2.09-.735c.001-.178.07-.349.192-.478.199-.232.547-.258.779-.06.021.018.041.038.06.06.027.03.051.062.072.096.083.11.13.244.134.382v.695s-1.237,0-1.237,0v-.695Z"/>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

@@ -0,0 +1,13 @@
<svg id="uuid-588fe919-40d5-4cd4-ba0b-9913154d9b1c" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
<rect x="7.862" y="5.437" width="7.182" height="1.396" rx=".698" ry=".698"/>
<path d="m12.98,8.144h-4.395c-.335,0-.644.225-.71.554-.09.449.251.842.683.842h3.022c.268-.557.67-1.076,1.399-1.396Z"/>
<path d="m17.436,11.063c0-1.461-1.18-2.645-2.636-2.645s-2.636,1.184-2.636,2.645c0,.892.441,1.679,1.115,2.158l-.169,3.387c-.008.161.116.298.276.306.083.004.164-.027.222-.086l1.146-.726,1.137.736c.113.115.297.117.412.004.059-.058.091-.138.087-.22l-.131-3.357c.709-.474,1.176-1.283,1.176-2.202Z"/>
<path d="m12.701,13.482c-.193-.168-.358-.362-.504-.568H1.905c-.506,0-.917-.412-.917-.917V2.98c0-.506.412-.917.917-.917h14.19c.506,0,.917.412.917.917v5.691c.48.427.831.99.987,1.634V2.98c0-1.05-.855-1.905-1.905-1.905H1.905C.855,1.075,0,1.93,0,2.98v9.017C0,13.047.855,13.902,1.905,13.902h10.776l.021-.419Z"/>
<g>
<path d="m4.637,8.479c-1.187,0-2.154-.966-2.154-2.153s.966-2.153,2.154-2.153,2.153.966,2.153,2.153-.966,2.153-2.153,2.153Zm0-3.319c-.643,0-1.166.523-1.166,1.166s.523,1.166,1.166,1.166,1.166-.523,1.166-1.166-.523-1.166-1.166-1.166Z"/>
<path d="m7.457,10.311h-.987c0-1.01-.822-1.832-1.832-1.832s-1.832.822-1.832,1.832h-.987c0-1.554,1.265-2.819,2.82-2.819s2.819,1.265,2.819,2.819Z"/>
</g>
<g id="uuid-51c02749-836c-4702-ab14-9b01ec3151e7">
<path d="m14.338,12.249c-.079,0-.154-.031-.209-.087l-.859-.859c-.111-.12-.103-.307.017-.418.113-.104.288-.104.401,0l.65.652,1.592-1.593c.12-.111.307-.103.418.017.104.113.104.288,0,.401l-1.801,1.801c-.056.055-.131.085-.209.085Z" fill="#fff"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -0,0 +1,27 @@
<svg id="f861199a-9921-482a-87ea-8504385ff0cd" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
<defs>
<linearGradient id="f13c7428-fd1f-409a-aa83-518164fbbc0c" x1="9" y1="7.11" x2="9" y2="14.2" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#a67af4" />
<stop offset="1" stop-color="#552f99" />
</linearGradient>
<linearGradient id="a6b01360-3b65-4cb5-8c1b-eed2f64af70c" x1="8.8" y1="3.31" x2="9.32" y2="9.75" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#a67af4" />
<stop offset="1" stop-color="#552f99" />
</linearGradient>
</defs>
<title>Icon-identity-235</title>
<g>
<path d="M2.15,11.75a7.34,7.34,0,0,1,1-7.2,1.94,1.94,0,0,1-.7-.83,8.48,8.48,0,0,0-1.17,8.6A3.1,3.1,0,0,1,2.15,11.75ZM5.94,1.14a3.14,3.14,0,0,1,.62.9A7.5,7.5,0,0,1,9,1.61,7.33,7.33,0,0,1,13.33,3a2.15,2.15,0,0,1,.55-.69h0L14,2.22A8.44,8.44,0,0,0,5.94,1.14Zm9.91,5.12a7.32,7.32,0,0,1-1,7.19,2,2,0,0,1,.43.4,1.94,1.94,0,0,1,.27.43,8.48,8.48,0,0,0,1.17-8.6A3.13,3.13,0,0,1,15.85,6.26ZM11.44,16A7.25,7.25,0,0,1,9,16.39H9A7.32,7.32,0,0,1,4.67,15a2.05,2.05,0,0,1-.55.69h0L4,15.78a8.48,8.48,0,0,0,8.09,1.09A3.13,3.13,0,0,1,11.44,16Z" fill="#0078d4" />
<path d="M5.18,1.87a2.09,2.09,0,1,1-3,0,2.09,2.09,0,0,1,3,0Z" fill="#32bedd" />
<path d="M4.42,4.07a1,1,0,0,0,0-1.45A1,1,0,0,0,3,2.62,1,1,0,0,0,3,4.07H3a1,1,0,0,0,1.44,0" fill="#fff" />
<path d="M13.18,1.87a2.09,2.09,0,1,1,0,3,2.09,2.09,0,0,1,0-2.95Z" fill="#32bedd" />
<path d="M15.38,2.62a1,1,0,1,0,0,1.45h0a1,1,0,0,0,0-1.45" fill="#fff" />
<path d="M12.82,16.13a2.09,2.09,0,1,1,3,0,2.09,2.09,0,0,1-3,0Z" fill="#32bedd" />
<path d="M13.58,13.93a1,1,0,0,0,0,1.45,1,1,0,0,0,1.44,0,1,1,0,0,0,0-1.45h0a1,1,0,0,0-1.44,0" fill="#fff" />
<path d="M4.82,16.13a2.09,2.09,0,1,1,0-2.95,2.09,2.09,0,0,1,0,2.95Z" fill="#32bedd" />
<path d="M2.62,15.38a1,1,0,1,0,0-1.45h0a1,1,0,0,0,0,1.45" fill="#fff" />
<path d="M12.51,12.92a.76.76,0,0,0,.76-.76v-.09C13,9.69,11.61,7.74,9,7.74S5,9.39,4.74,12.08a.76.76,0,0,0,.68.84h7.09Z" fill="url(#f13c7428-fd1f-409a-aa83-518164fbbc0c)" />
<path d="M9,8.31a2.41,2.41,0,0,1-1.3-.38L9,11.28,10.27,8A2.37,2.37,0,0,1,9,8.31Z" fill="#fff" opacity="0.8" />
<circle cx="9.01" cy="5.92" r="2.39" fill="url(#a6b01360-3b65-4cb5-8c1b-eed2f64af70c)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="uuid-f8d4d392-7c12-4bd9-baff-66fbf7814b91" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
<path d="m3.802,14.032c.388.242,1.033.511,1.715.511.621,0,1.198-.18,1.676-.487,0,0,.001,0,.002-.001l1.805-1.128v4.073c-.286,0-.574-.078-.824-.234l-4.374-2.734Z" fill="#225086"/>
<path d="m7.853,1.507L.353,9.967c-.579.654-.428,1.642.323,2.111,0,0,2.776,1.735,3.126,1.954.388.242,1.033.511,1.715.511.621,0,1.198-.18,1.676-.487,0,0,.001,0,.002-.001l1.805-1.128-4.364-2.728,4.365-4.924V1s0,0,0,0c-.424,0-.847.169-1.147.507Z" fill="#6df"/>
<polygon points="4.636 10.199 4.688 10.231 9 12.927 9.001 12.927 9.001 12.927 9.001 5.276 9 5.275 4.636 10.199" fill="#cbf8ff"/>
<path d="m17.324,12.078c.751-.469.902-1.457.323-2.111l-4.921-5.551c-.397-.185-.842-.291-1.313-.291-.925,0-1.752.399-2.302,1.026l-.109.123h0s4.364,4.924,4.364,4.924h0s0,0,0,0l-4.365,2.728v4.073c.287,0,.573-.078.823-.234l7.5-4.688Z" fill="#074793"/>
<path d="m9.001,1v4.275s.109-.123.109-.123c.55-.627,1.377-1.026,2.302-1.026.472,0,.916.107,1.313.291l-2.579-2.909c-.299-.338-.723-.507-1.146-.507Z" fill="#0294e4"/>
<polygon points="13.365 10.199 13.365 10.199 13.365 10.199 9.001 5.276 9.001 12.926 13.365 10.199" fill="#96bcc2"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -0,0 +1,30 @@
<svg id="uuid-f4ec8483-67f3-444b-ae88-1121f3f27867" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
<defs>
<radialGradient id="uuid-a9da7b2d-3102-4725-93ea-0cda2352c3c6" cx="7.958" cy="7.925" r="7.985" gradientUnits="userSpaceOnUse">
<stop offset=".18" stop-color="#5ea0ef"/>
<stop offset="1" stop-color="#0078d4"/>
</radialGradient>
<linearGradient id="uuid-2be490ce-8f11-4771-88f0-040758b1514f" x1="300.661" y1="1169.257" x2="300.632" y2="1165.546" gradientTransform="translate(-297 -1159)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#ccc"/>
<stop offset="1" stop-color="#fcfcfc"/>
</linearGradient>
<linearGradient id="uuid-4dd8ce3d-a528-40d6-81cd-9a779af9902b" x1="14.251" y1="18" x2="14.251" y2="8.984" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#003067"/>
<stop offset="1" stop-color="#005ba1"/>
</linearGradient>
</defs>
<g>
<path d="m10.126,13.194v-2.922c.004-.333.268-.597.596-.602,1.118-.03,1.469-.275,1.841-.534.372-.259.756-.527,1.688-.527.827,0,1.223.211,1.561.44.266-1.984-.208-4.068-1.484-5.801C11.714-.302,6.721-1.059,3.176,1.558l-.086.057C-.392,4.318-1.026,9.336,1.673,12.822c2.207,2.85,5.958,3.792,9.157,2.564-.416-.659-.704-1.398-.704-2.192Z" fill="url(#uuid-a9da7b2d-3102-4725-93ea-0cda2352c3c6)"/>
<path d="m5.809,6.264c2.256-2.148,5.246-3.351,8.359-3.363-.41-.507-.88-.961-1.401-1.352-1.514.094-3.002.443-4.4,1.033-1.438.619-2.739,1.52-3.825,2.649.523.199.967.561,1.267,1.033Z" fill="#fff" isolation="isolate" opacity=".6"/>
<path d="m1.859,9.478c-.325.799-.587,1.621-.785,2.461.174.301.369.59.584.864.162.212.334.416.516.611.227-1.118.566-2.211,1.013-3.26-.499-.09-.961-.325-1.329-.676Z" fill="#fff" isolation="isolate" opacity=".6"/>
<path d="m2.778,5.212c-.331-.89-.549-1.818-.647-2.762-.394.414-.741.871-1.032,1.363.106.761.285,1.509.535,2.235.294-.382.691-.672,1.144-.836Z" fill="#f2f2f2" isolation="isolate" opacity=".55"/>
<circle cx="3.641" cy="7.626" r="2.561" fill="url(#uuid-2be490ce-8f11-4771-88f0-040758b1514f)"/>
<path d="m7.379,12.315c0-.45.183-.881.507-1.193-.865-.474-1.664-1.062-2.375-1.748-.372.403-.863.676-1.401.78.424.434.879.836,1.361,1.203.601.452,1.245.844,1.923,1.169-.009-.07-.015-.14-.015-.21Z" fill="#f2f2f2" isolation="isolate" opacity=".55"/>
<path d="m11.09,7.861c.084-.366.285-.694.573-.935-1.546-1.126-2.951-2.433-4.185-3.894-.719-.845-1.348-1.764-1.876-2.741-.35.105-.692.237-1.023.394.565,1.064,1.241,2.065,2.017,2.987,1.319,1.578,2.828,2.985,4.494,4.189Z" fill="#f2f2f2" isolation="isolate" opacity=".7"/>
<circle cx="3.641" cy="7.626" r="2.561" fill="#fff"/>
<path d="m10.126,13.194v-2.136c-.293-.255-.671-.415-1.09-.415-.922,0-1.669.748-1.669,1.672s.747,1.672,1.669,1.672c.431,0,.82-.168,1.116-.437-.013-.118-.026-.235-.026-.355Z" fill="#fff"/>
<path d="m11.72,9.55c.393-.102.615-.255.843-.414.372-.259.756-.527,1.688-.527.106,0,.204.004.297.011.036-.141.061-.287.061-.439,0-.981-.794-1.776-1.773-1.776s-1.773.795-1.773,1.776c0,.555.26,1.044.658,1.37Z" fill="#fff"/>
</g>
<path d="m17.77,10.046c-2.317-.061-1.783-1.062-3.519-1.062s-1.203,1.001-3.519,1.062c-.127.002-.229.104-.23.231v2.917c0,2.424,2.978,4.378,3.626,4.772.076.046.171.046.247,0,.647-.396,3.626-2.348,3.626-4.772v-2.917c-.002-.127-.104-.229-.23-.231Z" fill="url(#uuid-4dd8ce3d-a528-40d6-81cd-9a779af9902b)"/>
<path d="m16.812,13.666c-.017-.564-.44-1.032-.999-1.106-.034-.793-.7-1.412-1.494-1.387-.632-.011-1.202.377-1.422.97-.674.082-1.188.644-1.208,1.323.03.767.675,1.366,1.443,1.338.043,0,.086-.002.127-.005h2.336c.021,0,.042-.004.062-.009.624-.004,1.133-.499,1.156-1.123Z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

@@ -0,0 +1,30 @@
<svg id="uuid-11b6e5fc-40a5-405d-9c32-7035b72b9b0a" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
<defs>
<radialGradient id="uuid-cacf3cc5-0a3d-4115-943b-5bd551efadcd" cx="7.957" cy="7.925" r="7.985" gradientUnits="userSpaceOnUse">
<stop offset=".18" stop-color="#5ea0ef"/>
<stop offset="1" stop-color="#0078d4"/>
</radialGradient>
<linearGradient id="uuid-2a25906c-e495-4ebf-b557-92e03673ecb2" x1="300.661" y1="1169.257" x2="300.632" y2="1165.546" gradientTransform="translate(-297 -1159)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#ccc"/>
<stop offset="1" stop-color="#fcfcfc"/>
</linearGradient>
<linearGradient id="uuid-73ce8cf9-4957-4dc1-9af7-dfbfa3d5e4cb" x1="14.251" y1="19.336" x2="14.251" y2="10.32" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#5e9624"/>
<stop offset=".999" stop-color="#76bc2d"/>
</linearGradient>
</defs>
<g>
<path d="m10.126,13.194v-2.922c.004-.333.268-.597.596-.602,1.118-.03,1.469-.275,1.841-.534.372-.259.756-.527,1.688-.527.827,0,1.223.211,1.561.44.266-1.984-.208-4.068-1.484-5.801C11.714-.302,6.721-1.059,3.176,1.558l-.086.057C-.392,4.318-1.026,9.336,1.673,12.822c2.207,2.85,5.958,3.792,9.157,2.564-.416-.659-.704-1.398-.704-2.192Z" fill="url(#uuid-cacf3cc5-0a3d-4115-943b-5bd551efadcd)"/>
<path d="m5.809,6.264c2.256-2.148,5.246-3.351,8.359-3.363-.41-.507-.88-.961-1.401-1.352-1.514.094-3.002.443-4.4,1.033-1.438.619-2.739,1.52-3.825,2.649.523.199.967.561,1.267,1.033Z" fill="#fff" isolation="isolate" opacity=".6"/>
<path d="m1.859,9.478c-.325.799-.587,1.621-.785,2.461.174.301.369.59.584.864.162.212.334.416.516.611.227-1.118.566-2.211,1.013-3.26-.499-.09-.961-.325-1.329-.676Z" fill="#fff" isolation="isolate" opacity=".6"/>
<path d="m2.778,5.212c-.331-.89-.549-1.818-.647-2.762-.394.414-.741.871-1.032,1.363.106.761.285,1.509.535,2.235.294-.382.691-.672,1.144-.836Z" fill="#f2f2f2" isolation="isolate" opacity=".55"/>
<circle cx="3.641" cy="7.626" r="2.561" fill="url(#uuid-2a25906c-e495-4ebf-b557-92e03673ecb2)"/>
<path d="m7.379,12.315c0-.45.183-.881.507-1.193-.865-.474-1.664-1.062-2.375-1.748-.372.403-.863.676-1.401.78.424.434.879.836,1.361,1.203.601.452,1.245.844,1.923,1.169-.009-.07-.015-.14-.015-.21Z" fill="#f2f2f2" isolation="isolate" opacity=".55"/>
<path d="m11.09,7.861c.084-.366.285-.694.573-.935-1.546-1.126-2.951-2.433-4.185-3.894-.719-.845-1.348-1.764-1.876-2.741-.35.105-.692.237-1.023.394.565,1.064,1.241,2.065,2.017,2.987,1.319,1.578,2.828,2.985,4.494,4.189Z" fill="#f2f2f2" isolation="isolate" opacity=".7"/>
<circle cx="3.641" cy="7.626" r="2.561" fill="#fcfcfc"/>
<path d="m10.126,13.194v-2.136c-.293-.255-.671-.415-1.09-.415-.922,0-1.669.748-1.669,1.672s.747,1.672,1.669,1.672c.431,0,.82-.168,1.116-.437-.013-.118-.026-.235-.026-.355Z" fill="#fcfcfc"/>
<path d="m11.72,9.55c.393-.102.615-.255.843-.414.372-.259.756-.527,1.688-.527.106,0,.204.004.297.011.036-.141.061-.287.061-.439,0-.981-.794-1.776-1.773-1.776s-1.773.795-1.773,1.776c0,.555.26,1.044.658,1.37Z" fill="#fcfcfc"/>
</g>
<path d="m17.77,10.046c-2.317-.061-1.783-1.062-3.519-1.062s-1.203,1.001-3.519,1.062c-.127.002-.229.104-.23.231v2.917c0,2.424,2.978,4.378,3.626,4.772.076.046.171.046.247,0,.647-.396,3.626-2.348,3.626-4.772v-2.917c-.002-.127-.104-.229-.23-.231Z" fill="url(#uuid-73ce8cf9-4957-4dc1-9af7-dfbfa3d5e4cb)"/>
<path d="m15.976,12.783l.003-.002c-.033-.029-.074-.045-.118-.045h-.262v-.812c.002-.382-.138-.751-.393-1.036-.244-.285-.603-.447-.978-.44-.375-.005-.732.156-.977.44-.257.283-.398.653-.394,1.036v.812h-.212c-.012,0-.022.005-.033.007-.01.002-.019.002-.028.006-.07.026-.121.091-.122.17v2.097c0,.019.006.036.011.052,0,0,0,0,0,0,.003.008.005.017.008.024.011.028.028.054.052.074l.008-.006c.03.021.064.036.103.037h3.208c.042,0,.078-.017.109-.041l.014.01c.041-.034.065-.085.066-.138v-2.109c0-.055-.027-.103-.065-.136Zm-2.482-.873c.002-.211.083-.414.229-.568.236-.275.65-.307.925-.071.025.022.049.046.071.071.032.035.06.074.085.114.099.131.154.289.159.454v.825s-1.469,0-1.469,0v-.825Z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

@@ -0,0 +1,59 @@
<svg width="96" height="96" viewBox="0 0 96 96" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_98_3087)">
<g clip-path="url(#clip1_98_3087)">
<path d="M50.4537 12.4478C31.927 12.4478 16.8994 30.8113 16.8994 44.4229V86.3461C16.8994 90.0906 20.8042 93.119 25.6134 93.119H75.2856C80.1032 93.119 83.9996 90.084 83.9996 86.3461V37.0891C83.9996 23.4776 68.9804 12.4478 50.4537 12.4478Z" fill="url(#paint0_linear_98_3087)"/>
<path d="M50.4537 12.4478C31.927 12.4478 16.8994 30.8113 16.8994 44.4229V86.3461C16.8994 90.0906 20.8042 93.119 25.6134 93.119H75.2856C80.1032 93.119 83.9996 90.084 83.9996 86.3461V37.0891C83.9996 23.4776 68.9804 12.4478 50.4537 12.4478Z" fill="url(#paint1_linear_98_3087)" fill-opacity="0.6"/>
<path d="M50.4537 12.4478C31.927 12.4478 16.8994 30.8113 16.8994 44.4229V86.3461C16.8994 90.0906 20.8042 93.119 25.6134 93.119H75.2856C80.1032 93.119 83.9996 90.084 83.9996 86.3461V37.0891C83.9996 23.4776 68.9804 12.4478 50.4537 12.4478Z" fill="url(#paint2_radial_98_3087)" fill-opacity="0.5"/>
<path d="M42.0644 7.61354C28.1709 15.6294 16.9043 30.2449 16.9043 47.3401L16.8994 86.7313C16.8994 93.119 24.8106 94.1837 28.4684 92.0544L60.689 72.8718C64.2978 70.7898 67.2245 66.2424 67.2245 62.7124V32.4353C67.2245 13.2719 55.9579 -0.397553 42.0644 7.61354Z" fill="url(#paint3_radial_98_3087)"/>
<path d="M42.0644 7.61354C28.1709 15.6294 16.9043 30.2449 16.9043 47.3401L16.8994 86.7313C16.8994 93.119 24.8106 94.1837 28.4684 92.0544L60.689 72.8718C64.2978 70.7898 67.2245 66.2424 67.2245 62.7124V32.4353C67.2245 13.2719 55.9579 -0.397553 42.0644 7.61354Z" fill="url(#paint4_radial_98_3087)" fill-opacity="0.25"/>
<path d="M42.0644 7.61354C28.1709 15.6294 16.9043 30.2449 16.9043 47.3401L16.8994 86.7313C16.8994 93.119 24.8106 94.1837 28.4684 92.0544L60.689 72.8718C64.2978 70.7898 67.2245 66.2424 67.2245 62.7124V32.4353C67.2245 13.2719 55.9579 -0.397553 42.0644 7.61354Z" fill="url(#paint5_radial_98_3087)" fill-opacity="0.25"/>
<path d="M42.0644 7.61354C28.1709 15.6294 16.9043 30.2449 16.9043 47.3401L16.8994 86.7313C16.8994 93.119 24.8106 94.1837 28.4684 92.0544L60.689 72.8718C64.2978 70.7898 67.2245 66.2424 67.2245 62.7124V32.4353C67.2245 13.2719 55.9579 -0.397553 42.0644 7.61354Z" fill="url(#paint6_radial_98_3087)" fill-opacity="0.25"/>
<path d="M42.0644 7.61354C28.1709 15.6294 16.9043 30.2449 16.9043 47.3401L16.8994 86.7313C16.8994 93.119 24.8106 94.1837 28.4684 92.0544L60.689 72.8718C64.2978 70.7898 67.2245 66.2424 67.2245 62.7124V32.4353C67.2245 13.2719 55.9579 -0.397553 42.0644 7.61354Z" fill="url(#paint7_linear_98_3087)" fill-opacity="0.6"/>
<path d="M32.4476 3.65882C21.9186 7.542 12.0053 24.99 12.0053 44.002L12 61.0396C12 65.2258 15.1748 66.6174 19.0896 64.1484L36.5713 53.3864C41.5211 50.3393 44.5633 44.7574 44.5633 38.7224V21.2139C44.5633 8.18931 39.5788 1.02875 32.4476 3.65882Z" fill="url(#paint8_linear_98_3087)"/>
</g>
</g>
<defs>
<linearGradient id="paint0_linear_98_3087" x1="55.5758" y1="66.7305" x2="81.9176" y2="88.7778" gradientUnits="userSpaceOnUse">
<stop stop-color="#224F87"/>
<stop offset="1" stop-color="#0055C6"/>
</linearGradient>
<linearGradient id="paint1_linear_98_3087" x1="82.9438" y1="52.7834" x2="71.5177" y2="54.2164" gradientUnits="userSpaceOnUse">
<stop stop-color="#0059C5"/>
<stop offset="1" stop-color="#0059C5" stop-opacity="0"/>
</linearGradient>
<radialGradient id="paint2_radial_98_3087" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(36.4448 50.628) rotate(51.4758) scale(40.3141 36.3696)">
<stop stop-color="#041642"/>
<stop offset="1" stop-color="#041642" stop-opacity="0"/>
</radialGradient>
<radialGradient id="paint3_radial_98_3087" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(50.6602 5.27905) rotate(101.468) scale(52.7905 58.7614)">
<stop stop-color="#66DFFF"/>
<stop offset="1" stop-color="#0296E6"/>
</radialGradient>
<radialGradient id="paint4_radial_98_3087" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(28.4736 31.3316) scale(25.9066 40.722)">
<stop/>
<stop offset="1" stop-opacity="0"/>
</radialGradient>
<radialGradient id="paint5_radial_98_3087" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(38.7033 30.6662) rotate(-3.01258) scale(13.5717 37.6157)">
<stop/>
<stop offset="1" stop-opacity="0"/>
</radialGradient>
<radialGradient id="paint6_radial_98_3087" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(20.1037 61.8066) rotate(63.4736) scale(13.3863 29.831)">
<stop/>
<stop offset="1" stop-opacity="0"/>
</radialGradient>
<linearGradient id="paint7_linear_98_3087" x1="43.2204" y1="83.0991" x2="27.1104" y2="61.6996" gradientUnits="userSpaceOnUse">
<stop stop-color="#0086E2"/>
<stop offset="1" stop-color="#0086E2" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint8_linear_98_3087" x1="-7.66242" y1="25.7423" x2="10.5321" y2="56.9523" gradientUnits="userSpaceOnUse">
<stop stop-color="#CDFAFF"/>
<stop offset="1" stop-color="#45DDFB"/>
</linearGradient>
<clipPath id="clip0_98_3087">
<rect width="96" height="96" fill="white"/>
</clipPath>
<clipPath id="clip1_98_3087">
<rect width="96" height="96" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

@@ -0,0 +1,30 @@
<svg id="uuid-0bbb5b12-3243-469f-a125-16e9fd0c10bb" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
<defs>
<linearGradient id="uuid-0af6b584-dd4c-4308-9282-d2a7c9e792b7" x1="8.985" y1="13.416" x2="8.985" y2=".837" gradientUnits="userSpaceOnUse">
<stop offset=".089" stop-color="#225086"/>
<stop offset=".458" stop-color="#0055c5"/>
</linearGradient>
<linearGradient id="uuid-7632880e-fcbf-4182-861a-db42fad415fd" x1="15.2" y1="17.152" x2="15.2" y2="8.114" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#0294e4"/>
<stop offset=".192" stop-color="#23aced"/>
<stop offset=".398" stop-color="#40c1f4"/>
<stop offset=".603" stop-color="#55d0fa"/>
<stop offset=".805" stop-color="#61d9fd"/>
<stop offset="1" stop-color="#6df"/>
</linearGradient>
</defs>
<g>
<path d="m11.95,10.924c0-1.797,1.458-3.26,3.25-3.26,1.17,0,2.197.623,2.77,1.556V1.437c0-.331-.268-.6-.6-.6H.6c-.331,0-.6.268-.6.6v11.379c0,.331.268.6.6.6h12.509c-.73-.617-1.159-1.529-1.159-2.492Z" fill="url(#uuid-0af6b584-dd4c-4308-9282-d2a7c9e792b7)"/>
<g>
<path d="m6.616,10.125c.259.009.477-.193.486-.452,0-.005,0-.009,0-.014.002-.019.002-.038,0-.058-.193-1.532-1.063-2.771-2.723-2.771s-2.568,1.054-2.748,2.759c-.026.269.17.508.438.535h4.546Z" fill="#6df"/>
<path d="m4.398,7.194c-.288-.003-.569-.088-.811-.244l.811,2.145.82-2.13c-.247.151-.531.23-.82.229Z" fill="#f2f2f2"/>
<circle cx="4.388" cy="5.661" r="1.533" fill="#6df"/>
</g>
<rect x="7.828" y="4.128" width="7.631" height="1.483" rx=".741" ry=".741" fill="#6df"/>
<path d="m13.267,7.823h-4.697c-.409,0-.741.332-.741.741s.332.741.741.741h3.211c.284-.592.712-1.144,1.486-1.483Z" fill="#6df"/>
</g>
<path d="m18,10.924c0-1.552-1.254-2.81-2.8-2.81s-2.8,1.258-2.8,2.81c0,.948.469,1.784,1.185,2.293l-.18,3.598c-.009.171.123.316.293.325.088.004.174-.029.236-.092l1.217-.771,1.208.782c.12.122.316.124.438.005.063-.061.096-.146.093-.234l-.139-3.566c.753-.504,1.25-1.363,1.25-2.339Z" fill="url(#uuid-7632880e-fcbf-4182-861a-db42fad415fd)"/>
<g id="uuid-a7e8402a-60cf-4e4a-910f-8d3e78ed18c9">
<path d="m14.652,12.251c-.089,0-.174-.035-.237-.098l-.971-.971c-.125-.136-.116-.347.019-.472.128-.118.325-.118.453,0l.735.737,1.8-1.801c.136-.125.347-.116.472.019.118.128.118.325,0,.453l-2.036,2.036c-.063.062-.148.097-.236.096Z" fill="#fff"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -0,0 +1 @@
<svg id="a76a0103-ce03-4d58-859d-4c27e02925d2" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><defs><linearGradient id="efeb8e96-2af0-4681-9a6a-45f9b0262f19" x1="-6518.78" y1="1118.86" x2="-6518.78" y2="1090.06" gradientTransform="matrix(0.5, 0, 0, -0.5, 3267.42, 559.99)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#5ea0ef" /><stop offset="0.18" stop-color="#589eed" /><stop offset="0.41" stop-color="#4897e9" /><stop offset="0.66" stop-color="#2e8ce1" /><stop offset="0.94" stop-color="#0a7cd7" /><stop offset="1" stop-color="#0078d4" /></linearGradient></defs><title>Icon-identity-232</title><path d="M5.67,10.61H10v4.32H5.67Zm-5-5.76H5V.53H1.23a.6.6,0,0,0-.6.6Zm.6,10.08H5V10.61H.63v3.72A.6.6,0,0,0,1.23,14.93Zm-.6-5H5V5.57H.63Zm10.08,5h3.72a.6.6,0,0,0,.6-.6V10.61H10.71Zm-5-5H10V5.57H5.67Zm5,0H15V5.57H10.71Zm0-9.36V4.85H15V1.13a.6.6,0,0,0-.6-.6Zm-5,4.32H10V.53H5.67Z" fill="url(#efeb8e96-2af0-4681-9a6a-45f9b0262f19)" /><polygon points="17.37 10.7 17.37 15.21 13.5 17.47 13.5 12.96 17.37 10.7" fill="#32bedd" /><polygon points="17.37 10.7 13.5 12.97 9.63 10.7 13.5 8.44 17.37 10.7" fill="#9cebff" /><polygon points="13.5 12.97 13.5 17.47 9.63 15.21 9.63 10.7 13.5 12.97" fill="#50e6ff" /><polygon points="9.63 15.21 13.5 12.96 13.5 17.47 9.63 15.21" fill="#9cebff" /><polygon points="17.37 15.21 13.5 12.96 13.5 17.47 17.37 15.21" fill="#50e6ff" /></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,8 @@
Herunterladen von Azure-Symbolen zur Verwendung in Architekturdiagrammen und Dokumentationen
https://learn.microsoft.com/de-de/azure/architecture/icons/
https://arch-center.azureedge.net/icons/Azure_Public_Service_Icons_V23.zip
Microsoft Entra-Architektursymbole
Erlaubt für Architekturdiagramme, Schulungsmaterialien oder in Dokumentationen
https://learn.microsoft.com/de-de/entra/architecture/architecture-icons
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 425.196850393701425 59.527559055117308"><path d="m60.293984607886159,50.769293013130664c8.922085244085793-5.90894112510432,2.597510115368095-15.968015131942593-1.841832000440263-21.080502289770266-.962305207704048-1.104701746114188-.307094671095001-1.620484383381154,1.198667759555974-.794515764901917,7.032853155409612,3.857120845534155,21.932207291582927,11.951225666169194,19.629745551583255,19.496181327776867-1.77912256691161,5.843802805071391-11.053347286466305,5.940295841861371-20.420016898639005,3.368497575585934l-.14551238270451-.016879534525287.14551238270451-.084422206860836c.477558342503471-.274954859722129,1.000112420952064-.602143046497076,1.433435587940039-.888359107304495h0Z" fill="#ef7d00" stroke-width="0"/><path d="m58.723893486027919,51.738050717322039s-11.792955495717251,7.412274669248291-32.605274366960657,7.412274669248291c-8.06348613008231,0-14.851929513702089-1.234806646702054-17.722799765328091-4.059061904712507-3.023595691251103-2.973766716497266-4.663633837730231-7.983897162041103-4.663633837730231-12.590464433895249,0-3.947333125281148,1.640038146479128-7.265977191917045,5.056769973368318-7.265977191917045,8.776572861384921,0,36.110427476475706,13.903289859388678,49.93493799665066,16.503228861276511h0Z" fill="#cf022b" stroke-width="0"/><path d="m19.422620628053664,8.758143370950165c-8.922085244093978,5.908597646209273-2.596700486548798,15.968015131932589,1.841832000432078,21.080600426611454.962305207699501,1.104603609266633.307904299943402,1.62041078074617-1.197858130716668.794515764885546C13.033741342349458,26.776040580090012-1.865612793805667,18.681690417384743.436848946185819,11.136980097850028c1.779122566906153-5.843483860380729,11.053322752266467-5.940050499790232,20.419207269799699-3.368816520284781l.146297477333974.017198479225044-.146297477333974.084839288377225c-.476748713675079.274758586072494-1.000112420955702.60140702028184-1.433435587931854.88794202578265h0Z" fill="#ef7d00" stroke-width="0"/><path d="m20.9927117499019,7.789312064143814S32.785667245631885.377233668550616,53.598795745702773.377233668550616c8.063486130077763,0,14.851929513703908,1.234953851946557,17.722775231131891,4.058939233677847,3.023620225444574,2.973913921728126,4.66365837192734,7.983651819962688,4.66365837192734,12.590611639137933,0,3.947406727897032-1.640038146482766,7.265977191915226-5.056769973371047,7.265977191915226-8.776572861384921,0-36.111237105314103-13.903216256770065-49.935747625489057-16.503449669137808h0Z" fill="#cf022b" stroke-width="0"/><path d="m175.46730934423249,29.92167399203845c-7.058291915608606,0-10.555369198777953-4.485328629730247-10.555369198777953-4.485328629730247v12.418041986202297h-5.439505080450544V.389427381112h5.145917753170579l.293587327279965,3.66455045787734S168.335620596815716.001111137908993,175.406628868478947.001111137908993c6.221446336843655,0,15.179396058821112,3.171875436868504,15.179396058821112,14.845649032890833,0,11.673209208499429-8.059841642842912,15.074913821238624-15.118715583067569,15.074913821238624h0Zm-.294742557937752-24.99176673931288c-5.463200537271405,0-10.260626640840201,3.097376285703831-10.260626640840201,9.859885053890139,0,6.762261848655726,4.219493294497624,10.143736696624728,10.202247807880667,10.143736696624728,3.133558816155528,0,9.747995230255583-1.271441597674311,9.747995230255583-10.028054894419256,0-8.757054224476633-6.594215467879621-9.975566856095611-9.689616397296049-9.975566856095611h0Zm36.606844034394271,9.916852918074255c0-11.082313123853964,8.957958540529035-14.846760170799826,15.182870569425177-14.846760170799826,7.067542579625297,0,10.492951467726016,4.05397783898934,10.492951467726016,4.05397783898934l.29129450300934-3.66455045787734h5.147037709646611v29.525879614341648h-5.134921015314831l-.30341119734112-3.900446799464589s-3.524247250592452,3.906813796049391-10.556533248012784,3.906813796049391c-7.058283097057938,0-15.119288789138409-4.099851961190325-15.119288789138409-15.074913821238624h0Zm5.725570180450632.058713938021356c0,8.026701513805165,6.612134771299679,10.028054894419256,9.748577254866177,10.028054894419256,5.982172488775177,0,10.201674601834384-3.381474847969002,10.201674601834384-10.143736696624728,0-6.763090792807816-4.797434922136745-9.859885053890139-10.259471410165133-9.859885053890139-3.097147003254577,0-9.690780446535427,1.820714103560931-9.690780446535427,9.975566856095611h0Zm-5.314096412284016-9.451215586149374V.463926532279402c-5.562594468691714-.508513145477991-9.468261852613068.824534876218422-12.511086558157331,4.00316532607485l-.29127686591346-4.0647188387602h-5.344714434622801v29.493303872820434h5.635991300536261v-15.281409101045938c0-4.263418516103229,3.436970013483915-9.668540051277887,12.511086558157331-9.16000926869674h0Zm-102.303119767699172,6.849953557847584c-5.671530076464478-1.013057941288025-11.246003138526248-1.720799877382888-11.246003138526248-4.364955356365499,0-1.722528314125157,1.709Line truncated

After

Width:  |  Height:  |  Size: 14 KiB