Skip to content

Troubleshooting

Reference for diagnosing a KeycloakInstance that is stuck, failing, or not behaving as expected. Start with State inspection, then match your symptom in the sections below.

State inspection — start here

NS=my-keycloak
NAME=my-keycloak

# 1. Phase and print columns
kubectl get kci $NAME -n $NS

# 2. Full status including conditions
kubectl describe kci $NAME -n $NS

# 3. Conditions as JSON (often the most direct answer)
kubectl get kci $NAME -n $NS \
  -o jsonpath='{.status.conditions}' | jq

# 4. StatefulSet rollout status
kubectl get statefulset $NAME -n $NS
kubectl rollout status statefulset/$NAME -n $NS

# 5. Keycloak pods
kubectl get pods -n $NS
kubectl describe pod -n $NS <stuck-pod-name>

# 6. Managed Postgres (if postgres.managed: true)
kubectl get perconapgcluster ${NAME}-pg -n $NS
kubectl describe perconapgcluster ${NAME}-pg -n $NS

Where are the logs?

Component Command
Operator kubectl logs -n bnerd-keycloak-system deploy/bnerd-keycloak-operator --tail=200
Keycloak pod kubectl logs -n $NS $NAME-0 --tail=200
Percona PG operator kubectl logs -n pgo deploy/percona-postgresql-operator --tail=200

Phase: Pending

Symptom: kubectl get kci shows Pending for more than a few minutes.

Causes:

  1. KeycloakVersionMap/default not found, or the version/alias not (yet) present in it — condition reason VersionResolutionPending:

    kubectl get kcvm default
    # Error from server (NotFound): ...
    kubectl apply -f examples/versionmap-default.yaml
    

    This is transient and requeues every 30 seconds — no manual reconcile trigger needed once the map exists.

  2. BYO credentialsSecret not found yet — condition reason WaitingForCredentials:

    kubectl describe kci $NAME -n $NS | grep -i "waiting for"
    

    Create the missing Secret; the operator progresses on the next reconcile (30-second requeue).


Phase: Provisioning

Symptom: Stuck in Provisioning for more than 10–15 minutes.

Managed Postgres not becoming ready

Condition reason PostgresProvisioning.

kubectl describe perconapgcluster ${NAME}-pg -n $NS
kubectl get pods -n $NS | grep pg

Common causes:

  • No default StorageClass — PVCs stay Pending. Set a default StorageClass.
  • Percona PG Operator not installed or not running: kubectl get pods -n pgo.
  • Insufficient cluster resources (CPU/memory). Check pod events.

BYO credentials Secret invalid

Condition reason CredentialsSecretInvalid — the Secret exists but is missing a required key (host, dbname, user, or password):

kubectl get secret <credentialsSecret-name> -n $NS -o yaml

This is phase Failed but bounded-retried (~60s requeue): correcting the Secret recovers without editing the CR.


Phase: Failed

Symptom: phase: Failed with a condition reason.

ValidationFailed

The spec failed basic validation:

kubectl get kci $NAME -n $NS \
  -o jsonpath='{.status.conditions[?(@.type=="Validated")]}' | jq .message

Common reasons: missing spec.hosts.host, invalid spec.postgres.topology, negative or BYO-only spec.postgres.nodes, or an invalid provider name.

PerconaCRDMissing

spec.postgres.managed: true but the pgv2.percona.com CRD is not installed. The operator never falls back to BYO or an in-cluster database:

kubectl get crd perconapgclusters.pgv2.percona.com

Install the Percona PG Operator (see Installation) and change any spec field (or re-apply) to trigger a reconcile.

VersionDowngradeBlocked

A spec.version change resolved to an image older than the running one. The workload is left untouched. See Upgrades § No downgrades for the break-glass override.

ServiceMonitorCRDMissing

Not a Failed phase — a warning condition (MetricsExporterReady=False). spec.metrics.serviceMonitor: true was set but the monitoring.coreos.com ServiceMonitor CRD is absent; the instance still deploys without metrics scraping.

kubectl get crd servicemonitors.monitoring.coreos.com

StatefulSet not converging / Ready never reported

Symptom: phase stays Deploying/Progressing (reason WorkloadNotReady) even though pods look Running.

Ready is gated on the rollout fully converging: updatedReplicas >= spec.replicas, updateRevision == currentRevision, and observedGeneration caught up. A slow or stuck rolling update (e.g. a readiness probe failing on the new revision) keeps the instance in Progressing indefinitely.

kubectl get statefulset $NAME -n $NS -o jsonpath='{.status}' | jq
kubectl describe pod ${NAME}-0 -n $NS   # check readiness/liveness probe events

Common causes:

  • A provider image failed to start (see the numeric non-root user requirement in the KeycloakInstance Guide § Providers).
  • Insufficient CPU/memory for spec.resources on available nodes.
  • A misconfigured spec.env override breaking Keycloak startup.

Getting more detail

Operator logs for a specific instance

kubectl logs -n bnerd-keycloak-system deploy/bnerd-keycloak-operator --tail=500 \
  | grep $NAME

Full condition dump

kubectl get kci $NAME -n $NS -o json \
  | jq '.status | {phase, host, observedVersion, observedGeneration, conditions}'

Events

kubectl get events -n $NS --field-selector involvedObject.name=$NAME \
  --sort-by='.lastTimestamp'