Valkey (component)
A Kustomize component that gives an app a small in-namespace Valkey (open-source Redis fork) instance for caching, session storage, or queueing. Single-replica, no persistence, intentionally cheap to lose.
What it composes
Deployment<app>-valkeyrunning the official Valkey image.Service<app>-valkeyexposing the standard port on ClusterIP only.Secretwith a generated auth password (sourced from the app's SOPS-encrypted Secret if the app overrides it).emptyDirvolume — no PVC, no Longhorn replica. Cache lost on restart, deliberately.
How an app uses it
# k8s/apps/talos/<app>/kustomization.yaml
components:
- ../../../components/talos/valkey
The app's Deployment references <app>-valkey:6379 for its cache. If the app needs a persistent Valkey (queue jobs that must survive restart), it should not use this component — drop a custom StatefulSet with a PVC instead.
Why single-replica, no persistence
- Cache vs. store. If the workload can't survive losing its Valkey, the workload is using Valkey as a store, not a cache. Use Postgres (via cnpg) or MongoDB (via mongodb) for state.
- One replica is enough. A failed Valkey gets rescheduled. Apps that depend on it usually have a Redis client with reconnect-and-retry built in.
- No PVC means no Longhorn replica overhead and no backup tier consideration. Caches are the wrong shape for backups.
Why Valkey, not Redis
Valkey is the BSD-licensed fork that took over after Redis's license change. Functionally a drop-in: every Redis client in every app talks to it without changes. The reasons here:
- Licence clarity. No Redis SLA / commercial-clause concerns.
- Active community + Linux Foundation stewardship.
- API-compatible — when Redis ships a new feature that Valkey doesn't have, the workloads already running here don't need it.
Operational notes
- Wipe + restart is the standard recovery:
kubectl rollout restart deployment <app>-valkey. Cache repopulates from upstream sources. - Memory limits are set on the Deployment patch — Valkey gracefully evicts when it hits the limit (LRU by default). Tune per app if eviction is too aggressive.
- The auth password is rotated together with the rest of the app's SOPS-encrypted secrets — see Topics → SOPS / age key rotation for the procedure.
Cluster Deployment
- Talos
- Edge
Kubernetes Metadata
- Image:
valkey/valkey:9.1.0-alpine@sha256:a35428eba9043cc0b79dbe54100f0c92784f2de00ad09b01182bfb1c5c83d1bd
Rendered manifests (kustomize build)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: valkey
spec:
replicas: 1
selector:
matchLabels:
app: valkey
serviceName: valkey
template:
metadata:
labels:
app: valkey
spec:
containers:
- args:
- valkey-server
image: valkey/valkey:9.1.0-alpine@sha256:a35428eba9043cc0b79dbe54100f0c92784f2de00ad09b01182bfb1c5c83d1bd
livenessProbe:
initialDelaySeconds: 10
periodSeconds: 10
tcpSocket:
port: 6379
name: valkey
ports:
- containerPort: 6379
name: client
readinessProbe:
initialDelaySeconds: 3
periodSeconds: 5
tcpSocket:
port: 6379
resources:
limits:
memory: 512Mi
requests:
cpu: 50m
memory: 128Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
volumeMounts:
- mountPath: /conf
name: conf
- mountPath: /data
name: data
securityContext:
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 999
seccompProfile:
type: RuntimeDefault
volumes:
- emptyDir: {}
name: conf
- emptyDir: {}
name: data
Kubernetes Metadata
- Image:
valkey/valkey:9.1.0-alpine@sha256:a35428eba9043cc0b79dbe54100f0c92784f2de00ad09b01182bfb1c5c83d1bd
Rendered manifests (kustomize build)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: valkey
spec:
replicas: 1
selector:
matchLabels:
app: valkey
serviceName: valkey
template:
metadata:
labels:
app: valkey
spec:
containers:
- args:
- valkey-server
image: valkey/valkey:9.1.0-alpine@sha256:a35428eba9043cc0b79dbe54100f0c92784f2de00ad09b01182bfb1c5c83d1bd
livenessProbe:
initialDelaySeconds: 10
periodSeconds: 10
tcpSocket:
port: 6379
name: valkey
ports:
- containerPort: 6379
name: client
readinessProbe:
initialDelaySeconds: 3
periodSeconds: 5
tcpSocket:
port: 6379
resources:
limits:
memory: 512Mi
requests:
cpu: 50m
memory: 128Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
volumeMounts:
- mountPath: /conf
name: conf
- mountPath: /data
name: data
securityContext:
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 999
seccompProfile:
type: RuntimeDefault
volumes:
- emptyDir: {}
name: conf
- emptyDir: {}
name: data