Ein Inhouse-Chart valkey für einzelne Cache- und Warteschlangen-Instanzen, je Anwendung eine — als Ersatz für die geteilte Instanz cluster-redis.
Warum
cluster-redis versorgt heute sechs Anwendungen (OneUptime auf Index 2, Outline, drei Paperless-Instanzen; Stand 26.09.2026). Die Trennung läuft über eine ACL-Datei in einem einzigen 1Password-Feld (cluster-redis, Feld users.acl), und daran hängt alles:
Redis-ACL-Schlüsselmuster gelten über alle DB-Indizes hinweg. Ein eigener Index isoliert nichts. Anwendungen mit unprefixten Schlüsseln lassen sich deshalb überhaupt nicht einfangen — Sidekiq 8 (das neue sure) ist genau so ein Fall und hat die Namespace-Unterstützung ab Version 7 entfernt.
Eine Änderung an users.acl betrifft sechs Anwendungen und braucht einen Redis-Neustart, damit sie greift. Der Kommentar in cluster-config/fleet-cd/jlab-git/gitea/jlab-git.values.yaml hat genau deshalb schon entschieden, Gitea nicht dort anzuschließen: „Ein weiterer Nutzer waere eine Aenderung an einem Element, an dem alle anderen Verbraucher mit haengen."
Am 26.09.2026 hat dieselbe Konstruktion einen Monat Stillstand bei Paperless verursacht (cluster-config#102): Paperless 3.0 legte Celery-Ergebnisse als unprefixte celery-task-meta-*-Schlüssel ab, die ACL lehnte sie ab, und die Meldung NoPermissionError tauchte nur im Worker-Log auf.
Mit einer Instanz je Anwendung verschwindet die ACL-Frage ersatzlos: Jede darf ~*, weil sie allein ist.
Das Abbild: offiziell, nicht Bitnami
docker.io/valkey/valkey, nicht bitnamicharts/valkey. Der Bitnami-Chart existiert (6.3.3, App 9.1.2), aber Bitnami führt seit August 2025 nur noch latest — die Folge steht bereits fünfmal in cluster-config als tag: "latest@sha256:…", zweimal davon ausgerechnet in cluster-redis selbst. Renovate sieht das offizielle Abbild dagegen ohne Kunstgriff (es schlägt gerade einen Digest für valkey:9.1-alpine vor).
Gewünschte Merkmale
Grundform
StatefulSet, eine Kopie, Service. Kein Cluster-Modus, keine Repliken — das ist ein Cache je Anwendung, kein Datenbank-Ersatz.
scaleDown-Schalter chart-global, wie in den übrigen Inhouse-Charts.
values.schema.json mit additionalProperties: false. Hat sich bewährt: ein verschriebener Schlüssel scheitert beim Rendern statt still ignoriert zu werden.
NOTES.txt, das die Pflichtfelder des 1Password-Eintrags namentlich aufzählt — nach dem Muster des sure-Charts. Ein fehlendes Feld ergibt sonst CreateContainerConfigError und keinen Render-Fehler.
Speicher
persistence.enabled umschaltbar. Für Warteschlangen (Sidekiq, Celery) an, für reine Zwischenspeicher aus.
longhorn-encrypted-ns, Vorgabe klein (1Gi). Auf verschlüsselten Longhorn-Volumes wird Platz nie zurückgegeben — lieber knapp anfangen.
appendonly als Wert, mit Begründung im Kommentar: Für Warteschlangen ist AOF die haltbarere Wahl, RDB verliert im Zweifel die letzten Minuten.
Verdrängung — der wichtigste Standardwert
maxmemory-policy als Wert, Vorgabe noeviction. Nicht allkeys-lru: Unter Druck würde Redis/Valkey sonst die Celery- beziehungsweise Sidekiq-Warteschlange wegwerfen, und die Anwendung bliebe dabei grün. Das war eine der Hypothesen bei cluster-config#102 und ist hier billiger zu verhindern als zu diagnostizieren.
maxmemory passend zum Speicher-Limit setzen, nicht darüber — sonst holt das OOM-Kill des Kubelet, was die Verdrängungsregel hätte regeln sollen.
Zugang
Passwort als OnePasswordItem, das der Chart selbst rendert (secrets.authSecretRef), niemals als Literal. Feldname im NOTES.txt dokumentiert.
--requirepass über Umgebung, nicht als Argument — sonst steht es in der Prozessliste.
Optional eine NetworkPolicy, die Ingress auf den eigenen Namensraum begrenzt. Im Cluster gibt es faktisch keine (die acht vorhandenen sind Allow-all oder Chart-Beigaben), und dann ist das Passwort die einzige Grenze. Mit der Policy wäre es die zweite.
Härtung und Ressourcen
runAsNonRoot, feste UID/GID, fsGroup passend zum Volume, readOnlyRootFilesystem: true, alle Capabilities weg, seccompProfile: RuntimeDefault im Pod-Kontext (damit Init-Container mitgedeckt sind).
Schreibpfade als emptyDir, soweit nötig.
Ressourcen nach der Konvention des Repositories: Limits für Speicher und ephemeral-storage aus den Requests berechnet, kein CPU-Limit als Vorgabe.
Probes: redis-cli ping beziehungsweise valkey-cli ping als Exec-Probe. Kein HTTP.
Versionierung
<chartVersion>+up<appVersion>, wie alle Inhouse-Charts.
Der Installationstest (k3d) muss durchlaufen — inklusive eines Falls mit und eines ohne Persistenz.
Erster Abnehmer: sure
cluster-config#110 bereitet das Deployment von Sure vor und lässt die Redis-Frage bewusst offen, weil der Chart die Verbindung als fertige redis://-Adresse aus dem Tresor bekommt. Sure läuft noch nicht — damit ist es der risikofreie Erstversuch für diesen Chart: Es gibt keine Warteschlange zu verlieren und keinen ACL-Nutzer zu entfernen.
Danach, je Anwendung verschieden
Reihenfolge immer: Instanz ausrollen → connection-url im Tresor umbiegen → Pods neu starten → prüfen → zuletzt den ACL-Nutzer aus users.acl entfernen, damit ein Rückfall möglich bleibt.
Paperless ×3 — erst nach 3.2.0, sonst vermischen sich zwei Ursachen (cluster-config#102).
OneUptime (db2, 33 426 Schlüssel und wachsend) — zuletzt. Hier heißt Umziehen: Warteschlangen leer laufen lassen oder Verlust in Kauf nehmen.
Der gemeinsame Bestand liegt bei 464 MB, fast vollständig OneUptime. In Summe entsteht also kein neuer Speicherbedarf, er verteilt sich nur.
Ein Inhouse-Chart `valkey` für einzelne Cache- und Warteschlangen-Instanzen, je Anwendung eine — als Ersatz für die geteilte Instanz `cluster-redis`.
## Warum
`cluster-redis` versorgt heute sechs Anwendungen (OneUptime auf Index 2, Outline, drei Paperless-Instanzen; Stand 26.09.2026). Die Trennung läuft über eine **ACL-Datei in einem einzigen 1Password-Feld** (`cluster-redis`, Feld `users.acl`), und daran hängt alles:
- **Redis-ACL-Schlüsselmuster gelten über alle DB-Indizes hinweg.** Ein eigener Index isoliert nichts. Anwendungen mit unprefixten Schlüsseln lassen sich deshalb überhaupt nicht einfangen — Sidekiq 8 (das neue `sure`) ist genau so ein Fall und hat die Namespace-Unterstützung ab Version 7 entfernt.
- **Eine Änderung an `users.acl` betrifft sechs Anwendungen** und braucht einen Redis-Neustart, damit sie greift. Der Kommentar in `cluster-config/fleet-cd/jlab-git/gitea/jlab-git.values.yaml` hat genau deshalb schon entschieden, Gitea *nicht* dort anzuschließen: *„Ein weiterer Nutzer waere eine Aenderung an einem Element, an dem alle anderen Verbraucher mit haengen."*
- Am 26.09.2026 hat dieselbe Konstruktion einen Monat Stillstand bei Paperless verursacht (`cluster-config#102`): Paperless 3.0 legte Celery-Ergebnisse als unprefixte `celery-task-meta-*`-Schlüssel ab, die ACL lehnte sie ab, und die Meldung `NoPermissionError` tauchte nur im Worker-Log auf.
Mit einer Instanz je Anwendung verschwindet die ACL-Frage ersatzlos: Jede darf `~*`, weil sie allein ist.
## Das Abbild: offiziell, nicht Bitnami
**`docker.io/valkey/valkey`, nicht `bitnamicharts/valkey`.** Der Bitnami-Chart existiert (6.3.3, App 9.1.2), aber Bitnami führt seit August 2025 nur noch `latest` — die Folge steht bereits fünfmal in `cluster-config` als `tag: "latest@sha256:…"`, zweimal davon ausgerechnet in `cluster-redis` selbst. Renovate sieht das offizielle Abbild dagegen ohne Kunstgriff (es schlägt gerade einen Digest für `valkey:9.1-alpine` vor).
## Gewünschte Merkmale
**Grundform**
- StatefulSet, eine Kopie, Service. Kein Cluster-Modus, keine Repliken — das ist ein Cache je Anwendung, kein Datenbank-Ersatz.
- `scaleDown`-Schalter chart-global, wie in den übrigen Inhouse-Charts.
- `values.schema.json` mit `additionalProperties: false`. Hat sich bewährt: ein verschriebener Schlüssel scheitert beim Rendern statt still ignoriert zu werden.
- `NOTES.txt`, das die Pflichtfelder des 1Password-Eintrags **namentlich** aufzählt — nach dem Muster des `sure`-Charts. Ein fehlendes Feld ergibt sonst `CreateContainerConfigError` und keinen Render-Fehler.
**Speicher**
- `persistence.enabled` umschaltbar. Für Warteschlangen (Sidekiq, Celery) an, für reine Zwischenspeicher aus.
- `longhorn-encrypted-ns`, Vorgabe klein (1Gi). Auf verschlüsselten Longhorn-Volumes wird Platz nie zurückgegeben — lieber knapp anfangen.
- `appendonly` als Wert, mit Begründung im Kommentar: Für Warteschlangen ist AOF die haltbarere Wahl, RDB verliert im Zweifel die letzten Minuten.
**Verdrängung — der wichtigste Standardwert**
- `maxmemory-policy` als Wert, **Vorgabe `noeviction`**. Nicht `allkeys-lru`: Unter Druck würde Redis/Valkey sonst die Celery- beziehungsweise Sidekiq-Warteschlange wegwerfen, und die Anwendung bliebe dabei grün. Das war eine der Hypothesen bei `cluster-config#102` und ist hier billiger zu verhindern als zu diagnostizieren.
- `maxmemory` passend zum Speicher-Limit setzen, nicht darüber — sonst holt das OOM-Kill des Kubelet, was die Verdrängungsregel hätte regeln sollen.
**Zugang**
- Passwort als `OnePasswordItem`, das der Chart selbst rendert (`secrets.authSecretRef`), niemals als Literal. Feldname im `NOTES.txt` dokumentiert.
- `--requirepass` über Umgebung, nicht als Argument — sonst steht es in der Prozessliste.
- Optional eine **NetworkPolicy**, die Ingress auf den eigenen Namensraum begrenzt. Im Cluster gibt es faktisch keine (die acht vorhandenen sind Allow-all oder Chart-Beigaben), und dann ist das Passwort die einzige Grenze. Mit der Policy wäre es die zweite.
**Härtung und Ressourcen**
- `runAsNonRoot`, feste UID/GID, `fsGroup` passend zum Volume, `readOnlyRootFilesystem: true`, alle Capabilities weg, `seccompProfile: RuntimeDefault` im **Pod**-Kontext (damit Init-Container mitgedeckt sind).
- Schreibpfade als `emptyDir`, soweit nötig.
- Ressourcen nach der Konvention des Repositories: Limits für Speicher und `ephemeral-storage` aus den Requests berechnet, **kein** CPU-Limit als Vorgabe.
- Probes: `redis-cli ping` beziehungsweise `valkey-cli ping` als Exec-Probe. Kein HTTP.
**Versionierung**
- `<chartVersion>+up<appVersion>`, wie alle Inhouse-Charts.
- Der Installationstest (k3d) muss durchlaufen — inklusive eines Falls *mit* und eines *ohne* Persistenz.
## Erster Abnehmer: `sure`
`cluster-config#110` bereitet das Deployment von Sure vor und lässt die Redis-Frage bewusst offen, weil der Chart die Verbindung als fertige `redis://`-Adresse aus dem Tresor bekommt. Sure **läuft noch nicht** — damit ist es der risikofreie Erstversuch für diesen Chart: Es gibt keine Warteschlange zu verlieren und keinen ACL-Nutzer zu entfernen.
## Danach, je Anwendung verschieden
Reihenfolge immer: Instanz ausrollen → `connection-url` im Tresor umbiegen → Pods neu starten → prüfen → **zuletzt** den ACL-Nutzer aus `users.acl` entfernen, damit ein Rückfall möglich bleibt.
- **Outline** (`db1`, 3 Schlüssel) — praktisch aufwandsfrei, guter zweiter Schritt.
- **Paperless ×3** — erst *nach* 3.2.0, sonst vermischen sich zwei Ursachen (`cluster-config#102`).
- **OneUptime** (`db2`, 33 426 Schlüssel und wachsend) — zuletzt. Hier heißt Umziehen: Warteschlangen leer laufen lassen oder Verlust in Kauf nehmen.
Der gemeinsame Bestand liegt bei 464 MB, fast vollständig OneUptime. In Summe entsteht also kein neuer Speicherbedarf, er verteilt sich nur.
Freigegebener Umsetzungsplan (Manager-Sitzung, 2026-09-27). Die Anforderungen im Issue-Text gelten unverändert; hier stehen die verifizierten Fakten, vier Entscheidungen und drei Punkte, die nicht angenommen werden dürfen.
Verifiziert, nicht aus der Erinnerung
Gegen die Registry abgefragt:
Exakte Tags existieren. Neueste stabile Fassung ist 9.1.2, es gibt 9.1.2-alpine3.24 (unveränderlich), 9.1.2-alpine (wandert mit der Alpine-Basis) und 9.1-alpine (wandert mit jedem Patch). Der im Issue genannte 9.1-alpine taugt damit nicht als appVersion.
Das Image setzt User nicht — es startet als root. Wie bei Redis lässt der Entrypoint (tini -- docker-entrypoint.sh) die Rechte per gosu auf den Benutzer valkey fallen. Startet der Pod direkt als uid 999, wird dieser Schritt übersprungen. Das ist bei der Umsetzung zu bestätigen, nicht vorauszusetzen.
WorkingDir: /data, Cmd: valkey-server, kein deklariertes Volume.
Entschieden
appVersion: 9.1.2-alpine3.24, Chart 1.0.0+up9.1.2.alpine3.24 (Bindestriche im Suffix zu Punkten). Vollständig unveränderlicher Tag.
Das Passwort kommt als fertige Konfigurationszeile aus dem 1Password-Eintrag und wird als Datei gemountet — kein Init-Container, der sie aus der Umgebung zusammensetzt, und kein --requirepass in der Prozessliste. Der Feldname wird in NOTES.txt namentlich dokumentiert.
Der Install-Test fährt den Pfad mit Persistenz. Das ist der riskante Pfad (PVC, fsGroup auf dem Volume, AOF-Start) und die Vorgabe des Charts. Die Variante ohne Persistenz wird lokal gerendert und im PR als bekannte Lücke benannt — die Maschinerie kann nur eine Variante je Chart.
NetworkPolicy standardmäßig an, mit Wert zum Abschalten und einem Wert, der Verbraucher aus anderen Namensräumen erlaubt. Neues Chart, es gibt keine bestehende Installation, die daran brechen könnte.
Die Folge von Entscheidung 1, die niemand später als Versäumnis lesen soll
Ein vollständig unveränderlicher Tag bindet die Alpine-Basis mit ein — und Docker-Versionierung bietet nur Kandidaten mit demselben Suffix an. Das steht in der README schon einmal, als Begründung für die nginx-Einschränkung: Eine suffix-blinde Regel friert ein Abbild stillschweigend ein, sobald sich das Suffix ändert.
Hier heißt das: Sobald Valkey auf alpine3.25 wechselt, wird Renovate keine Aktualisierung mehr anbieten, und nichts meldet es. Das gehört
als Kommentar an die gepinnte Version und in den renovate.json5-Block,
und in die Chart-Seite im Wiki, mit dem Hinweis, dass die Basis von Hand nachgezogen wird.
Wer den Block schreibt, prüft per Probelauf, dass die Regel überhaupt greift — nach der Regel aus der README: Eine gültige Regel ist keine passende Regel, und „keine Aktualisierung" sieht bei einer funktionierenden und einer kaputten Regel gleich aus.
Die Folge von Entscheidung 2, die abgesichert werden muss
Eine fertige Konfigurationszeile im Tresor heißt: Ist das Feld verschrieben — requirepas, falsche Anführungszeichen, leer —, startet Valkey ohne Passwort und ist gesund. Kein Render-Fehler, kein Absturz, ein offener Server.
Deshalb prüft ein Init-Container die gemountete Datei und bricht ab, wenn keine Zeile mit requirepass darin steht. Das ist kein Widerspruch zu Entscheidung 2: Er setzt die Konfiguration nicht zusammen, er prüft sie nur. Das Passwort landet dabei in keiner Ausgabe.
Persistenz und Verdrängung sind ein Paar, nicht zwei Werte
Die Vorgabe noeviction ist für eine Warteschlange richtig und für einen Zwischenspeicher falsch: Bei vollem Speicher lehnt Valkey dann Schreibvorgänge ab, statt kalte Schlüssel zu verwerfen. In values.yaml gehören deshalb die beiden sinnvollen Paare dokumentiert:
maxmemory wird aus dem berechneten Speicher-Limit abgeleitet, und ein konfigurierter Wert über dem Limit bricht den Render mit fail ab — sonst holt das OOM-Kill des Kubelet, was die Verdrängungsregel regeln sollte.
Was gemessen werden muss, nicht angenommen
Kann die Probe überhaupt fehlschlagen?valkey-cli ping antwortet ohne Authentifizierung mit NOAUTH. Ob der Rückgabewert dann ungleich null ist, entscheidet, ob die Probe etwas prüft. Mit absichtlich falschem Passwort gegentesten — eine Probe, die nicht scheitern kann, ist die Fehlerklasse, die dieses Repo am häufigsten teuer bezahlt hat.
Läuft der Pod als uid 999 an, ohne den gosu-Pfad des Entrypoints?
Greift checksum/config? Die Hauptkonfiguration kommt als ConfigMap, also ist die Annotation nach Richtlinie 9 Pflicht. Das Passwort-Secret ist davon nicht erfasst (Helm sieht seinen Inhalt nie) — dafür checksum/secret-ref über das gerenderte OnePasswordItem.
Erster Abnehmer
sure, weil es noch nicht läuft: keine Warteschlange zu verlieren, kein ACL-Nutzer zu entfernen. Das Chart bekommt seine Verbindung als fertige redis://-Adresse aus dem Tresor, also ist keine Änderung am sure-Chart nötig — nur ein Eintrag im Tresor und das Ausrollen der Instanz. Die Reihenfolge für alle weiteren Abnehmer steht im Issue und bleibt unberührt.
Freigegebener Umsetzungsplan (Manager-Sitzung, 2026-09-27). Die Anforderungen im Issue-Text gelten unverändert; hier stehen die verifizierten Fakten, vier Entscheidungen und drei Punkte, die nicht angenommen werden dürfen.
## Verifiziert, nicht aus der Erinnerung
Gegen die Registry abgefragt:
- **Exakte Tags existieren.** Neueste stabile Fassung ist **9.1.2**, es gibt `9.1.2-alpine3.24` (unveränderlich), `9.1.2-alpine` (wandert mit der Alpine-Basis) und `9.1-alpine` (wandert mit jedem Patch). Der im Issue genannte `9.1-alpine` taugt damit nicht als `appVersion`.
- **Das Image setzt `User` nicht — es startet als root.** Wie bei Redis lässt der Entrypoint (`tini -- docker-entrypoint.sh`) die Rechte per gosu auf den Benutzer `valkey` fallen. Startet der Pod direkt als uid 999, wird dieser Schritt übersprungen. **Das ist bei der Umsetzung zu bestätigen**, nicht vorauszusetzen.
- `WorkingDir: /data`, `Cmd: valkey-server`, kein deklariertes Volume.
## Entschieden
1. **`appVersion: 9.1.2-alpine3.24`**, Chart `1.0.0+up9.1.2.alpine3.24` (Bindestriche im Suffix zu Punkten). Vollständig unveränderlicher Tag.
2. **Das Passwort kommt als fertige Konfigurationszeile aus dem 1Password-Eintrag** und wird als Datei gemountet — kein Init-Container, der sie aus der Umgebung zusammensetzt, und kein `--requirepass` in der Prozessliste. Der Feldname wird in `NOTES.txt` namentlich dokumentiert.
3. **Der Install-Test fährt den Pfad *mit* Persistenz.** Das ist der riskante Pfad (PVC, fsGroup auf dem Volume, AOF-Start) und die Vorgabe des Charts. Die Variante ohne Persistenz wird lokal gerendert und im PR **als bekannte Lücke benannt** — die Maschinerie kann nur eine Variante je Chart.
4. **NetworkPolicy standardmäßig an**, mit Wert zum Abschalten und einem Wert, der Verbraucher aus anderen Namensräumen erlaubt. Neues Chart, es gibt keine bestehende Installation, die daran brechen könnte.
## Die Folge von Entscheidung 1, die niemand später als Versäumnis lesen soll
Ein vollständig unveränderlicher Tag bindet die Alpine-Basis mit ein — und **Docker-Versionierung bietet nur Kandidaten mit demselben Suffix an**. Das steht in der README schon einmal, als Begründung für die nginx-Einschränkung: Eine suffix-blinde Regel friert ein Abbild stillschweigend ein, sobald sich das Suffix ändert.
Hier heißt das: Sobald Valkey auf `alpine3.25` wechselt, wird Renovate **keine** Aktualisierung mehr anbieten, und nichts meldet es. Das gehört
- als Kommentar an die gepinnte Version und in den `renovate.json5`-Block,
- und in die Chart-Seite im Wiki, mit dem Hinweis, dass die Basis von Hand nachgezogen wird.
Wer den Block schreibt, prüft per Probelauf, dass die Regel überhaupt greift — nach der Regel aus der README: Eine gültige Regel ist keine passende Regel, und „keine Aktualisierung" sieht bei einer funktionierenden und einer kaputten Regel gleich aus.
## Die Folge von Entscheidung 2, die abgesichert werden muss
Eine fertige Konfigurationszeile im Tresor heißt: Ist das Feld verschrieben — `requirepas`, falsche Anführungszeichen, leer —, startet Valkey **ohne Passwort** und ist gesund. Kein Render-Fehler, kein Absturz, ein offener Server.
**Deshalb prüft ein Init-Container die gemountete Datei** und bricht ab, wenn keine Zeile mit `requirepass ` darin steht. Das ist kein Widerspruch zu Entscheidung 2: Er setzt die Konfiguration nicht zusammen, er prüft sie nur. Das Passwort landet dabei in keiner Ausgabe.
## Persistenz und Verdrängung sind ein Paar, nicht zwei Werte
Die Vorgabe `noeviction` ist für eine Warteschlange richtig und für einen Zwischenspeicher falsch: Bei vollem Speicher lehnt Valkey dann Schreibvorgänge ab, statt kalte Schlüssel zu verwerfen. In `values.yaml` gehören deshalb die beiden sinnvollen Paare dokumentiert:
- **Warteschlange** (Vorgabe): `persistence.enabled: true` + `maxmemory-policy: noeviction`
- **Zwischenspeicher**: `persistence.enabled: false` + `maxmemory-policy: allkeys-lru`
`maxmemory` wird aus dem **berechneten** Speicher-Limit abgeleitet, und ein konfigurierter Wert **über** dem Limit bricht den Render mit `fail` ab — sonst holt das OOM-Kill des Kubelet, was die Verdrängungsregel regeln sollte.
## Was gemessen werden muss, nicht angenommen
1. **Kann die Probe überhaupt fehlschlagen?** `valkey-cli ping` antwortet ohne Authentifizierung mit `NOAUTH`. Ob der Rückgabewert dann ungleich null ist, entscheidet, ob die Probe etwas prüft. **Mit absichtlich falschem Passwort gegentesten** — eine Probe, die nicht scheitern kann, ist die Fehlerklasse, die dieses Repo am häufigsten teuer bezahlt hat.
2. **Läuft der Pod als uid 999 an, ohne den gosu-Pfad des Entrypoints?**
3. **Greift `checksum/config`?** Die Hauptkonfiguration kommt als ConfigMap, also ist die Annotation nach Richtlinie 9 Pflicht. Das Passwort-Secret ist davon nicht erfasst (Helm sieht seinen Inhalt nie) — dafür `checksum/secret-ref` über das gerenderte `OnePasswordItem`.
## Erster Abnehmer
`sure`, weil es noch nicht läuft: keine Warteschlange zu verlieren, kein ACL-Nutzer zu entfernen. Das Chart bekommt seine Verbindung als fertige `redis://`-Adresse aus dem Tresor, also ist **keine Änderung am sure-Chart nötig** — nur ein Eintrag im Tresor und das Ausrollen der Instanz. Die Reihenfolge für alle weiteren Abnehmer steht im Issue und bleibt unberührt.
Nachtrag zu Entscheidung 1: Der unveränderliche Tag bleibt — aber er braucht eine Regex-Versionierung, keine Docker-Versionierung. Vorgabe des Betreuers: Renovate muss einen Wechsel auf alpine3.25 mitbekommen und vorschlagen.
Gemessen: Upstream bindet die Basis an die Version
Ausgewertet über den Tag-Bestand von valkey/valkey:
Je Valkey-Version existiert genau eine Alpine-Basis: die zur Zeit des Releases aktuelle. Ältere Basen (3.19 bis 3.23) tragen nur ältere Valkey-Versionen. Upstream baut alte Versionen also nicht gegen neue Basen nach.
Folge: Ein Wechsel auf alpine3.25 erscheint nicht als 9.1.2-alpine3.25, sondern als 9.1.3-alpine3.25 oder 9.2.0-alpine3.25. Docker-Versionierung, die nur Kandidaten mit demselben Suffix anbietet, würde auf ein 9.1.3-alpine3.24 warten, das nie gebaut wird — das Chart fröre beim nächsten Basiswechsel ein. Der Einwand von vorhin ist damit belegt, nicht bloß vermutet.
Die Regel
Im customManagers-Block eine versioningTemplate mit einem Ausdruck, der beide Versionen als sortierbare Felder erfasst:
major/minor/patch sind Valkey, build/revision sind die Alpine-Basis (3 und 24).
Alle Gruppen sind numerisch. Das ist nach der Regel aus der README zwingend: Renovate liest major, minor, patch, build und revision mit Number.parseInt, und eine nicht-numerische Gruppe wird zu den führenden Ziffern oder zu NaN.
Die Verankerung auf -alpine schließt 9.1.2-trixie und das nackte 9.1.2 aus, ohne sie zu erwähnen.
Kein compatibility-Feld. Es würde genau die Suffix-Bindung wiederherstellen, die hier das Problem ist.
Damit ordnet Renovate über Suffixgrenzen hinweg und bietet 9.1.3-alpine3.25 an.
Was daran ungeprüft bleibt, und wie es geprüft wird
Im Arbeits-Workspace gibt es kein node, npm oder npx — ein Renovate-Probelauf ist hier nicht möglich (bei #34 schon festgestellt, dort konnte auch renovate-config-validator nicht laufen). Die Regel ist also bis zum ersten Lauf auf der Instanz unbelegt, und genau so gehört sie im PR benannt.
Die Abnahme ist damit nicht mit dem Merge erreicht, sondern erst, wenn eines von beiden vorliegt:
ein Probelauf dort, wo node existiert — mit zwei Fixtures nach dem Muster des mediathekarr-Blocks: die echte Version ergibt keine Aktualisierung, eine absichtlich veraltete ergibt genau eine, und zwar über die Suffixgrenze hinweg;
oder der Nachweis am ersten Lauf der Instanz, dass valkey im Dependency Dashboard erscheint.
Das ist nicht Formalie: Bei einer Digest- oder Versionierungsregel sehen eine funktionierende und eine nicht passende Regel identisch aus, solange die gepinnte Version aktuell ist — beide erzeugen nichts. Genau das steht als Lehre im Wiki.
Unverändert
Die übrigen drei Entscheidungen und alles andere aus dem Plan-Kommentar oben bleiben, wie sie sind: unveränderlicher Tag 9.1.2-alpine3.24, Passwort als Konfigurationszeile aus dem Tresor mit prüfendem Init-Container, Install-Test mit Persistenz, NetworkPolicy standardmäßig an.
Nachtrag zu Entscheidung 1: Der unveränderliche Tag bleibt — aber er braucht eine **Regex-Versionierung**, keine Docker-Versionierung. Vorgabe des Betreuers: Renovate muss einen Wechsel auf `alpine3.25` mitbekommen und vorschlagen.
## Gemessen: Upstream bindet die Basis an die Version
Ausgewertet über den Tag-Bestand von `valkey/valkey`:
```
vorhandene Basen: alpine3.19 … alpine3.24
Tags fuer 9.1.2: 9.1.2, 9.1.2-alpine, 9.1.2-alpine3.24, 9.1.2-trixie
Tags fuer 9.0.6: 9.0.6, 9.0.6-alpine, 9.0.6-alpine3.24, 9.0.6-trixie
```
Je Valkey-Version existiert **genau eine** Alpine-Basis: die zur Zeit des Releases aktuelle. Ältere Basen (3.19 bis 3.23) tragen nur ältere Valkey-Versionen. Upstream baut alte Versionen also nicht gegen neue Basen nach.
**Folge:** Ein Wechsel auf `alpine3.25` erscheint nicht als `9.1.2-alpine3.25`, sondern als `9.1.3-alpine3.25` oder `9.2.0-alpine3.25`. Docker-Versionierung, die nur Kandidaten mit demselben Suffix anbietet, würde auf ein `9.1.3-alpine3.24` warten, das nie gebaut wird — das Chart fröre beim nächsten Basiswechsel ein. Der Einwand von vorhin ist damit belegt, nicht bloß vermutet.
## Die Regel
Im `customManagers`-Block eine `versioningTemplate` mit einem Ausdruck, der **beide** Versionen als sortierbare Felder erfasst:
```
regex:^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)-alpine(?<build>\d+)\.(?<revision>\d+)$
```
- `major`/`minor`/`patch` sind Valkey, `build`/`revision` sind die Alpine-Basis (3 und 24).
- Alle Gruppen sind **numerisch**. Das ist nach der Regel aus der README zwingend: Renovate liest `major`, `minor`, `patch`, `build` und `revision` mit `Number.parseInt`, und eine nicht-numerische Gruppe wird zu den führenden Ziffern oder zu `NaN`.
- Die Verankerung auf `-alpine` schließt `9.1.2-trixie` und das nackte `9.1.2` aus, ohne sie zu erwähnen.
- **Kein `compatibility`-Feld.** Es würde genau die Suffix-Bindung wiederherstellen, die hier das Problem ist.
Damit ordnet Renovate über Suffixgrenzen hinweg und bietet `9.1.3-alpine3.25` an.
## Was daran ungeprüft bleibt, und wie es geprüft wird
**Im Arbeits-Workspace gibt es kein node, npm oder npx** — ein Renovate-Probelauf ist hier nicht möglich (bei #34 schon festgestellt, dort konnte auch `renovate-config-validator` nicht laufen). Die Regel ist also bis zum ersten Lauf auf der Instanz **unbelegt**, und genau so gehört sie im PR benannt.
Die Abnahme ist damit nicht mit dem Merge erreicht, sondern erst, wenn eines von beiden vorliegt:
1. ein Probelauf dort, wo node existiert — mit zwei Fixtures nach dem Muster des mediathekarr-Blocks: die echte Version ergibt keine Aktualisierung, eine absichtlich veraltete ergibt genau eine, und zwar über die Suffixgrenze hinweg;
2. oder der Nachweis am ersten Lauf der Instanz, dass `valkey` im Dependency Dashboard erscheint.
Das ist nicht Formalie: Bei einer Digest- oder Versionierungsregel sehen eine funktionierende und eine nicht passende Regel identisch aus, solange die gepinnte Version aktuell ist — beide erzeugen nichts. Genau das steht als Lehre im Wiki.
## Unverändert
Die übrigen drei Entscheidungen und alles andere aus dem Plan-Kommentar oben bleiben, wie sie sind: unveränderlicher Tag `9.1.2-alpine3.24`, Passwort als Konfigurationszeile aus dem Tresor mit prüfendem Init-Container, Install-Test mit Persistenz, NetworkPolicy standardmäßig an.
Entscheidung 1 revidiert (Betreuer): appVersion: 9.1.2-alpine, nicht 9.1.2-alpine3.24. Damit entfällt die Regex-Versionierung aus dem Nachtrag oben ersatzlos.
Warum das besser ist, als ich es vorher dargestellt habe
Ich habe -alpine3.24 als „vollständig unveränderlich" bezeichnet. Das war falsch. Die Erstellungszeitpunkte widerlegen es:
Zwei verschiedene Versionslinien, am selben Tag innerhalb von Minuten gebaut — 9.0.6 ist ein älteres Release. Upstream baut also die gesamte Tag-Matrix periodisch neu, und auch der Tag mit Basis-Nummer wird dabei neu gepusht. Unveränderlich ist an einem Tag nichts; das ist allein ein Digest.
Die Wahl stand also nie zwischen „unveränderlich" und „wandernd", sondern zwischen zwei gleich wandernden Tags mit unterschiedlichem Renovate-Verhalten. Damit ist -alpine die klar bessere Wahl.
Renovate braucht keine versioningTemplate. Docker-Versionierung trennt am ersten Bindestrich, liest 9.1.2 als Version und alpine als Kompatibilitäts-Suffix. Angeboten werden 9.1.3-alpine, 9.2.0-alpine — das Suffix bleibt für immer gleich, also kann die Bindung nie einfrieren.
Der Alpine-Wechsel kommt mit dem nächsten Valkey-Release, und genau so liefert upstream ihn aus: Für jede Version existiert eine Basis, die zur Release-Zeit aktuelle. 9.1.3-alpine trägt die neue Basis, ohne dass wir sie benennen müssen.
Der Block in renovate.json5 ist damit der einfachste im ganzen Repo: Abbildpfad und Standard-Versionierung, kein Sonderfall, nichts zu beweisen. Die unbelegbare Regel aus dem Nachtrag ist vom Tisch — das ist der eigentliche Gewinn, denn ohne node ließ sie sich hier nicht prüfen.
Der Preis, ausdrücklich benannt
Ein wandernder Tag heißt: Wird 9.1.2-alpine neu gebaut, ändert sich das laufende Abbild ohne Änderung im Repository, und nichts meldet es. Das ist dieselbe Klasse, die bei #51 untersucht wurde — dort hat sich der Verdacht zwar nicht bestätigt, die Sorge war aber berechtigt.
Falls das je zählt, steht das Gegenmittel bereit: pinDigests für dieses eine Abbild einschalten. Global ist es seit #34 für custom.regex und helm-values abgeschaltet, eine Ausnahme je Chart ist aber möglich. Das gehört als Satz in den Renovate-Block, damit der nächste Leser die Wahl kennt, statt sie neu herzuleiten.
Unverändert
Passwort als Konfigurationszeile aus dem Tresor mit prüfendem Init-Container, Install-Test mit Persistenz, NetworkPolicy standardmäßig an, Paarbildung von Persistenz und Verdrängungsregel, und die drei Punkte, die gemessen statt angenommen werden.
Entscheidung 1 revidiert (Betreuer): **`appVersion: 9.1.2-alpine`**, nicht `9.1.2-alpine3.24`. Damit entfällt die Regex-Versionierung aus dem Nachtrag oben ersatzlos.
## Warum das besser ist, als ich es vorher dargestellt habe
Ich habe `-alpine3.24` als „vollständig unveränderlich" bezeichnet. **Das war falsch.** Die Erstellungszeitpunkte widerlegen es:
```
9.1-alpine erstellt 2026-09-21T07:46:04Z
9.0.6-alpine3.24 erstellt 2026-09-21T07:49:20Z
```
Zwei verschiedene Versionslinien, am selben Tag innerhalb von Minuten gebaut — 9.0.6 ist ein älteres Release. Upstream baut also die gesamte Tag-Matrix periodisch neu, und **auch der Tag mit Basis-Nummer wird dabei neu gepusht.** Unveränderlich ist an einem Tag nichts; das ist allein ein Digest.
Die Wahl stand also nie zwischen „unveränderlich" und „wandernd", sondern zwischen zwei gleich wandernden Tags mit unterschiedlichem Renovate-Verhalten. Damit ist `-alpine` die klar bessere Wahl.
## Was jetzt gilt
- **`appVersion: 9.1.2-alpine`**, Chart `1.0.0+up9.1.2.alpine`.
- **Renovate braucht keine `versioningTemplate`.** Docker-Versionierung trennt am ersten Bindestrich, liest `9.1.2` als Version und `alpine` als Kompatibilitäts-Suffix. Angeboten werden `9.1.3-alpine`, `9.2.0-alpine` — das Suffix bleibt für immer gleich, also kann die Bindung nie einfrieren.
- **Der Alpine-Wechsel kommt mit dem nächsten Valkey-Release**, und genau so liefert upstream ihn aus: Für jede Version existiert eine Basis, die zur Release-Zeit aktuelle. `9.1.3-alpine` trägt die neue Basis, ohne dass wir sie benennen müssen.
- Der Block in `renovate.json5` ist damit der einfachste im ganzen Repo: Abbildpfad und Standard-Versionierung, kein Sonderfall, nichts zu beweisen. Die unbelegbare Regel aus dem Nachtrag ist vom Tisch — das ist der eigentliche Gewinn, denn ohne node ließ sie sich hier nicht prüfen.
## Der Preis, ausdrücklich benannt
Ein wandernder Tag heißt: Wird `9.1.2-alpine` neu gebaut, ändert sich das laufende Abbild **ohne Änderung im Repository**, und nichts meldet es. Das ist dieselbe Klasse, die bei #51 untersucht wurde — dort hat sich der Verdacht zwar nicht bestätigt, die Sorge war aber berechtigt.
Falls das je zählt, steht das Gegenmittel bereit: `pinDigests` für dieses eine Abbild einschalten. Global ist es seit #34 für `custom.regex` und `helm-values` abgeschaltet, eine Ausnahme je Chart ist aber möglich. Das gehört als Satz in den Renovate-Block, damit der nächste Leser die Wahl kennt, statt sie neu herzuleiten.
## Unverändert
Passwort als Konfigurationszeile aus dem Tresor mit prüfendem Init-Container, Install-Test mit Persistenz, NetworkPolicy standardmäßig an, Paarbildung von Persistenz und Verdrängungsregel, und die drei Punkte, die gemessen statt angenommen werden.
Damit ist belegt, was in der PR-Beschreibung ausdrücklich als unbelegt markiert war — ein Probelauf war hier nicht möglich, weil im Arbeits-Workspace node fehlt. Renovate erkennt den Abbildpfad aus dem customManagers-Block und liest die appVersion als Version. Keine offene Aktualisierung, korrekt: 9.1.2 ist aktuell.
Wichtig ist dabei die Art des Belegs: Das Dashboard führt einen Abschnitt „Detected Dependencies", der alles auflistet, was erkannt wird — nicht nur Fälliges. Ohne diesen Abschnitt hätte „valkey erscheint nicht" nichts bedeutet, weil eine passende und eine nicht passende Regel bei aktueller Version dasselbe Ergebnis liefern: keines. So ist das Fehlen eine Aussage und die Anwesenheit ein Nachweis.
Offen bleibt aus #53 nur noch, dass fsGroup selbst unter den knoten-verzeichnis-gestützten Volumes von k3d nicht bewiesen ist — Schreibbarkeit ja, Eigentümer-Mechanismus nein. Das steht so in values.yaml und auf der Wiki-Seite.
Nachtrag, damit die letzte offene Prüfung aus PR #53 nicht offen bleibt: **Der Renovate-Block greift.**
Im Dependency Dashboard steht jetzt unter „Detected Dependencies":
```
valkey/Chart.yaml (1)
• docker.io/valkey/valkey 9.1.2-alpine
```
Damit ist belegt, was in der PR-Beschreibung ausdrücklich als unbelegt markiert war — ein Probelauf war hier nicht möglich, weil im Arbeits-Workspace node fehlt. Renovate erkennt den Abbildpfad aus dem `customManagers`-Block und liest die `appVersion` als Version. Keine offene Aktualisierung, korrekt: 9.1.2 ist aktuell.
Wichtig ist dabei die **Art** des Belegs: Das Dashboard führt einen Abschnitt „Detected Dependencies", der alles auflistet, was erkannt wird — nicht nur Fälliges. Ohne diesen Abschnitt hätte „valkey erscheint nicht" nichts bedeutet, weil eine passende und eine nicht passende Regel bei aktueller Version dasselbe Ergebnis liefern: keines. So ist das Fehlen eine Aussage und die Anwesenheit ein Nachweis.
Offen bleibt aus #53 nur noch, dass `fsGroup` selbst unter den knoten-verzeichnis-gestützten Volumes von k3d nicht bewiesen ist — Schreibbarkeit ja, Eigentümer-Mechanismus nein. Das steht so in `values.yaml` und auf der Wiki-Seite.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Ein Inhouse-Chart
valkeyfür einzelne Cache- und Warteschlangen-Instanzen, je Anwendung eine — als Ersatz für die geteilte Instanzcluster-redis.Warum
cluster-redisversorgt heute sechs Anwendungen (OneUptime auf Index 2, Outline, drei Paperless-Instanzen; Stand 26.09.2026). Die Trennung läuft über eine ACL-Datei in einem einzigen 1Password-Feld (cluster-redis, Feldusers.acl), und daran hängt alles:sure) ist genau so ein Fall und hat die Namespace-Unterstützung ab Version 7 entfernt.users.aclbetrifft sechs Anwendungen und braucht einen Redis-Neustart, damit sie greift. Der Kommentar incluster-config/fleet-cd/jlab-git/gitea/jlab-git.values.yamlhat genau deshalb schon entschieden, Gitea nicht dort anzuschließen: „Ein weiterer Nutzer waere eine Aenderung an einem Element, an dem alle anderen Verbraucher mit haengen."cluster-config#102): Paperless 3.0 legte Celery-Ergebnisse als unprefixtecelery-task-meta-*-Schlüssel ab, die ACL lehnte sie ab, und die MeldungNoPermissionErrortauchte nur im Worker-Log auf.Mit einer Instanz je Anwendung verschwindet die ACL-Frage ersatzlos: Jede darf
~*, weil sie allein ist.Das Abbild: offiziell, nicht Bitnami
docker.io/valkey/valkey, nichtbitnamicharts/valkey. Der Bitnami-Chart existiert (6.3.3, App 9.1.2), aber Bitnami führt seit August 2025 nur nochlatest— die Folge steht bereits fünfmal incluster-configalstag: "latest@sha256:…", zweimal davon ausgerechnet incluster-redisselbst. Renovate sieht das offizielle Abbild dagegen ohne Kunstgriff (es schlägt gerade einen Digest fürvalkey:9.1-alpinevor).Gewünschte Merkmale
Grundform
scaleDown-Schalter chart-global, wie in den übrigen Inhouse-Charts.values.schema.jsonmitadditionalProperties: false. Hat sich bewährt: ein verschriebener Schlüssel scheitert beim Rendern statt still ignoriert zu werden.NOTES.txt, das die Pflichtfelder des 1Password-Eintrags namentlich aufzählt — nach dem Muster dessure-Charts. Ein fehlendes Feld ergibt sonstCreateContainerConfigErrorund keinen Render-Fehler.Speicher
persistence.enabledumschaltbar. Für Warteschlangen (Sidekiq, Celery) an, für reine Zwischenspeicher aus.longhorn-encrypted-ns, Vorgabe klein (1Gi). Auf verschlüsselten Longhorn-Volumes wird Platz nie zurückgegeben — lieber knapp anfangen.appendonlyals Wert, mit Begründung im Kommentar: Für Warteschlangen ist AOF die haltbarere Wahl, RDB verliert im Zweifel die letzten Minuten.Verdrängung — der wichtigste Standardwert
maxmemory-policyals Wert, Vorgabenoeviction. Nichtallkeys-lru: Unter Druck würde Redis/Valkey sonst die Celery- beziehungsweise Sidekiq-Warteschlange wegwerfen, und die Anwendung bliebe dabei grün. Das war eine der Hypothesen beicluster-config#102und ist hier billiger zu verhindern als zu diagnostizieren.maxmemorypassend zum Speicher-Limit setzen, nicht darüber — sonst holt das OOM-Kill des Kubelet, was die Verdrängungsregel hätte regeln sollen.Zugang
OnePasswordItem, das der Chart selbst rendert (secrets.authSecretRef), niemals als Literal. Feldname imNOTES.txtdokumentiert.--requirepassüber Umgebung, nicht als Argument — sonst steht es in der Prozessliste.Härtung und Ressourcen
runAsNonRoot, feste UID/GID,fsGrouppassend zum Volume,readOnlyRootFilesystem: true, alle Capabilities weg,seccompProfile: RuntimeDefaultim Pod-Kontext (damit Init-Container mitgedeckt sind).emptyDir, soweit nötig.ephemeral-storageaus den Requests berechnet, kein CPU-Limit als Vorgabe.redis-cli pingbeziehungsweisevalkey-cli pingals Exec-Probe. Kein HTTP.Versionierung
<chartVersion>+up<appVersion>, wie alle Inhouse-Charts.Erster Abnehmer:
surecluster-config#110bereitet das Deployment von Sure vor und lässt die Redis-Frage bewusst offen, weil der Chart die Verbindung als fertigeredis://-Adresse aus dem Tresor bekommt. Sure läuft noch nicht — damit ist es der risikofreie Erstversuch für diesen Chart: Es gibt keine Warteschlange zu verlieren und keinen ACL-Nutzer zu entfernen.Danach, je Anwendung verschieden
Reihenfolge immer: Instanz ausrollen →
connection-urlim Tresor umbiegen → Pods neu starten → prüfen → zuletzt den ACL-Nutzer aususers.aclentfernen, damit ein Rückfall möglich bleibt.db1, 3 Schlüssel) — praktisch aufwandsfrei, guter zweiter Schritt.cluster-config#102).db2, 33 426 Schlüssel und wachsend) — zuletzt. Hier heißt Umziehen: Warteschlangen leer laufen lassen oder Verlust in Kauf nehmen.Der gemeinsame Bestand liegt bei 464 MB, fast vollständig OneUptime. In Summe entsteht also kein neuer Speicherbedarf, er verteilt sich nur.
Freigegebener Umsetzungsplan (Manager-Sitzung, 2026-09-27). Die Anforderungen im Issue-Text gelten unverändert; hier stehen die verifizierten Fakten, vier Entscheidungen und drei Punkte, die nicht angenommen werden dürfen.
Verifiziert, nicht aus der Erinnerung
Gegen die Registry abgefragt:
9.1.2-alpine3.24(unveränderlich),9.1.2-alpine(wandert mit der Alpine-Basis) und9.1-alpine(wandert mit jedem Patch). Der im Issue genannte9.1-alpinetaugt damit nicht alsappVersion.Usernicht — es startet als root. Wie bei Redis lässt der Entrypoint (tini -- docker-entrypoint.sh) die Rechte per gosu auf den Benutzervalkeyfallen. Startet der Pod direkt als uid 999, wird dieser Schritt übersprungen. Das ist bei der Umsetzung zu bestätigen, nicht vorauszusetzen.WorkingDir: /data,Cmd: valkey-server, kein deklariertes Volume.Entschieden
appVersion: 9.1.2-alpine3.24, Chart1.0.0+up9.1.2.alpine3.24(Bindestriche im Suffix zu Punkten). Vollständig unveränderlicher Tag.--requirepassin der Prozessliste. Der Feldname wird inNOTES.txtnamentlich dokumentiert.Die Folge von Entscheidung 1, die niemand später als Versäumnis lesen soll
Ein vollständig unveränderlicher Tag bindet die Alpine-Basis mit ein — und Docker-Versionierung bietet nur Kandidaten mit demselben Suffix an. Das steht in der README schon einmal, als Begründung für die nginx-Einschränkung: Eine suffix-blinde Regel friert ein Abbild stillschweigend ein, sobald sich das Suffix ändert.
Hier heißt das: Sobald Valkey auf
alpine3.25wechselt, wird Renovate keine Aktualisierung mehr anbieten, und nichts meldet es. Das gehörtrenovate.json5-Block,Wer den Block schreibt, prüft per Probelauf, dass die Regel überhaupt greift — nach der Regel aus der README: Eine gültige Regel ist keine passende Regel, und „keine Aktualisierung" sieht bei einer funktionierenden und einer kaputten Regel gleich aus.
Die Folge von Entscheidung 2, die abgesichert werden muss
Eine fertige Konfigurationszeile im Tresor heißt: Ist das Feld verschrieben —
requirepas, falsche Anführungszeichen, leer —, startet Valkey ohne Passwort und ist gesund. Kein Render-Fehler, kein Absturz, ein offener Server.Deshalb prüft ein Init-Container die gemountete Datei und bricht ab, wenn keine Zeile mit
requirepassdarin steht. Das ist kein Widerspruch zu Entscheidung 2: Er setzt die Konfiguration nicht zusammen, er prüft sie nur. Das Passwort landet dabei in keiner Ausgabe.Persistenz und Verdrängung sind ein Paar, nicht zwei Werte
Die Vorgabe
noevictionist für eine Warteschlange richtig und für einen Zwischenspeicher falsch: Bei vollem Speicher lehnt Valkey dann Schreibvorgänge ab, statt kalte Schlüssel zu verwerfen. Invalues.yamlgehören deshalb die beiden sinnvollen Paare dokumentiert:persistence.enabled: true+maxmemory-policy: noevictionpersistence.enabled: false+maxmemory-policy: allkeys-lrumaxmemorywird aus dem berechneten Speicher-Limit abgeleitet, und ein konfigurierter Wert über dem Limit bricht den Render mitfailab — sonst holt das OOM-Kill des Kubelet, was die Verdrängungsregel regeln sollte.Was gemessen werden muss, nicht angenommen
valkey-cli pingantwortet ohne Authentifizierung mitNOAUTH. Ob der Rückgabewert dann ungleich null ist, entscheidet, ob die Probe etwas prüft. Mit absichtlich falschem Passwort gegentesten — eine Probe, die nicht scheitern kann, ist die Fehlerklasse, die dieses Repo am häufigsten teuer bezahlt hat.checksum/config? Die Hauptkonfiguration kommt als ConfigMap, also ist die Annotation nach Richtlinie 9 Pflicht. Das Passwort-Secret ist davon nicht erfasst (Helm sieht seinen Inhalt nie) — dafürchecksum/secret-refüber das gerenderteOnePasswordItem.Erster Abnehmer
sure, weil es noch nicht läuft: keine Warteschlange zu verlieren, kein ACL-Nutzer zu entfernen. Das Chart bekommt seine Verbindung als fertigeredis://-Adresse aus dem Tresor, also ist keine Änderung am sure-Chart nötig — nur ein Eintrag im Tresor und das Ausrollen der Instanz. Die Reihenfolge für alle weiteren Abnehmer steht im Issue und bleibt unberührt.Nachtrag zu Entscheidung 1: Der unveränderliche Tag bleibt — aber er braucht eine Regex-Versionierung, keine Docker-Versionierung. Vorgabe des Betreuers: Renovate muss einen Wechsel auf
alpine3.25mitbekommen und vorschlagen.Gemessen: Upstream bindet die Basis an die Version
Ausgewertet über den Tag-Bestand von
valkey/valkey:Je Valkey-Version existiert genau eine Alpine-Basis: die zur Zeit des Releases aktuelle. Ältere Basen (3.19 bis 3.23) tragen nur ältere Valkey-Versionen. Upstream baut alte Versionen also nicht gegen neue Basen nach.
Folge: Ein Wechsel auf
alpine3.25erscheint nicht als9.1.2-alpine3.25, sondern als9.1.3-alpine3.25oder9.2.0-alpine3.25. Docker-Versionierung, die nur Kandidaten mit demselben Suffix anbietet, würde auf ein9.1.3-alpine3.24warten, das nie gebaut wird — das Chart fröre beim nächsten Basiswechsel ein. Der Einwand von vorhin ist damit belegt, nicht bloß vermutet.Die Regel
Im
customManagers-Block eineversioningTemplatemit einem Ausdruck, der beide Versionen als sortierbare Felder erfasst:major/minor/patchsind Valkey,build/revisionsind die Alpine-Basis (3 und 24).major,minor,patch,buildundrevisionmitNumber.parseInt, und eine nicht-numerische Gruppe wird zu den führenden Ziffern oder zuNaN.-alpineschließt9.1.2-trixieund das nackte9.1.2aus, ohne sie zu erwähnen.compatibility-Feld. Es würde genau die Suffix-Bindung wiederherstellen, die hier das Problem ist.Damit ordnet Renovate über Suffixgrenzen hinweg und bietet
9.1.3-alpine3.25an.Was daran ungeprüft bleibt, und wie es geprüft wird
Im Arbeits-Workspace gibt es kein node, npm oder npx — ein Renovate-Probelauf ist hier nicht möglich (bei #34 schon festgestellt, dort konnte auch
renovate-config-validatornicht laufen). Die Regel ist also bis zum ersten Lauf auf der Instanz unbelegt, und genau so gehört sie im PR benannt.Die Abnahme ist damit nicht mit dem Merge erreicht, sondern erst, wenn eines von beiden vorliegt:
valkeyim Dependency Dashboard erscheint.Das ist nicht Formalie: Bei einer Digest- oder Versionierungsregel sehen eine funktionierende und eine nicht passende Regel identisch aus, solange die gepinnte Version aktuell ist — beide erzeugen nichts. Genau das steht als Lehre im Wiki.
Unverändert
Die übrigen drei Entscheidungen und alles andere aus dem Plan-Kommentar oben bleiben, wie sie sind: unveränderlicher Tag
9.1.2-alpine3.24, Passwort als Konfigurationszeile aus dem Tresor mit prüfendem Init-Container, Install-Test mit Persistenz, NetworkPolicy standardmäßig an.Entscheidung 1 revidiert (Betreuer):
appVersion: 9.1.2-alpine, nicht9.1.2-alpine3.24. Damit entfällt die Regex-Versionierung aus dem Nachtrag oben ersatzlos.Warum das besser ist, als ich es vorher dargestellt habe
Ich habe
-alpine3.24als „vollständig unveränderlich" bezeichnet. Das war falsch. Die Erstellungszeitpunkte widerlegen es:Zwei verschiedene Versionslinien, am selben Tag innerhalb von Minuten gebaut — 9.0.6 ist ein älteres Release. Upstream baut also die gesamte Tag-Matrix periodisch neu, und auch der Tag mit Basis-Nummer wird dabei neu gepusht. Unveränderlich ist an einem Tag nichts; das ist allein ein Digest.
Die Wahl stand also nie zwischen „unveränderlich" und „wandernd", sondern zwischen zwei gleich wandernden Tags mit unterschiedlichem Renovate-Verhalten. Damit ist
-alpinedie klar bessere Wahl.Was jetzt gilt
appVersion: 9.1.2-alpine, Chart1.0.0+up9.1.2.alpine.versioningTemplate. Docker-Versionierung trennt am ersten Bindestrich, liest9.1.2als Version undalpineals Kompatibilitäts-Suffix. Angeboten werden9.1.3-alpine,9.2.0-alpine— das Suffix bleibt für immer gleich, also kann die Bindung nie einfrieren.9.1.3-alpineträgt die neue Basis, ohne dass wir sie benennen müssen.renovate.json5ist damit der einfachste im ganzen Repo: Abbildpfad und Standard-Versionierung, kein Sonderfall, nichts zu beweisen. Die unbelegbare Regel aus dem Nachtrag ist vom Tisch — das ist der eigentliche Gewinn, denn ohne node ließ sie sich hier nicht prüfen.Der Preis, ausdrücklich benannt
Ein wandernder Tag heißt: Wird
9.1.2-alpineneu gebaut, ändert sich das laufende Abbild ohne Änderung im Repository, und nichts meldet es. Das ist dieselbe Klasse, die bei #51 untersucht wurde — dort hat sich der Verdacht zwar nicht bestätigt, die Sorge war aber berechtigt.Falls das je zählt, steht das Gegenmittel bereit:
pinDigestsfür dieses eine Abbild einschalten. Global ist es seit #34 fürcustom.regexundhelm-valuesabgeschaltet, eine Ausnahme je Chart ist aber möglich. Das gehört als Satz in den Renovate-Block, damit der nächste Leser die Wahl kennt, statt sie neu herzuleiten.Unverändert
Passwort als Konfigurationszeile aus dem Tresor mit prüfendem Init-Container, Install-Test mit Persistenz, NetworkPolicy standardmäßig an, Paarbildung von Persistenz und Verdrängungsregel, und die drei Punkte, die gemessen statt angenommen werden.
Nachtrag, damit die letzte offene Prüfung aus PR #53 nicht offen bleibt: Der Renovate-Block greift.
Im Dependency Dashboard steht jetzt unter „Detected Dependencies":
Damit ist belegt, was in der PR-Beschreibung ausdrücklich als unbelegt markiert war — ein Probelauf war hier nicht möglich, weil im Arbeits-Workspace node fehlt. Renovate erkennt den Abbildpfad aus dem
customManagers-Block und liest dieappVersionals Version. Keine offene Aktualisierung, korrekt: 9.1.2 ist aktuell.Wichtig ist dabei die Art des Belegs: Das Dashboard führt einen Abschnitt „Detected Dependencies", der alles auflistet, was erkannt wird — nicht nur Fälliges. Ohne diesen Abschnitt hätte „valkey erscheint nicht" nichts bedeutet, weil eine passende und eine nicht passende Regel bei aktueller Version dasselbe Ergebnis liefern: keines. So ist das Fehlen eine Aussage und die Anwesenheit ein Nachweis.
Offen bleibt aus #53 nur noch, dass
fsGroupselbst unter den knoten-verzeichnis-gestützten Volumes von k3d nicht bewiesen ist — Schreibbarkeit ja, Eigentümer-Mechanismus nein. Das steht so invalues.yamlund auf der Wiki-Seite.