Installation¶
This page covers installing the cluster prerequisites and the
bnerd-keycloak-operator itself.
Cluster prerequisites¶
The operator renders raw Kubernetes resources directly — there is no Flux or Helm indirection to satisfy at reconcile time. The following are optional depending on which features you use.
1. Percona PostgreSQL Operator (for managed Postgres)¶
Required only when a KeycloakInstance uses spec.postgres.managed: true.
Install the Percona PG Operator into its own namespace:
helm repo add percona https://percona.github.io/percona-helm-charts/
helm install pg-operator percona/pg-operator \
--namespace pgo \
--create-namespace
Verify:
No silent fallback
If spec.postgres.managed: true is set but this CRD is not installed, the
operator sets the instance to phase: Failed with reason
PerconaCRDMissing rather than falling back to an in-cluster or BYO
database.
2. Ingress controller (for Ingress objects)¶
Required only when spec.ingress.enabled is true (the default). The
operator's Ingress rules default to class nginx (public) and
nginx-internal (admin) — install ingress-nginx or another controller and
set spec.ingress.class / spec.ingress.adminClass to match.
For dev/kind clusters without an ingress controller, set
spec.ingress.enabled: false to get Services only.
3. cert-manager (for TLS)¶
Required only when spec.ingress.clusterIssuer is set. Without it, both
Ingresses are plain HTTP with no TLS annotation.
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.4/cert-manager.yaml
Verify:
Provision a ClusterIssuer (e.g. Let's Encrypt) at the cluster level and
reference its name in spec.ingress.clusterIssuer — see the
KeycloakInstance Guide.
4. Prometheus Operator (optional, for metrics)¶
Required only when a KeycloakInstance sets spec.metrics.serviceMonitor:
true.
If absent, the operator still deploys the instance — it sets
MetricsExporterReady=False/ServiceMonitorCRDMissing as a warning
condition rather than failing.
Installing the operator¶
helm install bnerd-keycloak-operator charts/bnerd-keycloak-operator \
--namespace bnerd-keycloak-system \
--create-namespace \
--set image.tag=0.1.0
The Helm chart installs:
- The operator
Deploymentwith leader election enabled - A
ServiceAccountandClusterRole/Rolewith the minimum RBAC permissions - Both CRDs (
KeycloakInstance,KeycloakVersionMap) fromcharts/bnerd-keycloak-operator/crds/ - The default
KeycloakVersionMap(versionMap.installDefault: true, the chart default) — see Applying the default KeycloakVersionMap below
Verify the operator is running:
This applies the manifests in config/manager/ using kustomize and sets
the operator image. CRDs from config/crd/bases/ are applied first with
make install.
Useful for development or when you want to run directly from a repository
checkout without packaging a Helm chart. With kustomize the default
KeycloakVersionMap is not installed automatically — apply it
explicitly (next section).
Applying the default KeycloakVersionMap¶
The KeycloakVersionMap named default is required for version resolution
— without it, a KeycloakInstance stays Pending with reason
VersionResolutionPending (this is transient, not a failure: the map may
simply not be applied yet).
Installed automatically as part of the chart
(versionMap.installDefault: true, the default). No extra step needed.
Verify it's there:
Set versionMap.installDefault: false if you manage your own
KeycloakVersionMap/default out-of-band, then apply your own copy.
See Upgrades & Version Management for the ladder this default map covers.
Verifying the installation¶
# Operator pod
kubectl get pods -n bnerd-keycloak-system
# CRDs registered
kubectl get crd | grep k8s.bnerd.com
# Default version map
kubectl get kcvm default
# Operator logs (no errors expected)
kubectl logs -n bnerd-keycloak-system deploy/bnerd-keycloak-operator --tail=50
RBAC summary¶
The operator requires cluster-level read access to CRDs (for capability
gating), namespace-scoped create/update/delete access for Secrets,
Services, StatefulSets, Ingresses, PodDisruptionBudgets,
PerconaPGCluster, and ServiceMonitor resources, and patch/create on
Events. The full role is in config/rbac/role.yaml.
The operator runs with a non-root UID (65532), a read-only root filesystem,
and allowPrivilegeEscalation: false by default.