Troubleshooting
This page diagnoses and resolves the problems you are most likely to hit operating the Momento Valkey Operator: stuck cluster states, pods that won't schedule, TLS and ACL failures, and an unhealthy operator. It is written for the on-call engineer who needs to go from symptom to fix. For the theory behind failure recovery, see Failure modes; for the full state machine, see Cluster status.
Read the situation first
Before working a specific symptom below, gather the same four signals every time:
# Cluster state and a one-line reason (when Invalid)
kubectl get valkeycluster -n my-app
# Full status: targetSpec (if bootstrapping) and status.message
kubectl describe valkeycluster my-cluster -n my-app
# Per-node lifecycle: Joining / Active / Leaving
kubectl get valkeynodes -n my-app
# Operator logs: structured JSON, filtered by RUST_LOG
kubectl -n valkey-operator logs deployment/valkey-operator
kubectl get valkeycluster shows the STATE column: Creating, Active, or Invalid in practice (the schema also defines Updating, but the current release never reports it; a cluster mid-change shows Active); kubectl describe or kubectl get valkeycluster -o yaml surfaces status.message, which is populated on Invalid with the exact validation failure. The operator emits one JSON log line per reconcile action, filtered by the RUST_LOG environment variable on its Deployment (info by default); Logging explains the format and how to filter by cluster. See Cluster status for what each state and column means.
Know where explanations surface: TLS validation failures are the only errors written to status.message, and the operator emits no Kubernetes Events at all. Every other diagnosis below (missing references, ACL problems, connection failures) is explained only in the operator logs, so expect kubectl describe to look uninformative even when the logs name the exact problem.
Cluster stuck in Creating
A cluster that has been Creating for longer than a few reconcile ticks usually has one of three causes. (A fourth is an unpullable image: the operator trusts a ValkeyImage's repository:tag verbatim, so a typo there shows up as pods in ImagePullBackOff.)
| Cause | How to confirm | Fix |
|---|---|---|
Referenced ValkeyImage or ValkeyConfig is missing, or the baseRef inheritance chain is broken | kubectl get valkeyconfig <name> / kubectl get valkeyimage <name> returns not found; operator logs (never status.message) show the resolution error verbatim: ValkeyConfig "<name>" not found, ValkeyImage "<name>" not found, no image_ref in config chain ending at "<name>", or config inheritance depth exceeds 10 (cycle?) | Create the missing resource. References are resolved fresh on every reconcile; you do not need to recreate the ValkeyCluster once the missing ValkeyImage or ValkeyConfig exists. |
| Pods are unschedulable: resource requests too large for available capacity, or placement constraints unsatisfiable | kubectl get pods -n my-app shows pods Pending; kubectl describe pod <pod> -n my-app events show scheduling failures | Resize node capacity, reduce the config's resources, or relax placement (zones, nodeSelector, zoneSpread: required). See Zone-aware placement and Sizing. |
Pods are rejected by Pod Security admission: the namespace enforces the restricted Pod Security Standard, and Valkey pods carry no securityContext (no runAsNonRoot declaration) | kubectl get pods -n my-app shows no pods created, or events / kubectl describe namespace my-app show a violates PodSecurity admission rejection; check the namespace's pod-security.kubernetes.io/enforce label | Relabel or exempt the namespace to privileged or baseline enforcement. See Prerequisites for the compatibility statement. |
A wedged bootstrap can't be fixed by editing
During bootstrap, the operator works the cluster's topology from a snapshot (status.targetSpec) taken the moment the cluster enters Creating. Edits to shards or replicasPerShard while still Creating are deferred until bootstrap finishes, so a wrong topology value cannot be corrected by editing. Other spec fields (configRef, placement, tls.secretRef, acl) are read live on every reconcile, but they only shape nodes that have not been created yet. Node specs are immutable once created, so editing placement mid-bootstrap does not fix a node already stuck Pending under the old placement. Mid-bootstrap edits can also leave a cluster with nodes built from two different configurations.
External fixes still work while Creating: creating a missing ValkeyImage or ValkeyConfig unblocks bootstrap immediately, because references resolve live on every reconcile; no recreate needed (see the table above). But a mistake in the spec itself (a wrong topology value, or an unsatisfiable placement already stamped onto stuck nodes) requires deleting and recreating the ValkeyCluster; that is the reliable path. See targetSpec snapshot semantics.
Cluster shows Invalid
Invalid has exactly one trigger: the TLS Secret referenced by spec.tls.secretRef failed validation. The operator checks it on every reconcile and writes the specific failure to status.message. The messages, verbatim (with <secret> standing for the Secret name):
status.message | What it means |
|---|---|
TLS Secret "<secret>" not found in namespace "<namespace>" | spec.tls.secretRef names a Secret that doesn't exist in the cluster's namespace |
TLS Secret "<secret>" has no data | The Secret exists but is empty |
TLS Secret "<secret>" missing required key "<key>" | A required key (tls.crt, tls.key, or ca.crt) is absent from the Secret |
TLS Secret "<secret>": tls.crt is not valid PEM | The certificate data is malformed |
TLS Secret "<secret>": tls.crt is not a valid X.509 certificate | The PEM block doesn't parse as a certificate |
TLS cert in Secret "<secret>" missing SAN "<name>" | The certificate's SAN list is missing {cluster}.{namespace}.svc.cluster.local or the wildcard *.{cluster}.{namespace}.svc.cluster.local; the message names the one it expected |
Fix the Secret in place: patch it with corrected data, or point spec.tls.secretRef at a valid one. Recovery is automatic: once validation passes, the operator resets the state to Creating, and a previously-formed cluster passes through bootstrap as a no-op back to Active. No ValkeyCluster edit or recreation is needed. See TLS.