Files
helm-charts/keycloak/Chart.yaml
T
jklein f97e1e6d52 feat(keycloak): Gateway-API as an alternative to the two Ingresses
Group 3 of the #114 sweep, first chart. keycloak has TWO Ingress objects -
the public hostname and the admin hostname - so it gets TWO HTTPRoutes, with
httpRoute.admin.parentRefs falling back to httpRoute.parentRefs exactly as
ingress.admin.className falls back to ingress.className: "which data path" is
a property of the Gateway in this API, not of the route, so an internal
Gateway here is what an internal ingress class is in the other mode.

The admin route stays gated on ingress.admin.enabled, because that value is
not an Ingress switch - it also decides whether KC_HOSTNAME_ADMIN is set on
the Deployment, i.e. whether the admin hostname exists at all. Switching to
Gateway mode therefore must not require turning it off.

FIXED ALONG THE WAY: the admin Ingress did not hang off ingress.enabled.
Measured on origin/main, `helm template -f ci/keycloak/test-values.yaml --set
ingress.enabled=false` emitted kc-keycloak-admin-ingress - so
"ingress.enabled: false" did not mean "no Ingress", and ingress.clusterIssuer
stayed required for an object nobody asked for. It also made Gateway mode
impossible: the admin Ingress would have gone on claiming the admin host next
to the admin HTTPRoute, one host over two data paths, which is the exact
conflict the mutual exclusion exists to prevent. The default render is
unchanged; what changed is a combination that could not be coherent.

WHAT THIS MODE DROPS, MEASURED ON THE LIVE CLUSTER rather than inferred. On
2026-10-12 BOTH of this chart's Ingress objects in jk-cluster carried

    nginx.ingress.kubernetes.io/proxy-buffer-size:    16k
    nginx.ingress.kubernetes.io/proxy-buffers-number: 4

set by the OPERATOR through ingress.annotations and ingress.admin.annotations
- the chart sets neither, which is why reading the chart alone does not reveal
them. The Gateway API has no annotation channel and no counterpart for proxy
buffer sizing; it is implementation policy, not routing. Per decision 1 of
#114 the chart renders no policy object, so this is NAMED and not rebuilt, in
values.yaml, in the schema and in the Gateway branch of NOTES.txt, with the
consequence spelled out in Keycloak's own terms: large headers (JWTs, SAML
assertions, long Set-Cookie chains on the login flow) make a too-small buffer
answer 502 at the PROXY while Keycloak logs the request as successful.

Named and deliberately not touched: four further Ingress objects in the same
namespace (keycloak-realm-*-ingress, with app-root) belong to the Helm release
jk-cluster-config-fleet-cd-keycloak-realm-ingress, i.e. to another repository.
They point at this release's Service under four further hostnames. This chart
renders exactly the two routes its own two Ingresses cover.

Minor: additive, defaults unchanged. Empty helm template diff against
origin/main with ci/keycloak/test-values.yaml.

Part of #114
2026-10-12 20:44:49 +00:00

51 lines
2.5 KiB
YAML

apiVersion: v2
name: keycloak
description: A Helm chart to deploy Keycloak, an OpenID Connect and SAML identity provider, as a two-node cluster on Kubernetes
icon: https://www.keycloak.org/resources/images/icon.svg
type: application
# appVersion is the exact image tag of quay.io/keycloak/keycloak. No "v"
# prefix here - upstream tags are plain three-part versions (26.8.0).
#
# THE TAG LANDSCAPE, AND WHY THIS CHART NEEDS NO VERSION CONSTRAINT. Measured
# on 2026-10-04 against quay.io's tag API, this registry carries four shapes
# side by side:
#
# 1. release tags 26.8.0, 26.7.5, ... <- what we track
# 2. REBUILD tags 26.8.0-0, 26.7.3-1, 26.7.2-2 - the same app
# version rebuilt (base image or CVE fix) without an app-version bump.
# 26.8.0-0 resolves to the SAME manifest digest as 26.8.0.
# 3. floating minor tags 26.8, 26.7, 26.6, ... - they move
# 4. floating names latest, nightly - they move daily
#
# This is the same GENUS of trap as garage's commit-SHA tags and stalwart's
# moving names, and it is the one case in this repo where the answer came out
# the other way: plain `docker` versioning already excludes all three unwanted
# shapes, so the renovate.json5 block carries NO versioningTemplate. Docker
# versioning splits a tag at the first dash and only ever offers candidates
# with the SAME suffix - our value has none, so the -N rebuilds are invisible
# to it - and 26.8 fails on the missing third part while latest/nightly parse
# as no version at all.
#
# THAT IS MEASURED, NOT ASSUMED, and the measurement is written down because
# the next round will otherwise add a constraint "to be safe" (renovate 44.132.5,
# --platform=local --dry-run=lookup against the real registry):
# appVersion 26.8.0 -> updates [], warnings []
# appVersion 26.7.0 -> exactly one: 26.8.0 (minor)
# appVersion 26.7.4 -> exactly two: 26.7.5 (patch), 26.8.0 (minor)
# No run offered a rebuild tag, a floating minor, latest or nightly.
#
# AND THE OTHER HALF, WHICH THE VERSION NUMBER CANNOT CARRY: Keycloak supports
# a rolling update only WITHIN a minor line. A minor jump needs the cluster
# shut down. The global `automerge: true` in renovate.json5 applies here
# anyway - a deliberate acceptance of that risk, not an oversight - so the
# procedure lives in NOTES.txt and on the wiki page instead of in a
# packageRules entry. Read the "MINOR UPGRADES" section of NOTES.txt before
# merging an app-version PR that changes the minor.
version: 1.2.0+up26.8.0
appVersion: "26.8.0"
maintainers:
- name: jklein