PR #121 bumped the three keycloak-k8s-resources URLs 26.0.6 -> 26.8.2. Upstream kubernetes/ at 26.8.2 ships four CRDs; we install two.
RS keycloak-operator-58dff6c4 (quay.io/keycloak/keycloak-operator:26.8.2): 0/1 CrashLoopBackOff, exit 1: Couldn't start informer for keycloaksamlclients.k8s.keycloak.org/v2alpha1 resources ... GET https://10.43.0.1:443/apis/k8s.keycloak.org/v2alpha1/namespaces/keycloak/keycloaksamlclients?resourceVersion=0. Message: Not Found.
kubectl get crd | grep keycloak: only keycloaks and keycloakrealmimports.
RS 78dbb75f64 (26.0.6) still 1/1 (RollingUpdate 25%/25%), keycloak-0/1 on 26.0.6, so SSO is up.
Flux platform stuck Healthy=Unknown "Running health checks for revision main@sha1:e8d2666"; platform-config, apps-wave-*, oauth2-proxy, velero, kured, ... all dependency ... is not ready.
Fix
upstream kubernetes/ @ 26.8.2
before
after
keycloaks.k8s.keycloak.org-v1.yml
yes
yes
keycloakrealmimports.k8s.keycloak.org-v1.yml
yes
yes
keycloakoidcclients.k8s.keycloak.org-v1.yml
no
added
keycloaksamlclients.k8s.keycloak.org-v1.yml
no
added
kubernetes.yml (already ships RBAC for both new kinds)
yes
yes
Both new URLs carry the same # renovate: datasource=github-tags depName=keycloak/keycloak-k8s-resources marker; the custom.regex manager's pattern matches all 5 (run over the file). Renovate can bump URLs, not add them, so the README now says to diff upstream's list on every bump.
Operator memory. Patched (kustomize patches:) from upstream's 450Mi/450Mi to limit 768Mi / request 512Mi. 450Mi is the upstream default and is unchanged at 26.8.2, but on prod the 26.0.6 pod had 154 restarts, lastState: OOMKilled (exit 137, 2026-11-07T23:09:54Z), and kubectl top421Mi/450Mi. 26.8.2 runs 4 controllers (was 2) on Quarkus 3.40.1.1 (was 3.15.1).
No sensitive path touched.
Local gate (pinned toolbox, worktree, both mounts, commit ea30ba8)
kubectl kustomize platform/keycloak: rc 0, 4 CRDs, operator memory 768Mi/512Mi. ci/gate.shrc 3 (UNDETERMINED). Did not run: gitea-settings (no token locally). conformance L2/L3 skipped (no cluster). Passed: spec-immutability, approval-policy (N/A offline), decisions-log (78 entries, this one included), lint, l0, render-golden, l1.
Post-merge checks (operator)
kubectl -n keycloak get crd | grep keycloak: 4 CRDs.
New operator pod 1/1 Ready, no restarts; old ReplicaSet 78dbb75f64 scaled to 0.
keycloak-0/1 roll to quay.io/keycloak/keycloak:26.8.2. Expect a full SSO outage while they roll: the CR's spec.update.strategy defaults to RecreateOnImageChange, and the server migrates the DB schema. Check the last CNPG backup first.
kubectl -n keycloak get keycloak keycloak: Ready=True; KeycloakRealmImport not failing.
Flux platform Ready, then platform-config and apps-wave-* Ready.
SSO login works (Grafana + an oauth2-proxy app + kubectl OIDC).
The next keycloak-passkey-reconciler and keycloak-client-secret-reconciler Jobs succeed. The passkey reconciler encodes 26.0.6 Admin API shapes and was not re-checked against 26.8.2.
26.8.2's Keycloak CRD defaults spec.networkPolicy.enabled: true, so the operator will now create a NetworkPolicy on the Keycloak pods. With no from lists it should allow all sources on HTTP/management. Confirm Gateway traffic and the ServiceMonitor scrape still work.
kubectl top the operator after a week; tune 768Mi.
## Incident (measured 2026-11-08 ~05:57Z, read-only `kubectl --context k3s-prod`)
PR #121 bumped the three `keycloak-k8s-resources` URLs 26.0.6 -> 26.8.2. Upstream `kubernetes/` at 26.8.2 ships **four** CRDs; we install two.
- RS `keycloak-operator-58dff6c4` (quay.io/keycloak/keycloak-operator:26.8.2): 0/1 `CrashLoopBackOff`, exit 1:
`Couldn't start informer for keycloaksamlclients.k8s.keycloak.org/v2alpha1 resources ... GET https://10.43.0.1:443/apis/k8s.keycloak.org/v2alpha1/namespaces/keycloak/keycloaksamlclients?resourceVersion=0. Message: Not Found.`
- `kubectl get crd | grep keycloak`: only `keycloaks` and `keycloakrealmimports`.
- RS `78dbb75f64` (26.0.6) still 1/1 (RollingUpdate 25%/25%), keycloak-0/1 on 26.0.6, so SSO is up.
- Flux `platform` stuck `Healthy=Unknown` "Running health checks for revision main@sha1:e8d2666"; platform-config, apps-wave-*, oauth2-proxy, velero, kured, ... all `dependency ... is not ready`.
## Fix
| upstream `kubernetes/` @ 26.8.2 | before | after |
|---|---|---|
| keycloaks.k8s.keycloak.org-v1.yml | yes | yes |
| keycloakrealmimports.k8s.keycloak.org-v1.yml | yes | yes |
| **keycloakoidcclients.k8s.keycloak.org-v1.yml** | no | **added** |
| **keycloaksamlclients.k8s.keycloak.org-v1.yml** | no | **added** |
| kubernetes.yml (already ships RBAC for both new kinds) | yes | yes |
- Both new URLs carry the same `# renovate: datasource=github-tags depName=keycloak/keycloak-k8s-resources` marker; the custom.regex manager's pattern matches all 5 (run over the file). Renovate can bump URLs, not add them, so the README now says to diff upstream's list on every bump.
- **Operator memory.** Patched (kustomize `patches:`) from upstream's 450Mi/450Mi to **limit 768Mi / request 512Mi**. 450Mi is the upstream default and is unchanged at 26.8.2, but on prod the 26.0.6 pod had **154 restarts**, `lastState: OOMKilled` (exit 137, 2026-11-07T23:09:54Z), and `kubectl top` **421Mi/450Mi**. 26.8.2 runs 4 controllers (was 2) on Quarkus 3.40.1.1 (was 3.15.1).
- No sensitive path touched.
## Local gate (pinned toolbox, worktree, both mounts, commit `ea30ba8`)
`kubectl kustomize platform/keycloak`: rc 0, 4 CRDs, operator memory 768Mi/512Mi.
`ci/gate.sh` **rc 3 (UNDETERMINED)**. Did not run: `gitea-settings` (no token locally). `conformance` L2/L3 skipped (no cluster). Passed: spec-immutability, approval-policy (N/A offline), decisions-log (78 entries, this one included), lint, l0, render-golden, l1.
## Post-merge checks (operator)
1. `kubectl -n keycloak get crd | grep keycloak`: 4 CRDs.
2. New operator pod `1/1 Ready`, no restarts; old ReplicaSet `78dbb75f64` scaled to 0.
3. keycloak-0/1 roll to `quay.io/keycloak/keycloak:26.8.2`. **Expect a full SSO outage while they roll:** the CR's `spec.update.strategy` defaults to `RecreateOnImageChange`, and the server migrates the DB schema. Check the last CNPG backup first.
4. `kubectl -n keycloak get keycloak keycloak`: Ready=True; KeycloakRealmImport not failing.
5. Flux `platform` Ready, then platform-config and apps-wave-* Ready.
6. SSO login works (Grafana + an oauth2-proxy app + kubectl OIDC).
7. The next `keycloak-passkey-reconciler` and `keycloak-client-secret-reconciler` Jobs succeed. The passkey reconciler encodes 26.0.6 Admin API shapes and was **not re-checked** against 26.8.2.
8. 26.8.2's Keycloak CRD defaults `spec.networkPolicy.enabled: true`, so the operator will now create a NetworkPolicy on the Keycloak pods. With no `from` lists it should allow all sources on HTTP/management. Confirm Gateway traffic and the ServiceMonitor scrape still work.
9. `kubectl top` the operator after a week; tune 768Mi.
Handoff: `decisions/2026-11-08-keycloak-operator-crds.md`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
PR #121 bumped the three keycloak-k8s-resources URLs to 26.8.2, but 26.8.2
ships two more CRDs (keycloakoidcclients, keycloaksamlclients). The new
operator fails to start its keycloaksamlclients informer (Not Found) and
CrashLoops, holding Flux `platform` in health checks.
- add both CRD URLs with the same renovate marker/depName
- patch operator memory 450Mi -> limit 768Mi / request 512Mi (26.0.6 was
OOMKilled at 421/450Mi, 154 restarts)
- README/renovate comments: Renovate cannot add CRDs a release introduces
Co-Authored-By: Claude Opus 5.5 <[email protected]>
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.
Incident (measured 2026-11-08 ~05:57Z, read-only
kubectl --context k3s-prod)PR #121 bumped the three
keycloak-k8s-resourcesURLs 26.0.6 -> 26.8.2. Upstreamkubernetes/at 26.8.2 ships four CRDs; we install two.keycloak-operator-58dff6c4(quay.io/keycloak/keycloak-operator:26.8.2): 0/1CrashLoopBackOff, exit 1:Couldn't start informer for keycloaksamlclients.k8s.keycloak.org/v2alpha1 resources ... GET https://10.43.0.1:443/apis/k8s.keycloak.org/v2alpha1/namespaces/keycloak/keycloaksamlclients?resourceVersion=0. Message: Not Found.kubectl get crd | grep keycloak: onlykeycloaksandkeycloakrealmimports.78dbb75f64(26.0.6) still 1/1 (RollingUpdate 25%/25%), keycloak-0/1 on 26.0.6, so SSO is up.platformstuckHealthy=Unknown"Running health checks for revision main@sha1:e8d2666"; platform-config, apps-wave-*, oauth2-proxy, velero, kured, ... alldependency ... is not ready.Fix
kubernetes/@ 26.8.2# renovate: datasource=github-tags depName=keycloak/keycloak-k8s-resourcesmarker; the custom.regex manager's pattern matches all 5 (run over the file). Renovate can bump URLs, not add them, so the README now says to diff upstream's list on every bump.patches:) from upstream's 450Mi/450Mi to limit 768Mi / request 512Mi. 450Mi is the upstream default and is unchanged at 26.8.2, but on prod the 26.0.6 pod had 154 restarts,lastState: OOMKilled(exit 137, 2026-11-07T23:09:54Z), andkubectl top421Mi/450Mi. 26.8.2 runs 4 controllers (was 2) on Quarkus 3.40.1.1 (was 3.15.1).Local gate (pinned toolbox, worktree, both mounts, commit
ea30ba8)kubectl kustomize platform/keycloak: rc 0, 4 CRDs, operator memory 768Mi/512Mi.ci/gate.shrc 3 (UNDETERMINED). Did not run:gitea-settings(no token locally).conformanceL2/L3 skipped (no cluster). Passed: spec-immutability, approval-policy (N/A offline), decisions-log (78 entries, this one included), lint, l0, render-golden, l1.Post-merge checks (operator)
kubectl -n keycloak get crd | grep keycloak: 4 CRDs.1/1 Ready, no restarts; old ReplicaSet78dbb75f64scaled to 0.quay.io/keycloak/keycloak:26.8.2. Expect a full SSO outage while they roll: the CR'sspec.update.strategydefaults toRecreateOnImageChange, and the server migrates the DB schema. Check the last CNPG backup first.kubectl -n keycloak get keycloak keycloak: Ready=True; KeycloakRealmImport not failing.platformReady, then platform-config and apps-wave-* Ready.keycloak-passkey-reconcilerandkeycloak-client-secret-reconcilerJobs succeed. The passkey reconciler encodes 26.0.6 Admin API shapes and was not re-checked against 26.8.2.spec.networkPolicy.enabled: true, so the operator will now create a NetworkPolicy on the Keycloak pods. With nofromlists it should allow all sources on HTTP/management. Confirm Gateway traffic and the ServiceMonitor scrape still work.kubectl topthe operator after a week; tune 768Mi.Handoff:
decisions/2026-11-08-keycloak-operator-crds.md.🤖 Generated with Claude Code