keycloak: die vier Realm-Hostnamen als Chart-Feature statt in cluster-config #122

Closed
opened 2026-10-13 11:00:26 +02:00 by jlab-bot · 1 comment
Member

Vier Hostnamen bedienen den keycloak-Chart, zeigen auf seinen eigenen Service — und gehören einem anderen Repository. Der Chart erwähnt sie nirgends, seine Wiki-Seite auch nicht. Wer den Chart liest, kann sie nicht finden.

Aufgefallen beim Gateway-API-Sweep (#114, PR #120): der Agent hat die laufenden Ingress-Objekte gelesen und die vier als Nebenbefund gemeldet. Richtig nicht angefasst — sie sind nicht seine. Dass sie es sein könnten, ist die Frage hier.

Gemessener Stand

Namensraum keycloak, vier Objekte neben den zwei chart-eigenen. Sie gehören der Helm-Release jk-cluster-config-fleet-cd-keycloak-realm-ingress, also Fleet aus jk-cluster-config — nicht der Release keycloak.

Objekt Host Realm (app-root) TLS-Secret cluster-issuer proxy-buffer
keycloak-realm-bekemeyer-klein-ingress bk.id.bekemeyer-klein.de bekemeyer-klein tls-id-wildcard-ingress nein 16k / 4
keycloak-realm-muth-event-ingress muth-event.id.bekemeyer-klein.de muth-event tls-id-wildcard-ingress nein 16k / 4
keycloak-realm-mail-ingress id.mail.bekemeyer-klein.de mail tls-id-mail-ingress letsencrypt-issuer 16k / 4
keycloak-realm-jk-family-ingress id.klein.pub klein-family tls-id-klein-pub-ingress letsencrypt-issuer keine

Alle vier: className: nginx, eine Regel path: / pathType: Prefix auf keycloak-keycloak-service:8080 — denselben Service, den dieser Chart rendert.

Was exakt übersetzbar ist

app-root hat ein Gegenstück, und zwar das, das mit #119 gerade hier gelandet ist. ingress-nginx rendert die Annotation als (rootfs/etc/nginx/template/nginx.tmpl:1000, controller-v1.14.5):

if ($uri = /) {
    return 302 $scheme://$http_host/realms/<realm>/account/;
}

Eine 302 auf genau /. In der Gateway-API:

rules:
  - matches:
      - path: { type: Exact, value: / }
    filters:
      - type: RequestRedirect
        requestRedirect:
          path: { type: ReplaceFullPath, replaceFullPath: /realms/<realm>/account/ }
          statusCode: 302
  - matches:
      - path: { type: PathPrefix, value: / }
    backendRefs:
      - name: <release>-keycloak-service
        port: 8080

Zwei Regeln je Host. Die Exact-Regel gewinnt auf / nach der Vorrangregel der Spezifikation ("Exact" path match vor "Prefix" path match with largest number of characters), unabhängig von der Listenposition — die Reihenfolge ist also keine Zusage, auf die sich jemand verlassen muss.

Billiger als bei qBittorrent in #119: 301 und 302 sind beide Support: Core. Die Portabilitätsfalle, die dort 308 ausschloss (ein abgelehnter Extended-Statuscode setzt Accepted: False auf die ganze Route), besteht hier nicht. statusCode trotzdem ausschreiben — die Vorgabe des Feldes ist 302, und ein Wert, der nur zufällig stimmt, ist keine Dokumentation.

TLS fällt aus der Zuständigkeit. Im Gateway-Modus rendert der Chart kein Zertifikat. Zwei der vier Hosts liegen unter *.id.bekemeyer-klein.de, das der bestehende Wildcard bereits deckt — ein Wildcard-Listener plus zwei benannte ersetzt drei Certificates in jk-cluster-config.

Was nicht übersetzbar ist

proxy-buffer-size: 16k und proxy-buffers-number: 4, getragen von drei der vier. Kein Gegenstück in der Gateway-API; Puffergrößen sind implementierungsspezifische Politik, und nach Entscheidung 1 von #114 rendert kein Chart ein Policy-Objekt. Bei Keycloak ist das nicht kosmetisch: große Header (JWT, SAML) enden dann als 502 des Proxys, nicht als Meldung der Anwendung. Derselbe Verlust, den PR #120 für das chart-eigene Paar schon im Gateway-Zweig von NOTES.txt benennt.

Zwei strukturelle Punkte

Vier Route-Objekte, nicht eines mit vier Hostnamen. spec.hostnames gilt für das ganze Objekt, und die Matches einer Regel sind pfadbasiert — innerhalb einer Route lässt sich nicht nach Hostname unterscheiden, und alle vier Realms würden auf Exact: / passen. Das Keycloak-Template aus #120 rendert schon zwei Route-Objekte (Haupt- und Admin-Host), die Form ist also vorhanden und muss nicht erfunden werden.

Der Realm folgt nicht aus dem Hostnamen. id.klein.pub zeigt auf klein-family, nicht auf jk-family — der Objektname führt in die Irre. Es braucht echte Daten, keine Ableitung.

Der Preis, und er sitzt nicht beim HTTPRoute

Das ist kein Übersetzen, sondern ein neues Chart-Feature. Dieses Repository hat eine Konvention gegen modus-asymmetrische Features — mit genau dieser Begründung hat der Gruppe-3-Agent in #120 keine CORS-Werte eingebaut, obwohl die Gateway-API einen CORS-Filter hat. Ein keycloak.realmHosts müsste also in beiden Modi rendern: vier Ingress-Objekte mit app-root und vier HTTPRoutes. Die HTTPRoute-Hälfte ist die leichte.

Und die Ingress-Hälfte passt nicht auf die Ingress-Konvention dieses Repositories. Die lautet: cert-manager-Annotation immer gesetzt, TLS-Secret tls-<release>-<chart>-ingress. Diese vier Objekte verwenden drei fremde Secret-Namen und setzen den Issuer nur auf zwei — dieselbe bewusste Auslassung wie beim qBittorrent-Objekt in freesailarr, damit pro Secret nur ein Certificate angefordert wird. Jeder Eintrag braucht also ein eigenes tlsSecretName und einen optionalen Issuer, und das ist eine Abweichung von der Konvention, die begründet und im Style-Guide vermerkt gehört.

Vorgeschlagene Form

keycloak:
  realmHosts: []      # Vorgabe leer: kein Objekt, Render unverändert
  # - host: bk.id.bekemeyer-klein.de
  #   realm: bekemeyer-klein
  #   tlsSecretName: tls-id-wildcard-ingress
  #   clusterIssuer: ""          # leer = keine Annotation, Zertifikat kommt woanders her
  #   annotations: {}            # je Eintrag, für proxy-buffer-size etc.

Leere Vorgabe, additiv, kein Wert wird verpflichtend → Minor. Zu belegen mit einem leeren helm template-Diff gegen origin/main für die Vorgaben.

annotations je Eintrag statt chart-global, weil drei der vier das Puffer-Paar tragen und einer nicht — eine globale Annotation könnte diesen Unterschied nicht ausdrücken.

Was zu klären ist, bevor etwas gebaut wird

Hängt in jk-cluster-config etwas namentlich an diesen Objekten? Fleet-Bundle, Monitoring, eine objectset-Referenz. Ungeprüft — ich habe nur den Namensraum keycloak gelesen, nicht das zweite Repository.

Denn ein Umzug ist eine Migration, kein Edit: die Objekte werden in einem Repository gelöscht und aus einem anderen erzeugt, mit einem Fenster, in dem es beide oder keines gibt. Beides ist schlecht — zwei Ingresses auf demselben Host und Pfad weist das Admission-Webhook von ingress-nginx ab und hinterlässt ein Fleet-Bundle in ErrApplied, bis forceSyncGeneration erhöht wird (so steht es in ytdlp-web-players Kollisions-fail, dort gemessen). Die Reihenfolge gehört also festgelegt, bevor jemand anfängt.

Grundlage

PR #120 ist gemergt, das keycloak.httproute.yaml-Template liegt also auf main und der Chart steht auf 1.2.0+up26.8.0. Die Form, auf die dieses Issue aufsetzt — zwei Route-Objekte für Haupt- und Admin-Host, Gateway-Zweig in NOTES.txt, der den Verlust der proxy-buffer-Annotationen benennt —, ist vorhanden und muss nicht erfunden werden.

Nicht in diesem Umfang

Das Gateway selbst, seine Listener und deren Zertifikate — die gehören nach cluster-config, und ein Wildcard-Listener für *.id.bekemeyer-klein.de ist dort zu entscheiden, nicht hier.

Vier Hostnamen bedienen den `keycloak`-Chart, zeigen auf **seinen eigenen Service** — und gehören einem anderen Repository. Der Chart erwähnt sie nirgends, seine Wiki-Seite auch nicht. Wer den Chart liest, kann sie nicht finden. Aufgefallen beim Gateway-API-Sweep (#114, PR #120): der Agent hat die laufenden Ingress-Objekte gelesen und die vier als Nebenbefund gemeldet. Richtig nicht angefasst — sie sind nicht seine. Dass sie es sein *könnten*, ist die Frage hier. ## Gemessener Stand Namensraum `keycloak`, vier Objekte neben den zwei chart-eigenen. Sie gehören der Helm-Release `jk-cluster-config-fleet-cd-keycloak-realm-ingress`, also Fleet aus `jk-cluster-config` — nicht der Release `keycloak`. | Objekt | Host | Realm (`app-root`) | TLS-Secret | `cluster-issuer` | `proxy-buffer` | | --- | --- | --- | --- | --- | --- | | `keycloak-realm-bekemeyer-klein-ingress` | `bk.id.bekemeyer-klein.de` | `bekemeyer-klein` | `tls-id-wildcard-ingress` | **nein** | 16k / 4 | | `keycloak-realm-muth-event-ingress` | `muth-event.id.bekemeyer-klein.de` | `muth-event` | `tls-id-wildcard-ingress` | **nein** | 16k / 4 | | `keycloak-realm-mail-ingress` | `id.mail.bekemeyer-klein.de` | `mail` | `tls-id-mail-ingress` | `letsencrypt-issuer` | 16k / 4 | | `keycloak-realm-jk-family-ingress` | `id.klein.pub` | **`klein-family`** | `tls-id-klein-pub-ingress` | `letsencrypt-issuer` | **keine** | Alle vier: `className: nginx`, eine Regel `path: / pathType: Prefix` auf **`keycloak-keycloak-service:8080`** — denselben Service, den dieser Chart rendert. ## Was exakt übersetzbar ist **`app-root` hat ein Gegenstück, und zwar das, das mit #119 gerade hier gelandet ist.** ingress-nginx rendert die Annotation als (`rootfs/etc/nginx/template/nginx.tmpl:1000`, `controller-v1.14.5`): ```nginx if ($uri = /) { return 302 $scheme://$http_host/realms/<realm>/account/; } ``` Eine 302 auf genau `/`. In der Gateway-API: ```yaml rules: - matches: - path: { type: Exact, value: / } filters: - type: RequestRedirect requestRedirect: path: { type: ReplaceFullPath, replaceFullPath: /realms/<realm>/account/ } statusCode: 302 - matches: - path: { type: PathPrefix, value: / } backendRefs: - name: <release>-keycloak-service port: 8080 ``` Zwei Regeln je Host. Die `Exact`-Regel gewinnt auf `/` nach der Vorrangregel der Spezifikation (`"Exact" path match` vor `"Prefix" path match with largest number of characters`), **unabhängig von der Listenposition** — die Reihenfolge ist also keine Zusage, auf die sich jemand verlassen muss. **Billiger als bei qBittorrent in #119:** `301` **und** `302` sind beide `Support: Core`. Die Portabilitätsfalle, die dort 308 ausschloss (ein abgelehnter Extended-Statuscode setzt `Accepted: False` auf die **ganze** Route), besteht hier nicht. `statusCode` trotzdem ausschreiben — die Vorgabe des Feldes ist 302, und ein Wert, der nur zufällig stimmt, ist keine Dokumentation. **TLS fällt aus der Zuständigkeit.** Im Gateway-Modus rendert der Chart kein Zertifikat. Zwei der vier Hosts liegen unter `*.id.bekemeyer-klein.de`, das der bestehende Wildcard bereits deckt — ein Wildcard-Listener plus zwei benannte ersetzt drei Certificates in `jk-cluster-config`. ## Was nicht übersetzbar ist `proxy-buffer-size: 16k` und `proxy-buffers-number: 4`, getragen von **drei der vier**. Kein Gegenstück in der Gateway-API; Puffergrößen sind implementierungsspezifische Politik, und nach Entscheidung 1 von #114 rendert kein Chart ein Policy-Objekt. Bei Keycloak ist das nicht kosmetisch: große Header (JWT, SAML) enden dann als **502 des Proxys**, nicht als Meldung der Anwendung. Derselbe Verlust, den PR #120 für das chart-eigene Paar schon im Gateway-Zweig von `NOTES.txt` benennt. ## Zwei strukturelle Punkte **Vier Route-Objekte, nicht eines mit vier Hostnamen.** `spec.hostnames` gilt für das ganze Objekt, und die Matches einer Regel sind pfadbasiert — innerhalb einer Route lässt sich nicht nach Hostname unterscheiden, und alle vier Realms würden auf `Exact: /` passen. Das Keycloak-Template aus #120 rendert schon zwei Route-Objekte (Haupt- und Admin-Host), die Form ist also vorhanden und muss nicht erfunden werden. **Der Realm folgt nicht aus dem Hostnamen.** `id.klein.pub` zeigt auf `klein-family`, nicht auf `jk-family` — der Objektname führt in die Irre. Es braucht echte Daten, keine Ableitung. ## Der Preis, und er sitzt nicht beim HTTPRoute Das ist **kein Übersetzen, sondern ein neues Chart-Feature.** Dieses Repository hat eine Konvention gegen modus-asymmetrische Features — mit genau dieser Begründung hat der Gruppe-3-Agent in #120 *keine* CORS-Werte eingebaut, obwohl die Gateway-API einen `CORS`-Filter hat. Ein `keycloak.realmHosts` müsste also **in beiden Modi** rendern: vier Ingress-Objekte mit `app-root` *und* vier HTTPRoutes. Die HTTPRoute-Hälfte ist die leichte. Und die Ingress-Hälfte passt **nicht** auf die Ingress-Konvention dieses Repositories. Die lautet: cert-manager-Annotation immer gesetzt, TLS-Secret `tls-<release>-<chart>-ingress`. Diese vier Objekte verwenden **drei fremde Secret-Namen** und setzen den Issuer nur auf zwei — dieselbe bewusste Auslassung wie beim qBittorrent-Objekt in `freesailarr`, damit pro Secret nur **ein** Certificate angefordert wird. Jeder Eintrag braucht also ein eigenes `tlsSecretName` und einen optionalen Issuer, und das ist eine Abweichung von der Konvention, die begründet und im Style-Guide vermerkt gehört. ## Vorgeschlagene Form ```yaml keycloak: realmHosts: [] # Vorgabe leer: kein Objekt, Render unverändert # - host: bk.id.bekemeyer-klein.de # realm: bekemeyer-klein # tlsSecretName: tls-id-wildcard-ingress # clusterIssuer: "" # leer = keine Annotation, Zertifikat kommt woanders her # annotations: {} # je Eintrag, für proxy-buffer-size etc. ``` Leere Vorgabe, additiv, kein Wert wird verpflichtend → **Minor**. Zu belegen mit einem leeren `helm template`-Diff gegen `origin/main` für die Vorgaben. `annotations` je Eintrag statt chart-global, weil drei der vier das Puffer-Paar tragen und einer nicht — eine globale Annotation könnte diesen Unterschied nicht ausdrücken. ## Was zu klären ist, bevor etwas gebaut wird **Hängt in `jk-cluster-config` etwas namentlich an diesen Objekten?** Fleet-Bundle, Monitoring, eine `objectset`-Referenz. **Ungeprüft** — ich habe nur den Namensraum `keycloak` gelesen, nicht das zweite Repository. Denn ein Umzug ist eine **Migration, kein Edit**: die Objekte werden in einem Repository gelöscht und aus einem anderen erzeugt, mit einem Fenster, in dem es beide oder keines gibt. Beides ist schlecht — zwei Ingresses auf demselben Host und Pfad weist das Admission-Webhook von ingress-nginx ab und hinterlässt ein Fleet-Bundle in `ErrApplied`, bis `forceSyncGeneration` erhöht wird (so steht es in `ytdlp-web-player`s Kollisions-`fail`, dort gemessen). Die Reihenfolge gehört also festgelegt, bevor jemand anfängt. ## Grundlage **PR #120 ist gemergt**, das `keycloak.httproute.yaml`-Template liegt also auf `main` und der Chart steht auf `1.2.0+up26.8.0`. Die Form, auf die dieses Issue aufsetzt — zwei Route-Objekte für Haupt- und Admin-Host, Gateway-Zweig in `NOTES.txt`, der den Verlust der `proxy-buffer`-Annotationen benennt —, ist vorhanden und muss nicht erfunden werden. ## Nicht in diesem Umfang Das Gateway selbst, seine Listener und deren Zertifikate — die gehören nach `cluster-config`, und ein Wildcard-Listener für `*.id.bekemeyer-klein.de` ist dort zu entscheiden, nicht hier.
Author
Member

Nachtrag: die Migration, die dieses Issue als Unbekannte führt, ist einmal gelaufen

Der Abschnitt „Was zu klären ist" nennt den Umzug eine Migration, kein Edit — mit einem Fenster, in dem es beide Objekte oder keines gibt, und mit dem Hinweis, dass zwei Ingresses auf demselben Host und Pfad das Admission-Webhook von ingress-nginx abweisen und ein Fleet-Bundle in ErrApplied hinterlassen.

Am 13.10.2026 ist freesailarr.jk-dev.de von Ingress auf Gateway umgeschwenkt, und zwar ohne Ausfall. Gemessen danach: keine Ingress-Objekte dieses Charts mehr, die Apps antworten über das Gateway mit korrekten Basispfaden, und die Umleitung kommt aus der Chart-Regel statt aus der Betreiber-Annotation.

Das beseitigt die Unbekannte nicht ganz, aber es verkleinert sie erheblich:

  • Der Modus-Wechsel eines Hosts ist durchführbar — einmal belegt, in diesem Cluster, mit dieser Gateway-Implementierung.
  • Der hier beschriebene Konfliktfall ist ein anderer. Bei freesailarr lag das alte und das neue Objekt in derselben Helm-Release; der Wechsel war ein helm upgrade, der die Ingress entfernt und die Route anlegt — es gab nie beide. Bei den Realm-Hostnamen liegen sie in zwei Repositories und zwei Releases, und genau daraus entsteht das Fenster. Der Präzedenzfall deckt also die Mechanik, nicht die Koordination.

Daraus folgt für den Umfang dieses Issues eine Präzisierung: Wenn der Chart die Realm-Hostnamen übernimmt, ist die saubere Reihenfolge erst die Objekte in jk-cluster-config entfernen, dann den Chart mit gesetztem realmHosts aufspielen — nicht umgekehrt und nicht gleichzeitig. Dann ist das Fenster eine kurze Nichterreichbarkeit statt eines abgewiesenen Objekts mit einem Fleet-Bundle in ErrApplied, das bis zum Erhöhen von forceSyncGeneration stehen bleibt.

Die Frage, ob in jk-cluster-config etwas namentlich an den vier Objekten hängt, bleibt unverändert ungeprüft — ich habe nur den Namensraum keycloak gelesen, nicht das zweite Repository.

# Nachtrag: die Migration, die dieses Issue als Unbekannte führt, ist einmal gelaufen Der Abschnitt „Was zu klären ist" nennt den Umzug eine **Migration, kein Edit** — mit einem Fenster, in dem es beide Objekte oder keines gibt, und mit dem Hinweis, dass zwei Ingresses auf demselben Host und Pfad das Admission-Webhook von ingress-nginx abweisen und ein Fleet-Bundle in `ErrApplied` hinterlassen. Am 13.10.2026 ist `freesailarr.jk-dev.de` von Ingress auf Gateway umgeschwenkt, und zwar **ohne Ausfall**. Gemessen danach: keine Ingress-Objekte dieses Charts mehr, die Apps antworten über das Gateway mit korrekten Basispfaden, und die Umleitung kommt aus der Chart-Regel statt aus der Betreiber-Annotation. Das beseitigt die Unbekannte nicht ganz, aber es verkleinert sie erheblich: - **Der Modus-Wechsel eines Hosts ist durchführbar** — einmal belegt, in diesem Cluster, mit dieser Gateway-Implementierung. - **Der hier beschriebene Konfliktfall ist ein anderer.** Bei `freesailarr` lag das alte und das neue Objekt in **derselben** Helm-Release; der Wechsel war ein `helm upgrade`, der die Ingress entfernt und die Route anlegt — es gab nie beide. Bei den Realm-Hostnamen liegen sie in **zwei Repositories** und zwei Releases, und genau daraus entsteht das Fenster. Der Präzedenzfall deckt also die Mechanik, nicht die Koordination. Daraus folgt für den Umfang dieses Issues eine Präzisierung: Wenn der Chart die Realm-Hostnamen übernimmt, ist die saubere Reihenfolge **erst** die Objekte in `jk-cluster-config` entfernen, **dann** den Chart mit gesetztem `realmHosts` aufspielen — nicht umgekehrt und nicht gleichzeitig. Dann ist das Fenster eine kurze Nichterreichbarkeit statt eines abgewiesenen Objekts mit einem Fleet-Bundle in `ErrApplied`, das bis zum Erhöhen von `forceSyncGeneration` stehen bleibt. Die Frage, ob in `jk-cluster-config` etwas **namentlich** an den vier Objekten hängt, bleibt unverändert **ungeprüft** — ich habe nur den Namensraum `keycloak` gelesen, nicht das zweite Repository.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jlab-cluster/helm-charts#122