Kubernetes / Infinispan rolling update at 26.7.3
- Upgrade
- 26.0.0 → 26.7.3
- Scale
- master realm + lab realm (1 user)
- Database
- PostgreSQL 16, single pod (StatefulSet), in-cluster
- Topology
- Deployment replicas: 2, maxSurge=1, maxUnavailable=0
- Host
- laptop (16 vCPU, 31 GB RAM)
- Condition
- Kubernetes / Infinispan, re-run at the 26.7.3 target
Environment
| Field | Value |
|---|---|
| Keycloak from → to | 26.0.0 → 26.7.3 |
| Distribution / start mode | quay.io/keycloak/keycloak, start w/ external DB |
| Database | PostgreSQL 16, single pod (StatefulSet), in-cluster |
| Cache | embedded Infinispan, KC_CACHE_STACK=kubernetes (DNS_PING) |
| Cluster | kind kclab (k8s v1.37.0, kind v0.33.0) — note: laptop, not the k3d box |
| Topology | Deployment replicas: 2, maxSurge=1, maxUnavailable=0 |
| Host | laptop (16 vCPU, 31 GB RAM) |
| JVM heap | -Xms256m -Xmx1g |
| Dataset | master realm + lab realm (1 user) |
Result — rolling update completes cleanly, cache still partitions
Timeline (from pod logs):
| t | event |
|---|---|
| 0s | set image → new 26.7.3 pod (Infinispan v=16.0.14) starts, old 26.0.0 pods (v=15.0.8) still serving |
| ~25s | new pod forms a 1-member cluster (v=16.0.14); no members discovered |
| ~36s | second new pod starts; first new pod ready; first old pod terminated |
| ~47s | the two new pods form a 2-member cluster (v=16.0.14) |
| ~57s | last old pod terminated; rollout complete |
| end | migration_model = 26.7.3, both pods ready |
Findings
-
Schema migration stays additive at 26.7.3 —
migration_modelreached 26.7.3, old pods logged no schema errors, rollout completed undermaxUnavailable=0. The database layer is safe; the cache is the risk, as at 26.7.1. -
The cache still partitions during the transition. 26.7.3 ships Infinispan 16.0.14 (26.7.1 was 16.0.12; 26.0.0 is 15.0.8). The new pods never merge with the old
v=15.0.8cluster — they form a separate 1-member cluster and only merge with each other once the old pods are gone. Same operational consequence as the 26.7.1 record: sessions are not shared between old and new pods during the window. -
New signal: 26.7.3 enables JGroups encryption (mTLS). The 26.7.3 pod logs
JGroups Encryption enabled (mTLS). This is a second axis of inter-version incompatibility in addition to the Infinispan/JGroups version bump, and belongs in the pre-flight as a thing to check when crossing into 26.7.x. -
kind vs k3d: a discovery race at first boot. On kind, two pods started simultaneously each became a 1-member cluster (
no members discovered after 2.00s) and did not merge on their own; deleting one pod triggered DNS_PING re-discovery and the 2-member cluster formed. The k3d run (original record) clustered on first boot. This is an environment/timing difference, not a Keycloak change — but it means the baseline "2-member cluster" must be verified explicitly before relying on a kind run. -
Cross-pod session sharing confirmed at the final 26.7.3 state — a refresh token issued on pod A was accepted on pod B (HTTP 200), proving the healed 2-member cluster shares the session cache.
What is still not tested
- Two new pods migrating concurrently (here
maxSurge=1made them sequential). - Functional session stranding inside the transition window (issuing on an
old pod and failing on a new pod) — the partition is proven at the cluster-view
level, not the HTTP level. The explicit
JGRP000006 cookie does not matchline from the 26.7.1 record was in the old pods' logs, which the Deployment deletes on termination; reproducing it cleanly needs live log capture during the rollout. - The 26.7.3 default
jdbc-pingstack (this run pinnedkubernetesto keep the version the only variable).