
🌐 Auch auf: English · Français · Español
Deep Dive aus der Reihe rund um die Ansible-Tour. Niveau: fortgeschrittene Linux-Administration. Die Tour erklärt die Rollen; die Deep Dives erklären die Technik darunter – wie sie funktioniert, warum sie hier ist, was genau dieses Setup damit macht, wie man sie im Alltag betreibt und was es sonst noch gegeben hätte.
Redis ist der kleinste Dienst in diesem Setup – ein paar Megabyte Speicher, ein Bruchteil eines CPU-Kerns – und beide Anwendungen hängen davon ab. Der Blog nutzt es als Objekt-Cache (Teil 3), Nextcloud für Dateisperren und als gemeinsamen Cache zwischen Prozessen (Teil 4). Dieser Beitrag erklärt, was Redis dort tut, warum die beiden Instanzen unterschiedlich abgesichert sind, was die Zahlen sagen und was eine Prüfung für diesen Artikel zutage brachte.
🧭 Wie Redis funktioniert
Ein Thread, alles im Speicher
Redis hält alle Daten im RAM und führt Befehle nacheinander in einer einzigen Ereignisschleife aus. Das klingt nach Engpass und ist das Gegenteil: Es gibt keine Sperren zwischen Threads, jeder Befehl ist atomar, und ein einfacher Lesezugriff dauert Mikrosekunden. Netzwerk und Systemaufrufe kosten mehr als der Befehl selbst.
Schlüssel, Typen, Ablauf
Jeder Eintrag ist ein Schlüssel mit einem Wert – ein String, ein Hash, eine Liste, eine Menge. Jeder Schlüssel kann eine Lebensdauer haben; Redis löscht ihn, wenn sie abläuft. Beide Anwendungen setzen auf fast jeden Schlüssel eine Lebensdauer, der Datenbestand räumt sich also selbst auf.
Wenn der Speicher ausgeht
maxmemory setzt eine Grenze; maxmemory-policy entscheidet, was an der Grenze passiert. allkeys-lru verdrängt den am längsten nicht genutzten Schlüssel – richtig für einen reinen Cache, in dem sich jeder Eintrag neu aufbauen lässt. noeviction verweigert stattdessen neue Schreibvorgänge – richtig für Daten, die nicht stillschweigend verschwinden dürfen, etwa eine Sperre.
Persistenz – oder keine
Redis kann Schnappschüsse schreiben (RDB, gesteuert über save) und ein Protokoll aller Schreibvorgänge (AOF). Beides ist für Daten, die einen Neustart überleben müssen. Ein Cache und kurzlebige Sperren brauchen keins von beiden: Nach einem Neustart füllt sich der Cache wieder, und die Anwendungen holen neue Sperren.
Authentifizierung und Protected Mode
requirepass (oder seit Redis 6 ACL-Benutzer) zwingt jeden Client, sich zuerst anzumelden. Der Protected Mode weist Verbindungen von außen nur ab, wenn Redis ohne Passwort auf allen Schnittstellen lauscht – sobald eine Bind-Adresse und kein Passwort konfiguriert sind, hilft er nicht mehr.
🛡️ Warum es hier ist
- WordPress-Objekt-Cache. WordPress fragt bei jedem Aufruf dieselben Optionen, Menüs und Beitrags-Metadaten in der Datenbank ab. Mit dem Plugin Redis Object Cache kommen die Antworten stattdessen aus Redis.
- Nextcloud-Dateisperren. Wenn zwei Clients gleichzeitig dieselbe Datei schreiben, braucht Nextcloud eine Sperre, die jeder PHP-Prozess in jedem Pod sofort sieht. Ohne sie überschreiben sich Sync-Clients gegenseitig. Nextcloud empfiehlt dafür ausdrücklich Redis.
- Verteilter Nextcloud-Cache. Daten, die prozessübergreifend geteilt werden – App-Konfiguration, sitzungsnaher Zustand – liegen ebenfalls dort; der Cache pro Prozess ist APCu.
🔧 Was dieses Repository macht
| Blog | Nextcloud-Server | |
|---|---|---|
| Wo | Pod in K3s (redis:7.4-alpine) | Auf dem Host, AlmaLinux-Paket (Redis 6.2) |
| Rolle | blog_k3s_deploy | next_packages + next_redis |
| Genutzt für | Objekt-Cache | Dateisperren + verteilter Cache |
| Speichergrenze | 80 MB, allkeys-lru | keine, noeviction |
| Persistenz | keine (--save "", AOF aus) | RDB-Schnappschüsse (Paket-Standard) |
| Passwort | keins | requirepass aus dem Vault |
| Erreichbar über | ClusterIP-Service, NetworkPolicy: nur WordPress-Pods | Knoten-IP und 127.0.0.1, nftables: nur das Pod-Netz |
| SELinux | container_t mit eigenen MCS-Kategorien | redis_t |
Der Blog: ein Wegwerf-Cache in einem abgeschlossenen Pod
command: ["redis-server", "--save", "", "--appendonly", "no",
"--maxmemory", "80mb", "--maxmemory-policy", "allkeys-lru"]
securityContext:
runAsNonRoot: true
readOnlyRootFilesystem: true
capabilities: { drop: [ALL] }Alles in diesem Redis kann weggeworfen werden, und so ist es auch konfiguriert: keine Plattenzugriffe, eine Speicherobergrenze mit LRU-Verdrängung, ein schreibgeschütztes Root-Dateisystem, keine Capabilities. Es hat kein Passwort, weil nichts außerhalb des Pod-Netzes es erreicht und darin nur die WordPress-Pods dürfen – eine NetworkPolicy sperrt jeden anderen Pod aus, auch die Datenbank und den Ingress-Controller.
Nextcloud: warum das Passwort
Auf den Nextcloud-Servern läuft Redis auf dem Host, und die Pods erreichen es über einen Kubernetes-Service, der auf die Knoten-IP zeigt. Redis lauscht also auf der öffentlichen Adresse des Servers. Zwischen Internet und Redis stand anfangs genau eine nftables-Regel. Die Rolle next_redis fügt requirepass als zweite Schicht hinzu, denn eine still versagende Regel ist hier keine Theorie: fail2ban lag auf dem Blog einmal zwei Tage tot, ohne dass es jemand bemerkte. Das Passwort erreicht Nextcloud über ein Kubernetes-Secret, eingehängt als redis.config.php – nicht über die ConfigMap mit dem Rest der Konfiguration, denn ConfigMaps sind nicht für Geheimnisse gedacht.
- name: Redis | Ensure Redis requires authentication
ansible.builtin.lineinfile:
path: /etc/redis/redis.conf
regexp: '^requirepass\s+'
line: 'requirepass {{ nextcloud_redis_pass }}'
no_log: true # the line contains the password
notify: Restart Redis
- ansible.builtin.meta: flush_handlers # restart NOW, the next role needs itDas flush_handlers ist keine Dekoration: Die Rollen danach führen occ-Befehle im Pod aus, die sich über die Knoten-IP mit Redis verbinden. Ohne den sofortigen Neustart würde Redis in diesem Moment noch nur auf 127.0.0.1 lauschen.
noeviction mit Absicht
Das Host-Redis hat keine Speichergrenze und die Standard-Policy noeviction. Für Sperren ist das richtig: Eine verdrängte Sperre wäre eine Sperre, die stillschweigend aufgehört hat, eine Datei zu schützen. Der Datenbestand ist ohnehin winzig (siehe unten), und der Server hat reichlich Speicher.
📊 Gemessen
| Blog | Nextcloud A | Nextcloud B | |
|---|---|---|---|
| Version | 7.4.11 | 6.2.24 | 6.2.24 |
| Belegter Speicher | 14,8 MB | 1,7 MB | 1,3 MB |
| Schlüssel | 19.079 | 56 | 83 |
| Trefferquote seit Neustart | 87,6 % | 85,9 % | 64,4 % |
| Verdrängte Schlüssel | 0 | 0 | 0 |
| Einträge im Slow-Log | 1 | 3 | 0 |
Die beiden Lasten sehen sich überhaupt nicht ähnlich. Der Blog-Cache hält Zehntausende kleine Objekte; Nextcloud hält ein paar Dutzend Sperren und Cache-Einträge, die ständig entstehen und ablaufen – über 11.000 Schlüssel liefen auf dem größeren Server innerhalb eines Tages ab. Die niedrigere Trefferquote auf dem kleineren Nextcloud-Server liegt in der Natur von Sperren, kein Problem: „Ist diese Datei gesperrt?“ ist immer dann ein Fehlgriff, wenn die Antwort „nein“ lautet. Das Fragmentierungsverhältnis, das Redis für die Host-Instanzen meldet (7 bis 9), sieht alarmierend aus und bedeutet bei dieser Größe nichts – ein paar Megabyte Prozess-Grundlast geteilt durch ein, zwei Megabyte Daten.
Der Blog nutzt Predis, einen in PHP geschriebenen Client, weil das offizielle WordPress-Image die Erweiterung phpredis nicht mitbringt. Die C-Erweiterung wäre schneller; bei 88 % Trefferquote und Seiten-Cache davor zeigt sich der Unterschied nicht in den Antwortzeiten.
🔍 Was die Prüfung für diesen Artikel fand
Beim Sammeln der Fakten für diesen Beitrag kamen vier Dinge zutage, die das Setup noch nicht getan hatte – keins gefährlich, alle wissenswert. Alle vier sind seit dem 20. Oktober 2026 behoben.
- Keine systemd-Sandbox für das Host-Redis. MariaDB auf denselben Servern bekam ein Härtungs-Drop-in (keine Capabilities, schreibgeschütztes Dateisystem, Systemaufruf-Filter); Redis läuft nur mit der Unit aus dem Paket. SELinux sperrt es trotzdem in
redis_tein, ungeschützt ist es also nicht – aber die zweite Schicht, die MariaDB hat, fehlt. Die Gliederung genau dieses Artikels behauptete, es gäbe sie. Behoben: dieselbe Art Drop-in wie bei MariaDB – mit einer Falle unterwegs: Die Sandbox-Optionen setzenNoNewPrivilegesvoraus, und darunter verweigerte SELinux den Wechsel nachredis_t; Redis startete zwei Minuten lang nicht. Ein kleines lokales Modul (init_nnp_daemon_domain(redis_t)) erlaubt genau diesen Übergang. - Schnappschüsse, die niemand braucht. Das Host-Redis behält den Paket-Standard
save 3600 1 300 100 60 10000und schreibt regelmäßigdump.rdb– für Sperren mit Lebensdauer und einen Cache, der sich selbst neu aufbaut. Nach einem Neustart wiederhergestellt, müssten veraltete Sperren sogar erst ablaufen. Behoben:save "", wie auf dem Blog, und die altedump.rdbentfernt. - Ein gewechseltes Passwort wäre nicht bei Nextcloud angekommen. Die Verbindungsdaten kommen aus einem Secret, eingehängt mit
subPath– und ein subPath-Mount aktualisiert sich in einem laufenden Pod nie. Der Pod wird neu ausgerollt, wenn sich seine Konfiguration ändert, über eine Checksummen-Annotation, aber das Secret war nicht Teil dieser Checksumme. Ein Passwortwechsel hätte Redis mit dem neuen Passwort neu gestartet, während Nextcloud bis zum nächsten zufälligen Neustart das alte behalten hätte: keine Sperren, Fehlerseiten. Behoben: Das Secret ist jetzt Teil der Checksumme. Auch das letzte Stück Handarbeit ist automatisiert – der Push-Dienst notify_push liest das Passwort ausconfig.php, wo der Installer es einmal hineingeschrieben hat: Das Playbook kopiert es aus dem Secret inconfig.php, sobald die beiden voneinander abweichen. - Monit überwacht es nicht. Monit startet und meldet K3s, sshd und die Monitoring-Dienste, aber nicht das Host-Redis oder MariaDB der Nextcloud-Server. Fiele Redis aus, würde Nextcloud es zuerst merken und Grafana als Zweites. Behoben: Beide stehen jetzt in Monits Liste.
🧰 Betrieb im Alltag
# host (Nextcloud): password from the config, never on the command line
export REDISCLI_AUTH="$(awk '/^requirepass/{print $2}' /etc/redis/redis.conf)"
redis-cli INFO stats | grep -E 'keyspace_(hits|misses)|evicted'
redis-cli INFO memory | grep used_memory_human
redis-cli SLOWLOG GET 5
redis-cli --latency # Ctrl-C to stop
# blog pod
k3s kubectl -n wordpress exec deploy/redis -- redis-cli INFO keyspace
wp redis status # inside the WordPress container, as www-dataMONITORzeigt jeden Befehl live – für ein paar Sekunden nützlich, auf einer belebten Instanz teuer und voller Daten.- Leeren. Auf dem Blog leert
wp cache flushden Objekt-Cache gefahrlos. Bei Nextcloud wirft einFLUSHALLauch alle Sperren weg; nur im Wartungsmodus. - Passwort wechseln. Im Vault ändern, Playbook laufen lassen:
next_redisschreibt es inredis.confund startet Redis neu,next_k3s_deployaktualisiert das Secret und rollt – seit der Korrektur oben – im selben Lauf den Nextcloud-Pod neu aus. notify_push bekommt es im selben Lauf. - Updates. Das Host-Paket bekommt Sicherheitskorrekturen über dnf-automatic, das Redis danach neu startet; das Blog-Image folgt dem Pin in
versions.yml.
🆘 Spickzettel: Symptom → Befehl
Die Kurzfassung dieses Artikels für den Moment, in dem etwas nicht stimmt. Auf dem Host als root ausführen; <…> sind Platzhalter. occ und wp sind die Shell-Funktionen aus den Deep Dives zu Nextcloud und WordPress.
| Symptom | Befehl |
|---|---|
| Läuft er, und eingesperrt? | systemctl status redis |
| Ansprechen, ohne Passwort auf der Kommandozeile | export REDISCLI_AUTH="$(awk '/^requirepass/{print $2}' /etc/redis/redis.conf)" |
| Tut der Cache seine Arbeit? | redis-cli INFO stats | grep -E 'keyspace_(hits|misses)|evicted' |
| Speicher voll? | redis-cli INFO memory | grep -E "used_memory_human|maxmemory_human" |
| Langsame Befehle, hohe Latenz | redis-cli SLOWLOG GET 5 |
| Keine Push-Benachrichtigungen in Nextcloud | k3s kubectl -n nextcloud logs deploy/notify-push --tail=20 |
| Der Cache des Blogs | k3s kubectl -n wordpress exec deploy/redis -- redis-cli INFO keyspace |
🔭 Wie es weitergeht
- Valkey. Nachdem Redis 2024 seine Lizenz geändert hatte, wurde der Fork Valkey der Linux Foundation in mehreren Distributionen zum Standard. Er ist ein direkter Ersatz; ein Wechsel wäre eine Paket- oder Image-Änderung.
- Metriken. Ein redis_exporter würde Trefferquote und Speicher nach Grafana bringen statt eines händischen
INFO.
⚖️ Alternativen – und warum Redis
| Option | Stärke | Warum nicht hier |
|---|---|---|
| Memcached | Einfacher, schneller Cache | Keine Sperr-Semantik, die Nextcloud nutzen kann; Sperren blieben in der Datenbank. |
| Nur APCu | Im Prozess, kein Netzwerk | Nicht zwischen PHP-Prozessen oder Pods geteilt – für Sperren nutzlos. Nextcloud nutzt es zusätzlich als lokalen Cache. |
| Sperren in der Datenbank | Kein zusätzlicher Dienst | Nextclouds Rückfallebene; belastet die ohnehin am stärksten belastete Komponente und ist langsamer. |
| Valkey / KeyDB | Forks mit anderer Verwaltung oder Threading | Valkey ist der wahrscheinliche nächste Schritt; KeyDB ist weniger aktiv. |
| Redis | Was beide Anwendungen erwarten und testen, winziger Ressourcenbedarf | Gewählt. |
Redis ist die Art Komponente, die man leicht vergisst, weil sie sich nie beschwert. Die Prüfung für diesen Artikel hat daran erinnert, dass „es funktioniert“ und „es ist so eingerichtet wie der Rest“ zwei verschiedene Aussagen sind – und dass sich die zweite auch bei den kleinen Diensten zu prüfen lohnt.


