Files

842 lines
23 KiB
Markdown
Raw Permalink Normal View History

# 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
```