4.0 KiB
Memory-Limits Baseline - Vorbereitung F-19
Status: Vorbereitung. Echte mem_limit-Werte werden erst gesetzt, wenn mindestens 7 Tage realer Peak-Werte vorliegen.
Bezug: Mai-2026-Audit F-19 "Keine Container-Memory-Limits".
Warum nicht heute
Audit-TODO 2026-05-30: F-19 ist nicht akut. Es gibt keinen dokumentierten OOM-/Memory-Vorfall. services/posture-check/docker-critical-events.sh ueberwacht die/oom/kill-Events und alarmiert via ntfy; der Detektions-Pfad ist da, der Daten-Befund fehlt. Limits ohne Peak-Daten zu setzen bedeutet entweder zu eng (Flapping) oder so weit weg vom Realwert, dass die Schutzwirkung gegen Null geht.
Familien-Einladung verschiebt die Risiko-Bilanz nach oben: Ein OOM in Authelia/Postgres bei Familien-Nutzung kostet Vertrauen, nicht nur Operator-Zeit. Sobald die Einladung raus ist, wird F-19 ein "should" statt "nice".
Plan
Phase 1 - Peak-Beobachtung (7 Tage)
Auf dem Host stuendlich docker stats --no-stream snappen und in eine Textfile pro Container schreiben. Beispiel-Snippet fuer das Cron-Skript:
#!/usr/bin/env bash
# /boot/config/plugins/user.scripts/scripts/docker-stats-snapshot/script
set -euo pipefail
OUT="/mnt/user/services/policy-checks/docker-stats-$(date +%Y%m%d).log"
mkdir -p "$(dirname "$OUT")"
{
echo "=== $(date -Iseconds) ==="
docker stats --no-stream --format 'table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.CPUPerc}}'
} >> "$OUT"
Cron: stuendlich (0 * * * *), 7 Tage laufen lassen.
Phase 2 - Peak-Auswertung
Pro Tier-1-Container das Maximum MemUsage aus dem 7-Tage-Log ableiten:
grep -E '^postgresql17|^authelia|^Redis|^vaultwarden|^gitea|^traefik|^komodo-mongo' \
/mnt/user/services/policy-checks/docker-stats-*.log \
| awk -F'\t' '{print $1, $2}' \
| sort -u
Erwartete Groessenordnungen (zur Plausibilitaetspruefung, nicht zur Festlegung):
| Container | Erwartung |
|---|---|
| postgresql17 | 200-600 MB |
| Redis | 30-80 MB |
| authelia | 50-150 MB |
| vaultwarden | 100-300 MB |
| gitea | 200-500 MB |
| traefik | 80-200 MB |
| komodo-mongo | 300-800 MB |
Phase 3 - Limit-Setting
Pro Tier-1-Container:
deploy:
resources:
limits:
memory: <peak * 1.5, mindestens floor>
Floor-Werte:
- postgresql17: 1G (Cache-Verhalten leidet bei weniger)
- komodo-mongo: 1G (WiredTiger braucht Working-Set)
- Redis: 256M (Paperless-Cache)
- vaultwarden: 256M
- gitea: 512M
- traefik: 256M
- authelia: 256M
mem_reservation bewusst nicht setzen — auf einem Single-Host-Setup ist Reservation Theater.
Phase 4 - Rollout-Reihenfolge
- Redis und authelia zuerst (kleinste Risiko-Container, klares Memory-Profil).
- Wenn nach 48 h kein Flapping: traefik, vaultwarden, gitea.
- Zuletzt postgresql17 und komodo-mongo, weil DB-Limits bei zu engem Setting Performance kippen.
Jede Stufe einzeln committen und 24 h beobachten.
Phase 5 - Tier-2 (optional)
Tier-2 (Immich, Nextcloud, Paperless, Mealie, Mail-Archiver) bewusst spaeter, nur wenn ein konkreter Vorfall das rechtfertigt. Immich-ML ist der wahrscheinlichste Kandidat fuer den ersten echten OOM-Vorfall, deshalb dort zuerst beobachten, dann limitieren.
Stop-Regel
Falls in Phase 3 ein Container nach Limit-Setzung haeufiger restartet als vor dem Limit: Limit raus, kein zweiter Versuch ohne dazwischenliegende Peak-Reanalyse. F-19 bleibt dann offen.
Was nicht ins Skript gehoert
- Mem-Limits sind kein Tuning, kein Performance-Hebel. Wer sich Performance erhofft, hat das falsche Werkzeug.
- Postgres-
shared_buffersundeffective_cache_sizemuessen zur Limit-Groesse passen. Setzen ohne Postgres-internes Tuning macht die DB langsamer, nicht stabiler. - Komodo-Mongo waechst mit Stack-/Update-Historie. Limit fuer naechste 12 Monate planen, nicht fuer den heutigen Stand.
Naechster Trigger
- Familien-Einladung raus, 4 Wochen stabile Nutzung, oder
- erster echter OOM-Vorfall im
docker-critical-events.sh-Log, oder - ein Immich/Nextcloud-Last-Sprung (z.B. grosses Foto-Backup), bei dem Host-Swap sichtbar wird.
Bei einem dieser Trigger: Phase 1 starten.