Keycloak Operator¶
A Kubernetes operator that manages Keycloak instances declaratively via Custom
Resource Definitions. Describe the instance you want in YAML, and the
operator renders and owns the StatefulSet, Services, Ingresses, and Secrets —
there is no Helm chart or Flux HelmRelease in the loop.
Who this is for¶
Platform Engineers
You run Kubernetes and want to offer managed Keycloak as a self-service product to internal teams or external customers. Start with Installation, then the KeycloakInstance Guide to understand the full configuration surface.
Managed-Service Operators
You operate Keycloak for multiple tenants and need declarative provisioning, custom themes/SPI providers, and safe version upgrades without handwriting StatefulSet manifests per customer. Start with the Quick Start, then Upgrades & Version Management.
Single-Instance Administrators
You administer one Keycloak for your organisation and want declarative version management and reproducible configuration instead of manual rollouts. Start with the Quick Start.
Not sure yet?
Follow the Quick Start — it deploys a working Keycloak instance with BYO Postgres in a few minutes and introduces both CRDs.
Architecture at a glance¶
flowchart LR
HQ([hq / user\nkubectl apply]) -->|KeycloakInstance CR| K8s[(Kubernetes API)]
K8s --> Op[bnerd-keycloak-operator\nreconcile loop]
Op -->|renders + owns| STS[StatefulSet\nKeycloak pods]
Op -->|renders + owns| Svc[Services\nclient + headless discovery]
Op -->|renders + owns| Ing[Ingresses\npublic + admin]
Op -->|creates/owns| Sec[Operator Secrets\nadmin bootstrap]
Op -->|optional, capability-gated| PG[PerconaPGCluster\nPercona PG Operator]
STS --> Pods[Keycloak Pods]
Svc --> Pods
Ing --> Pods
Sec --> Pods
PG --> Pods
style Op fill:#6366f1,stroke:#4f46e5,color:#fff
style STS fill:#16a34a,stroke:#15803d,color:#fff
Unlike bnerd-gitlab-operator, this operator is a raw-resource engine: it
renders and owns the Keycloak StatefulSet, Services, Ingresses, and Secrets
directly, with no Helm/Flux indirection. See the
KeycloakInstance Guide for the full reconcile
picture.
Why this operator instead of plain manifests?¶
| Concern | Plain manifests | This Operator |
|---|---|---|
| Backend provisioning | Manual PerconaPGCluster setup |
postgres.managed: true auto-provisions, capability-gated on the Percona CRD |
| Credential management | Inline or manually-created Secrets | Admin bootstrap credentials always via Secret — generated once, or bring-your-own |
| Theme / SPI providers | Custom image builds baking JARs into the Keycloak image | spec.providers injects JARs via initContainers — no custom Keycloak image needed |
| Version upgrades | Manual rolling update, no cross-minor safety | Bump spec.version; same-minor rolls in place, cross-minor is a supervised drain-first recreate |
| Downgrade safety | Your responsibility | Downgrades are refused by default (break-glass annotation to override) |
| Status observability | kubectl get pods + logs |
CRD status subresource: phase, host, observedVersion, conditions |
CRDs at a glance¶
| CRD | Scope | Short name | Purpose |
|---|---|---|---|
| KeycloakInstance | Namespaced | kci |
One CR = one Keycloak deployment. The primary workload resource. |
| KeycloakVersionMap | Cluster | kcvm |
Maps Keycloak version strings/aliases to container images. |
API version: k8s.bnerd.com/v1alpha1.
Quick links¶
- Quick Start — Deploy your first Keycloak instance in a few minutes
- Installation — Install the operator via Helm or kustomize
- KeycloakInstance Guide — Hosts, ingress/TLS, providers, Postgres, admin credentials
- Upgrades & Version Management — The version map, patch vs. cross-minor upgrades, downgrade guard
- Troubleshooting — Diagnose a stuck or failed instance
- CRD Reference — Full field reference for both CRDs