Day-2-Betriebshandbuch
Einleitung
Das helmfile apply ist fehlerfrei durchgelaufen. Die Pods laufen, der Ingress liefert Seiten aus, und Ihre Nutzer melden sich über DFN-AAI via Keycloak an – der erste Tag ist geschafft.
Der produktive Betrieb (Day 2) beginnt jetzt. Dieses Handbuch beschreibt den vollständigen Betriebslebenszyklus von openDesk Edu nach der Erstinstallation: Monitoring, Backup-Verifikation, Zertifikatserneuerung, Updates, Skalierung und die unvermeidliche Fehlersuche. Es richtet sich an IT-Mitarbeiter von Hochschulen und Rechenzentren, die einen Kubernetes-Cluster betreiben und konkrete Kommando-Beispiele benötigen – keine abstrakten Konzepte.
Jede Umgebung ist anders. Ihr Cluster-Topologie, Ihre Storage-Klasse, Ihr Ingress-Controller und Ihr Monitoring-Stapel werden von der Referenzinstallation abweichen. Passen Sie die nachfolgenden Kommandos entsprechend an.
Monitoring der Plattform
Health-Endpunkte
openDesk Edu stellt einen zentralen Health-Endpunkt unter https://opendesk-edu.de/api/health bereit (ersetzen Sie die Domain durch Ihre tatsächliche Adresse). Der Endpunkt liefert eine JSON-Übersicht über den Status aller Komponenten:
curl -s https://opendesk-edu.de/api/health | jq .
Eine gesunde Antwort enthält den Status "ok": true sowie einen Eintrag pro Dienst. Meldet ein Dienst einen Fehler, gibt der Endpunkt HTTP 503 zurück.
Die einzelnen Dienste exponieren eigene Health-Checks:
| Dienst | Health-Check-Pfad | Typ |
|---|---|---|
| Keycloak | /realms/master/.well-known/uma2-configuration |
HTTP-200-Prüfung |
| Nextcloud | /status.php |
HTTP-200-Prüfung |
| OpenCloud | /health |
HTTP-200-Prüfung |
| ILIAS | /Services/HealthCheck/health_check.php |
HTTP 200 |
| Moodle | /admin/tool/health/index.php |
HTTP 200 |
| Grommunio | /grommunio-api/health |
HTTP-200-Prüfung |
Ein einfaches Smoke-Test-Skript:
for svc in keycloak nextcloud opencloud ilias moodle grommunio; do
status=$(curl -s -o /dev/null -w "%{http_code}" "https://opendesk-edu.de/$svc/health")
echo "$svc: $status"
done
Prometheus / Grafana-Integration
Der openDesk Edu-Stack enthält optionale Prometheus- und Grafana-Konfigurationen. Im aktiven Zustand liefern sie:
- Kubernetes-Knotenmetriken (CPU, Arbeitsspeicher, Festplattenauslastung)
- Pod-Ressourcennutzung je Namespace
- Keycloak-Metriken (aktive Sitzungen, Anmelderate, Token-Ausstellung)
- PVC-Auslastung in Prozent der Kapazität
Prüfen, ob Prometheus Targets sammelt:
kubectl -n opendesk-monitoring port-forward svc/prometheus-operated 9090:9090 &
curl -s http://localhost:9090/api/v1/targets | jq '.data.activeTargets | length'
Wenn Grafana deployt ist, importieren Sie das openDesk-Edu-Dashboard aus dem GitHub-Repository des Projekts. Die Dashboard-ID wird in den Release-Notes veröffentlicht.
kubectl-basiertes Monitoring (ohne Prometheus)
Falls Sie Prometheus nicht einsetzen, geben diese Kommandos den notwendigen Überblick:
Pod-Neustarts:
kubectl -n opendesk-edu get pods --field-selector=status.phase!=Running
kubectl -n opendesk-edu get pods -o wide | grep -v Running
PVC-Auslastung:
kubectl -n opendesk-edu get pvc
for pvc in $(kubectl -n opendesk-edu get pvc -o name); do
echo "--- $pvc ---"
kubectl -n opendesk-edu exec deploy/ein-pod -- df -h | grep /data
done
Zertifikatsablauf:
kubectl -n opendesk-edu get certificate -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.notAfter}{"\n"}{end}'
Keycloak-Sitzungsanzahl (erfordert Keycloak-Admin-CLI):
kubectl -n opendesk-edu exec deploy/keycloak -- \
/opt/keycloak/bin/kcadm.sh get sessions -r master --no-config \
--server http://localhost:8080 --realm master \
--user "$KC_ADMIN" --password "$KC_PASSWORD"
Benachrichtigungen
Konfigurieren Sie für proaktives Monitoring Alarme im Prometheus Alertmanager. Der openDesk-Edu-Chart enthält Alert-Regeln für:
- Pod-Crashlooping
- PVC-Auslastung > 80 %
- Zertifikatsablauf < 30 Tage
- Keycloak-Ausfall
Alertmanager kann weiterleiten an:
- Matrix-Webhook: Richten Sie einen Matrix-Bot-Raum ein und setzen Sie
alertmanager.config.receivers[].webhook_configsauf Ihre Matrix-Webhook-URL. - E-Mail: Nutzen Sie den eingebauten E-Mail-Empfänger mit dem SMTP-Relay Ihrer Hochschule.
Ohne Alertmanager lässt sich ein einfacher Cron-Job einrichten, der den Health-Endpunkt prüft und bei Fehlern eine Matrix-Nachricht sendet:
#!/bin/bash
HEALTH=$(curl -s -o /dev/null -w "%{http_code}" https://opendesk-edu.de/api/health)
if [ "$HEALTH" != "200" ]; then
curl -X POST -H "Content-Type: application/json" \
-d '{"msgtype":"m.text","body":"openDesk Edu Health-Check FEHLGESCHLAGEN"}' \
"https://matrix.hochschule.de/_matrix/client/v3/rooms/!roomid:server/send/m.room.message?access_token=$TOKEN"
fi
Backup-Verifikation und Wiederherstellung
Funktionsweise von k8up / restic
Die Sicherung erfolgt über den k8up-Operator, der restic-Backups auf einen S3-kompatiblen Speicher plant. Der Standard-Zeitplan wird in den helmfile-Werten definiert:
k8up:
backup:
schedule: "0 2 * * *" # täglich um 02:00 Uhr
prometheus: # Backup-Metriken exponieren
backend: s3
s3:
endpoint: s3.hochschule.de
bucket: opendesk-backup
Jeder PersistentVolumeClaim (PVC) eines Dienstes wird über eine Schedule-Custom-Resource gesichert. Der Operator erstellt einen Job, der den PVC mountet und restic backup darauf ausführt.
Überprüfung der Backup-Integrität
Vertrauen Sie keinem Backup, das Sie nicht verifiziert haben. Führen Sie diese Prüfungen wöchentlich durch:
Snapshots auflisten:
kubectl -n opendesk-edu exec deploy/k8up -- \
restic -r s3:s3.hochschule.de/opendesk-backup snapshots \
--password-file /etc/restic/password
Repository-Integrität prüfen:
kubectl -n opendesk-edu exec deploy/k8up -- \
restic -r s3:s3.hochschule.de/opendesk-backup check \
--password-file /etc/restic/password \
--read-data-subset=5% # prüft 5 % der Daten; quartalsweise --read-data nutzen
Bestimmten Snapshot verifizieren:
kubectl -n opendesk-edu exec deploy/k8up -- \
restic -r s3:s3.hochschule.de/opendesk-backup \
verify --password-file /etc/restic/password <snapshot-id>
Schritt-für-Schritt-Wiederherstellung
Vor jeder Wiederherstellung muss der betroffene Dienst gestoppt werden, um Datenkorruption zu vermeiden. Skalieren Sie das Deployment auf null Replicas:
kubectl -n opendesk-edu scale deploy/<dienst> --replicas=0
Keycloak-Datenbank (PostgreSQL)
-
Letzten Snapshot mit Keycloak-Daten identifizieren:
kubectl -n opendesk-edu exec deploy/k8up -- \ restic -r s3:... snapshots --path /data/keycloak/postgresql \ --password-file /etc/restic/password --latest 1 -
Daten auf einen temporären PVC wiederherstellen:
kubectl -n opendesk-edu apply -f - <<EOF apiVersion: v1 kind: PersistentVolumeClaim metadata: name: keycloak-db-restore spec: storageClassName: ihre-storage-class accessModes: [ReadWriteOnce] resources: requests: storage: 10Gi EOF -
Restore-Job starten:
kubectl -n opendesk-edu apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: keycloak-db-restore spec: containers: - name: restic image: restic/restic:latest command: ["restic", "restore", "latest", "--target", "/restore", "--path", "/data/keycloak/postgresql"] env: - name: RESTIC_REPOSITORY value: s3:... - name: RESTIC_PASSWORD valueFrom: secretKeyRef: name: k8up-restic-secret key: password volumeMounts: - mountPath: /restore name: restore-target volumes: - name: restore-target persistentVolumeClaim: claimName: keycloak-db-restore restartPolicy: Never EOF -
Bestehenden Keycloak-PostgreSQL-Pod stoppen, alten PVC löschen und aus den wiederhergestellten Daten neu erstellen:
kubectl -n opendesk-edu scale statefulset keycloak-postgresql --replicas=0 kubectl -n opendesk-edu delete pvc data-keycloak-postgresql-0 # Neuen PVC mit gleichem Namen und gleicher StorageClass anlegen # Daten mit temporärem Pod vom Restore-PVC kopieren kubectl -n opendesk-edu scale statefulset keycloak-postgresql --replicas=1 -
Prüfen, ob Keycloak startet und Anmeldungen akzeptiert.
Nextcloud / OpenCloud-Dateien
Das Vorgehen ist analog – den Nextcloud-PVC aus dem letzten Snapshot wiederherstellen. Anschließend die Nextcloud-Wartungsreparatur ausführen:
kubectl -n opendesk-edu exec deploy/nextcloud -- \
php occ maintenance:repair
Bei OpenCloud den Integritätscheck durchführen:
kubectl -n opendesk-edu exec deploy/opencloud -- \
opencloud files:check
ILIAS / Moodle-LMS-Daten
ILIAS speichert Daten in mehreren PVCs (Dateien, ilias-data). Diese in der richtigen Reihenfolge wiederherstellen:
- Datenbank (MySQL/MariaDB) – gleiches Vorgehen wie bei PostgreSQL, angepasst auf MySQL
- Dateisystemdaten –
restic restoreauf die ILIAS-Daten-PVCs
Nach der Wiederherstellung den ILIAS-Cache leeren:
kubectl -n opendesk-edu exec deploy/ilias -- \
php ilias.php resetPassword
kubectl -n opendesk-edu exec deploy/ilias -- \
php setup/setup.php --update=keep,no-goto
Für Moodle:
kubectl -n opendesk-edu exec deploy/moodle -- \
php admin/cli/purge_caches.php
Grommunio-Mailboxen
Grommunio speichert Maildaten im eigenen PVC. Diesen wiederherstellen und dann prüfen:
kubectl -n opendesk-edu exec deploy/grommunio -- \
grommunio-admin-mailbox list
Zur Wiederherstellung einzelner Postfächer die Grommunio-Export-/Import-Tools nutzen:
kubectl -n opendesk-edu exec deploy/grommunio -- \
grommunio-admin-mailbox-export -u user@hochschule.de -f /tmp/backup.mbox
kubectl -n opendesk-edu exec deploy/grommunio -- \
grommunio-admin-mailbox-import -u user@hochschule.de -f /tmp/backup.mbox
Wiederherstellungstests in einer Staging-Umgebung
Mindestens einmal pro Quartal sollte eine vollständige Wiederherstellungsübung in einem Staging-Cluster durchgeführt werden. Die Staging-Umgebung sollte die Produktionstopologie abbilden (Storage-Klasse, Namespace-Struktur, Ingress).
Ablauf:
- Neuen openDesk-Edu-Stack im Staging-Namespace deployen:
helmfile -e staging sync. - Alle Dienste auf null Replicas skalieren.
- Sämtliche PVCs aus den aktuellsten Produktions-Snapshots wiederherstellen.
- Dienste hochskalieren.
- Anmeldeabläufe, Dateizugriff, Mail-Zustellung und LMS-Kursinhalte prüfen.
- Abweichungen dokumentieren und dieses Handbuch aktualisieren.
Zertifikatsmanagement
Funktionsweise der Zertifikatserneuerung
openDesk Edu kann TLS-Zertifikate entweder über openDesk Certificates (Bundesdruckerei, der Standard für deutsche Hochschulen) oder Let's Encrypt beziehen. Beide Verfahren nutzen Cert-manager mit dem entsprechenden Issuer.
Der Zertifikatsaussteller wird in den helmfile-Werten konfiguriert:
global:
certificates:
issuer: letsencrypt-prod # oder opendesk-ca
Cert-manager erneuert Zertifikate automatisch vor Ablauf. Standardmäßig beginnen die Erneuerungsversuche 30 Tage vor Ablauf.
Prüfung des Zertifikatsablaufs
# Alle Zertifikate mit Ablaufdatum auflisten
kubectl -n opendesk-edu get certificate -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.notAfter}{"\n"}{end}'
# Ablauf in Tagen (erfordert jq)
kubectl -n opendesk-edu get certificate -o json | \
jq -r '.items[] | "\(.metadata.name): \(.status.notAfter)"'
Auch das tatsächlich vom Ingress ausgelieferte TLS-Zertifikat lässt sich prüfen:
openssl s_client -connect opendesk-edu.de:443 -servername opendesk-edu.de \
</dev/null 2>/dev/null | openssl x509 -noout -dates
Fehlerbehebung bei fehlgeschlagenen Erneuerungen
Cert-manager-Zertifikatsstatus:
kubectl -n opendesk-edu describe certificate <name>
kubectl -n opendesk-edu describe certificaterequest
kubectl -n opendesk-edu get order
kubectl -n opendesk-edu get challenge
Häufige Fehlerursachen:
| Symptom | Wahrscheinliche Ursache | Lösung |
|---|---|---|
Order failed: DNS01 error |
DNS-Verzögerung (neue Domain) | 5–10 Minuten warten, Order-Ressource löschen, dann erfolgt erneuter Versuch |
rateLimited |
Let's Encrypt-Rate-Limit erreicht | cert-manager-Logs prüfen; 1 Stunde warten |
Challenge not ready |
Ingress antwortet noch nicht auf HTTP-01-Challenge | Ingress-Controller-Status und NetworkPolicy prüfen |
Certificate not issued, issuer not ready |
Let's Encrypt-Account nicht registriert | Issuer/ClusterIssuer-Status prüfen |
Bei openDesk Certificates (Bundesdruckerei): Wenden Sie sich bei ausstellerseitigen Problemen an das Bundesdruckerei-Supportportal. Geben Sie den Zertifikatsnamen und die Fehlermeldung aus kubectl describe certificate an.
Manuelle Zertifikatserneuerung
Falls die automatische Erneuerung fehlschlägt und ein Zertifikat dringend benötigt wird:
# Altes Zertifikat löschen, um Neuausstellung zu erzwingen
kubectl -n opendesk-edu delete certificate <name>
# Certificate-Manifest erneut einspielen (Cert-manager legt es neu an)
kubectl -n opendesk-edu apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: opendesk-edu-tls
namespace: opendesk-edu
spec:
secretName: opendesk-edu-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- opendesk-edu.de
- "*.opendesk-edu.de"
EOF
Aktualisierung von Komponenten
Sicheres Update-Verfahren
Der empfohlene Update-Pfad:
# 1. Änderungen prüfen
helmfile diff
# 2. Backup erstellen (k8up on-demand)
kubectl -n opendesk-edu apply -f - <<EOF
apiVersion: k8up.io/v1
kind: Backup
metadata:
name: pre-update-backup
namespace: opendesk-edu
spec:
failedJobsHistoryLimit: 1
successfulJobsHistoryLimit: 1
EOF
# 3. Update einspielen
helmfile apply
# 4. Rollout überwachen
kubectl -n opendesk-edu rollout status deploy/<dienst>
Einzelne Charts vs. vollständigen Stack aktualisieren
Für ein einzelnes Update (z. B. ein Keycloak-Patch-Release):
helmfile -l app=keycloak diff
helmfile -l app=keycloak apply
Für ein vollständiges Stack-Update (z. B. monatliches Release):
helmfile diff
helmfile apply
Prüfung auf Breaking Changes vor dem Update
Vor dem Update einer Komponente:
- Release Notes von openDesk Edu auf GitHub für jede neue Version lesen.
- Upstream-Chart-Upgrade-Hinweise prüfen – besonders bei Keycloak (Migrationsskripte bei Major-Versionen), PostgreSQL (Minor-Upgrades können Replikations-Slots invalidieren) und Grommunio (DB-Schema-Migrationen).
- Im Staging testen – die neue Version in einem Staging-Namespace deployen und alle Dienstinteraktionen prüfen.
Wichtige Versionskompatibilitäten:
| Komponente | Breaking Change ab | Maßnahme |
|---|---|---|
| Keycloak | Major-Versionssprung (z. B. 24 → 25) | kcadm.sh update-Migration ausführen, SAML-/OpenID-Konfiguration prüfen |
| PostgreSQL | Major-Version (15 → 16) | pg_upgrade oder Dump/Restore erforderlich |
| Grommunio | DB-Schema-Änderung | Release Notes auf Migrationskommandos prüfen |
| Nextcloud | Major-Version (28 → 29) | occ upgrade nach dem Deployment ausführen |
Rollback-Strategie
Helm-Rollback (einzelnes Chart):
helm -n opendesk-edu rollback keycloak 1
Helmfile-Rollback (gesamter Stack): Helmfile hat keinen eingebauten Rollback-Befehl. Empfohlenes Vorgehen:
# Auf vorherigen helmfile-Stand mit git zurückgehen
git revert HEAD
git push
helmfile apply
Alternativ: Die zuletzt verwendeten Helm-Chart-Versionen nachverfolgen:
helm -n opendesk-edu list --all
helm -n opendesk-edu rollback <release> <revision>
Häufige Fehlermodi
Keycloak-Datenbankverbindung verloren
Symptome: Nutzer können sich nicht anmelden; Keycloak gibt 500-Fehler zurück; Logs zeigen connection refused oder pq: role "keycloak" does not exist.
Fehlersuche:
kubectl -n opendesk-edu logs deploy/keycloak --tail=50
kubectl -n opendesk-edu exec deploy/keycloak-postgresql -- pg_isready
kubectl -n opendesk-edu get pvc data-keycloak-postgresql-0
Lösung:
- PostgreSQL ausgefallen: PVC- und Pod-Status prüfen.
- PostgreSQL läuft, aber Keycloak kann keine Verbindung herstellen: Die Umgebungsvariable
KC_DB_URLim Keycloak-Deployment mit dem PostgreSQL-Service-Namen abgleichen. - Datenbank korrupt: Aus dem letzten k8up-Backup wiederherstellen.
Pod steckt in CrashLoopBackOff
# Absturzursache ermitteln
kubectl -n opendesk-edu logs <pod-name> --previous
# Events prüfen
kubectl -n opendesk-edu get events --field-selector involvedObject.name=<pod-name>
# Häufige Ursachen:
# - OOM: Memory-Limits erhöhen oder resources.requests.memory hinzufügen
# - Konfigurationsfehler: Fehlerhaftes ConfigMap/YAML, mit kubectl describe prüfen
# - PVC nicht gefunden: Existenz und Bindung des PVC prüfen
# - Init-Container-Fehler: Init-Container-Logs separat prüfen
PVC läuft voll
Auslastung überwachen:
kubectl -n opendesk-edu get pvc
kubectl -n opendesk-edu top pod --containers
Für eine detailliertere Ansicht in einen Pod einsteigen:
kubectl -n opendesk-edu exec deploy/nextcloud -- df -h /var/www/html
Lösung:
- Identifizieren, welcher Dienst wächst: Nextcloud-Dateien, Grommunio-Mails, ILIAS-Uploads und PostgreSQL-WAL sind häufige Verursacher.
- Bereinigen: alte Daten archivieren, Aufbewahrungsfristen aktivieren (z. B. Nextcloud-Papierkorb-Autolöschung).
- PVC erweitern: PVC bearbeiten, um den Speicher zu vergrößern (erfordert StorageClass mit
allowVolumeExpansion: true).
NetworkPolicy blockiert Kommunikation zwischen Diensten
Symptome: Dienst A erreicht Dienst B nicht (z. B. Keycloak erreicht LDAP nicht oder ILIAS keine Verbindung zur Datenbank). Verbindungen hängen oder time out.
Fehlersuche:
# Nach NetworkPolicies im Namespace suchen
kubectl -n opendesk-edu get networkpolicies
# Konnektivität von einem Pod testen
kubectl -n opendesk-edu exec deploy/keycloak -- \
curl -s -o /dev/null -w "%{http_code}" http://keycloak-postgresql:5432
# Policy-Logs prüfen (bei Calico oder Cilium mit Logging)
Lösung: NetworkPolicy-Selektoren überprüfen und anpassen. Die openDesk-Edu-Standard-Policies erlauben Traffic innerhalb des Namespace, aber benutzerdefinierte Policies können zu restriktiv sein. Policy temporär aufheben, um die Ursache zu bestätigen:
kubectl -n opendesk-edu delete networkpolicy restriktive-policy
Anschließend eine korrigierte Version einspielen.
Knotenausfall / Pod-Eviction
Fällt ein Kubernetes-Knoten aus, werden Pods gemäß den PodDisruptionBudgets (PDB) neu geplant. openDesk Edu definiert PDBs für kritische Dienste:
kubectl -n opendesk-edu get pdb
Vorgehen:
- Ausfallenden Knoten cordonen:
kubectl cordon <node> - Graceful drain:
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data - Nach Reparatur uncordon:
kubectl uncordon <node> - Prüfen, ob Pods auf den verbleibenden Knoten laufen:
kubectl -n opendesk-edu get pods -o wide
OOMKilled-Pods
Symptom: Pod startet immer wieder neu mit Grund OOMKilled.
Fehlersuche:
kubectl -n opendesk-edu describe pod <pod-name> | grep -A5 "Last State"
kubectl -n opendesk-edu top pod <pod-name> --containers
Lösung: Memory-Limit in den Helm-Werten des betroffenen Dienstes erhöhen:
keycloak:
resources:
requests:
memory: "2Gi"
limits:
memory: "4Gi"
Für Java-basierte Dienste (Keycloak, Grommunio, Collabora) zusätzlich die JVM-Heap-Einstellungen anpassen:
keycloak:
extraEnv:
- name: JAVA_OPTS
value: "-Xms1g -Xmx2g"
Skalierung der Dienste
Wann skaliert werden sollte
Folgende Schwellenwerte helfen bei der Entscheidung:
| Symptom | Schwelle | Maßnahme |
|---|---|---|
| CPU-Drosselung | > 80 % dauerhaft | Replica-Anzahl oder CPU-Limit erhöhen |
| Speicherdruck | > 85 % des Limits | Memory-Limit oder Replica-Anzahl erhöhen |
| Anfragenlatenz | > 2s p99-Latenz | Horizontal skalieren |
| PVC-Auslastung | > 80 % Kapazität | PVC erweitern oder Bereinigungsrichtlinie einführen |
| Keycloak-Sitzungen | > 5.000 aktiv | Keycloak-Replicas erhöhen (erfordert HA-Konfiguration) |
Horizontal Pod Autoscaling (HPA)
Für zustandslose Dienste (NGINX, Collabora, Element, Etherpad) HPA aktivieren:
kubectl -n opendesk-edu autoscale deployment nextcloud --cpu-percent=70 --min=1 --max=5
Oder in den helmfile-Werten:
nextcloud:
autoscaling:
enabled: true
minReplicas: 1
maxReplicas: 5
targetCPUUtilizationPercentage: 70
Hinweis: Keycloak kann nur horizontal skaliert werden, wenn der Sitzungscache für den verteilten Modus konfiguriert ist (Infinispan/JGroups). Dazu müssen KEYCLOAK_CACHE_TYPE=distributed gesetzt und die Pod-Erkennung aktiviert sein. Ohne diese Konfiguration kann die Skalierung über eine Replica hinaus zu Sitzungsinkonsistenzen führen.
Vertikale Skalierung zustandsbehafteter Dienste
Zustandsbehaftete Dienste (Datenbanken, ILIAS, Moodle, Grommunio) werden typischerweise vertikal skaliert:
# StatefulSet-Ressourcengrenzen bearbeiten
kubectl -n opendesk-edu edit statefulset ilias-postgresql
# resources.requests.memory und resources.limits.memory anpassen
Nach Änderung der Limits starten die Pods mit den neuen Werten neu.
Bei ILIAS sind die PHP-FPM-Worker der Engpass. In den Werten erhöhen:
ilias:
php:
fpm:
maxChildren: 50
memoryLimit: "512M"
Cluster-Knoten-Skalierung
Für den Kubernetes-Worker-Pool selbst:
- Cloud/on-prem mit Cluster-Autoscaler: Min-/Max-Knoten pro Knotengruppe konfigurieren. Die openDesk-Edu-Referenzinstallation setzt 32 GB RAM pro Knoten als Basis voraus.
- Manuelle Skalierung: Worker-Knoten über Ihre Infrastruktur-Toolchain hinzufügen oder entfernen (Terraform, Ansible, Bare-Metal-Provisionierung).
Knotengrößen nach Dienst-Tier:
| Tier | Empfohlene Knotengröße | Dienste |
|---|---|---|
| Klein (≤ 500 Nutzer) | 3 × 32 GB RAM, 8 vCPU | Alle Dienste auf gemeinsamen Knoten |
| Mittel (500–2.000) | 5 × 64 GB RAM, 16 vCPU | Dedizierte DB-Knoten für Keycloak, LMS |
| Groß (2.000–5.000) | 7 × 128 GB RAM, 32 vCPU | Getrennte Knotenpools für LMS, Mail, Dateien |
Log-Sammlung
Optionen für zentralisiertes Logging
Der openDesk-Edu-Stack unterstützt verschiedene Logging-Backends:
| Backend | Bereitstellungsmethode | Standard-Aufbewahrung | Empfohlen für |
|---|---|---|---|
| Loki + Grafana | Im Monitoring-Chart enthalten | 7 Tage | Kleine bis mittlere Installationen |
| Elasticsearch + Kibana | Manuelle Bereitstellung via ECK | 30 Tage | Große Installationen, DSGVO-Compliance-Audit |
| journalctl (keine Zentralisierung) | Keine zusätzliche Software | Systemd-Standard | Nur Entwicklungs-/Testumgebungen |
Logs an Loki senden, falls noch nicht konfiguriert:
global:
logging:
backend: loki
loki:
url: http://loki:3100/loki/api/v1/push
Standard-Log-Pfade je Dienst
Ohne zentralisiertes Logging verbleiben die Logs in den Pods:
| Dienst | Log-Pfad (im Container) | Relevante Ereignisse |
|---|---|---|
| Keycloak | /opt/keycloak/data/log/server.log |
Anmeldefehler, Token-Fehler, SAML-Assertions-Probleme |
| Nextcloud | /var/www/html/data/nextcloud.log |
Dateisynchronisationsfehler, Freigabefehler |
| ILIAS | /var/www/ilias/data/log/ |
LMS-Zugriffsprobleme, Plugin-Fehler |
| Grommunio | /var/log/grommunio/ |
SMTP-Fehler, Postfach-Kontingentwarnungen |
| PostgreSQL | /var/log/postgresql/ |
Verbindungsfehler, Replikationsverzögerung |
| NGINX-Ingress | /var/log/nginx/ |
Zugriffs- und Fehler-Logs je Dienst |
Log-Aufbewahrungsrichtlinien
Für zentralisiertes Logging die Aufbewahrungsdauer an das Speicherbudget anpassen:
- Loki: 7–30 Tage (Standard 7)
- Elasticsearch: 30–90 Tage über ILM (Index Lifecycle Management)
- Pod-Logs (
kubectl logs): Kubernetes entfernt sie beim Löschen des Pods. Für längere Aufbewahrung--max-log-agein der kubelet-Konfiguration setzen.
Effektive Nutzung von kubectl Logs
# Logs aller Dienste in Echtzeit streamen
kubetail -n opendesk-edu -l app.kubernetes.io/component=opendesk-edu
# Bestimmtes Deployment verfolgen
kubectl -n opendesk-edu logs -f deploy/keycloak
# Letzte 100 Zeilen mit Zeitstempeln
kubectl -n opendesk-edu logs --tail=100 --timestamps deploy/nextcloud
# Fehler über alle Pods suchen
kubectl -n opendesk-edu logs --selector=app.kubernetes.io/instance=opendesk-edu \
--tail=1000 | grep -i error | head -50
# Pod mit mehreren Containern: Container bestimmen
kubectl -n opendesk-edu logs deploy/ilias -c ilias-fpm
Regelmäßige Wartungsaufgaben
Täglich
- Health-Check:
curl https://opendesk-edu.de/api/health– sollte 200 zurückgeben. - Zertifikatsablauf prüfen:
kubectl -n opendesk-edu get certificate -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.notAfter}{"\n"}{end}'– alles unter 30 Tagen markieren. - Fehlgeschlagene Backup-Jobs prüfen:
kubectl -n opendesk-edu get jobs -l app=k8up | grep -E "0/1|Error".
Wöchentlich
- Backup-Verifikation:
restic checkauf dem Backup-Repository ausführen. Aktuelle Snapshots auflisten und eine Stichprobe verifizieren. - Pod-Review:
kubectl -n opendesk-edu get pods– CrashLoopBackOff-, OOMKilled- oder Pending-Pods untersuchen. - Keycloak-Sitzungen prüfen: Aktive Sitzungen mit dem erwarteten Bereich für Ihre Nutzerbasis abgleichen.
Monatlich
- Update-Prüfung: openDesk-Edu-GitHub-Releases auf neue Versionen prüfen. Release Notes auf Breaking Changes durchsehen.
- Sicherheitsaudit: CVEs für die eingesetzten Komponentenversionen prüfen. openDesk-Edu-Sicherheitsmailingliste abonnieren.
- Ressourcentrendanalyse: Prometheus-/Grafana-Ressourcennutzungsgraphen mit dem Vormonat vergleichen. Dienste identifizieren, die schneller als erwartet wachsen.
- Nutzerfeedback: Support-Tickets auf Muster prüfen, die auf Betriebsprobleme hinweisen.
Vierteljährlich
- Vollständige Wiederherstellungsübung: Komplette Wiederherstellung in einer Staging-Umgebung durchführen. Keycloak, Nextcloud/OpenCloud, ILIAS/Moodle und Grommunio einschließen. Zeit messen und Verbesserungen dokumentieren.
- Keycloak-Sitzungen bereinigen: Alte Sitzungen prüfen und löschen:
kubectl -n opendesk-edu exec deploy/keycloak -- \ /opt/keycloak/bin/kcadm.sh logout --all --realm ihr-realm - Helm-Chart-Updates:
helmfile depsundhelmfile diffausführen, um die Kompatibilität mit dem nächsten geplanten Release zu prüfen. - Kapazitätsplanung: PVC-Auslastungswachstum, Knotenressourcenauslastung und Nutzerwachstumstrends analysieren. Ressourcenerweiterungen für das nächste Quartal planen.
Fazit
Der Betrieb von openDesk Edu ist ein fortlaufender Prozess, keine einmalige Einrichtung. Der Schlüssel zu einer stabilen Plattform ist Kontinuität: regelmäßige Health-Checks, verifizierte Backups, disziplinierte Update-Verfahren und proaktives Kapazitätsmanagement.
Erstellen Sie Runbooks für Ihre spezifische Umgebung, dokumentieren Sie Abweichungen von der Referenzinstallation, und teilen Sie Betriebswissen innerhalb Ihres Teams. Wenn etwas schiefgeht – und das wird es – zahlt sich die investierte Vorbereitungszeit vielfach aus.
Beachten Sie bei allen Betriebsprozessen die Anforderungen der DSGVO, insbesondere bei der Protokollierung personenbezogener Daten (Keycloak-Sitzungen, Mail-Logs) und der Aufbewahrung von Backups. Stimmen Sie Ihre Aufbewahrungsfristen mit dem Datenschutzbeauftragten Ihrer Hochschule ab.
Für Support wenden Sie sich an das openDesk-Edu-Community-Forum oder kontaktieren Sie die Projektverantwortlichen über das GitHub-Repository.
Dieses Handbuch wurde für den Betrieb von openDesk Edu an Hochschulen im deutschen Hochschulnetz (DFN) erstellt. Es berücksichtigt die besonderen Anforderungen von DFN-AAI, der Bundesdruckerei als Zertifikatsaussteller und der DSGVO.
