---
apiVersion: v1
kind: Namespace
metadata:
name: valkey
labels:
app.kubernetes.io/name: valkey
app.kubernetes.io/component: database
---
apiVersion: v1
kind: Secret
metadata:
name: valkey-auth
namespace: valkey
labels:
app.kubernetes.io/name: valkey
app.kubernetes.io/component: database
type: Opaque
stringData:
# CHANGE THIS: Generate a strong password with: openssl rand -base64 32
password: "REPLACE_WITH_STRONG_PASSWORD"
---
apiVersion: v1
kind: ConfigMap
metadata:
name: valkey-config
namespace: valkey
labels:
app.kubernetes.io/name: valkey
app.kubernetes.io/component: database
data:
valkey.conf: |
# Persistence
appendonly yes
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# Memory
maxmemory 256mb
maxmemory-policy allkeys-lru
# Network
bind 0.0.0.0
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
# Logging
loglevel notice
# Security
protected-mode yes
requirepass REPLACE_PASSWORD_PLACEHOLDER
---
apiVersion: v1
kind: Service
metadata:
name: valkey
namespace: valkey
labels:
app.kubernetes.io/name: valkey
app.kubernetes.io/component: database
annotations:
service.kubernetes.io/topology-aware-hints: auto
spec:
type: ClusterIP
clusterIP: None # Headless service for StatefulSet
ports:
- name: valkey
port: 6379
targetPort: 6379
protocol: TCP
selector:
app.kubernetes.io/name: valkey
app.kubernetes.io/component: database
---
apiVersion: v1
kind: Service
metadata:
name: valkey-client
namespace: valkey
labels:
app.kubernetes.io/name: valkey
app.kubernetes.io/component: database
annotations:
service.kubernetes.io/topology-aware-hints: auto
spec:
type: ClusterIP
ports:
- name: valkey
port: 6379
targetPort: 6379
protocol: TCP
selector:
app.kubernetes.io/name: valkey
app.kubernetes.io/component: database
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: valkey
namespace: valkey
labels:
app.kubernetes.io/name: valkey
app.kubernetes.io/component: database
app.kubernetes.io/version: "8.0" # CHANGE THIS: Update to match your Valkey version
annotations:
owner: "platform-team" # CHANGE THIS: Set to your team
spec:
serviceName: valkey
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: valkey
app.kubernetes.io/component: database
template:
metadata:
labels:
app.kubernetes.io/name: valkey
app.kubernetes.io/component: database
app.kubernetes.io/version: "8.0" # CHANGE THIS: Update to match your Valkey version
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "6379"
spec:
securityContext:
runAsNonRoot: true
runAsUser: 999
runAsGroup: 999
fsGroup: 999
fsGroupChangePolicy: "OnRootMismatch"
seccompProfile:
type: RuntimeDefault
initContainers:
- name: config-init
image: valkey/valkey:8.0-alpine # CHANGE THIS: Update version as needed
command:
- sh
- -c
- |
cp /tmp/valkey/valkey.conf /etc/valkey/valkey.conf
sed -i "s/REPLACE_PASSWORD_PLACEHOLDER/$(cat /etc/valkey-secret/password)/" /etc/valkey/valkey.conf
volumeMounts:
- name: config
mountPath: /tmp/valkey
- name: valkey-config
mountPath: /etc/valkey
- name: valkey-secret
mountPath: /etc/valkey-secret
readOnly: true
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: false
containers:
- name: valkey
image: valkey/valkey:8.0-alpine # CHANGE THIS: Update version as needed
imagePullPolicy: IfNotPresent
command:
- valkey-server
- /etc/valkey/valkey.conf
ports:
- name: valkey
containerPort: 6379
protocol: TCP
env:
- name: VALKEY_PASSWORD
valueFrom:
secretKeyRef:
name: valkey-auth
key: password
resources:
requests:
cpu: 100m # CHANGE THIS: Adjust based on workload
memory: 384Mi # CHANGE THIS: Should be ~1.5x maxmemory setting
limits:
cpu: 500m # CHANGE THIS: Adjust based on workload
memory: 512Mi # CHANGE THIS: Should be ~2x maxmemory setting
livenessProbe:
exec:
command:
- sh
- -c
- valkey-cli -a "$VALKEY_PASSWORD" ping | grep -q PONG
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
readinessProbe:
exec:
command:
- sh
- -c
- valkey-cli -a "$VALKEY_PASSWORD" ping | grep -q PONG
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
volumeMounts:
- name: data
mountPath: /data
- name: valkey-config
mountPath: /etc/valkey
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
volumes:
- name: config
configMap:
name: valkey-config
- name: valkey-config
emptyDir: {}
- name: valkey-secret
secret:
secretName: valkey-auth
volumeClaimTemplates:
- metadata:
name: data
labels:
app.kubernetes.io/name: valkey
app.kubernetes.io/component: database
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi # CHANGE THIS: Adjust based on expected data size
# storageClassName: "" # UNCOMMENT AND SET: Use specific storage class if needed-
-
Save rawkode/009509abfff635744bee876cc639e8e6 to your computer and use it in GitHub Desktop.
apiVersion: v1 kind: ConfigMap metadata: name: valkey-config labels: app.kubernetes.io/name: valkey app.kubernetes.io/component: key-value-store app.kubernetes.io/part-of: backend-infrastructure data: valkey.conf: | # Network bind 0.0.0.0 port 6379 protected-mode yes
# General
daemonize no
pidfile /var/run/valkey/valkey.pid
loglevel notice
# Persistence (Append Only File for durability)
appendonly yes
appendfilename "appendonly.aof"
# fsync every second is a good balance between speed and durability
appendfsync everysec
dir /data
# Memory Management (Adjust based on resource limits)
# configured slightly lower than container limit to allow for overhead
maxmemory 200mb
maxmemory-policy allkeys-lru
apiVersion: v1 kind: Secret metadata: name: valkey-auth labels: app.kubernetes.io/name: valkey type: Opaque stringData:
password: "ChangeMeToAStrongPassword123!"
apiVersion: v1 kind: Service metadata: name: valkey labels: app.kubernetes.io/name: valkey app.kubernetes.io/component: key-value-store spec: type: ClusterIP ports: - port: 6379 targetPort: 6379 name: valkey protocol: TCP selector: app.kubernetes.io/name: valkey
apiVersion: apps/v1 kind: StatefulSet metadata: name: valkey labels: app.kubernetes.io/name: valkey app.kubernetes.io/component: key-value-store spec: serviceName: "valkey" replicas: 1 selector: matchLabels: app.kubernetes.io/name: valkey template: metadata: labels: app.kubernetes.io/name: valkey spec: # Security Context: Run as non-root (999 is standard for valkey/redis images) securityContext: runAsUser: 999 runAsGroup: 999 fsGroup: 999 terminationGracePeriodSeconds: 60 containers: - name: valkey # Use a specific version tag for production stability image: valkey/valkey:8.0 imagePullPolicy: IfNotPresent # We override the command to inject the password from the secret # without writing it to the config file on disk. command: - "valkey-server" - "/etc/valkey/valkey.conf" - "--requirepass" - "$(VALKEY_PASSWORD)" env: - name: VALKEY_PASSWORD valueFrom: secretKeyRef: name: valkey-auth key: password ports: - containerPort: 6379 name: valkey volumeMounts: - name: valkey-data mountPath: /data - name: config mountPath: /etc/valkey resources: # Requests/Limits: Adjust based on your actual production load requests: cpu: "100m" memory: "256Mi" limits: cpu: "500m" memory: "512Mi" livenessProbe: exec: command: - sh - -c - "valkey-cli -a $VALKEY_PASSWORD ping | grep -q PONG" initialDelaySeconds: 15 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 readinessProbe: exec: command: - sh - -c - "valkey-cli -a $VALKEY_PASSWORD ping | grep -q PONG" initialDelaySeconds: 5 periodSeconds: 5 timeoutSeconds: 3 volumes: - name: config configMap: name: valkey-config
volumeClaimTemplates: - metadata: name: valkey-data spec: accessModes: [ "ReadWriteOnce" ] # If you have a specific StorageClass, uncomment and set it here: # storageClassName: "gp3" resources: requests: storage: 1Gi
apiVersion: v1 kind: ConfigMap metadata: name: valkey-config labels: app.kubernetes.io/name: valkey app.kubernetes.io/instance: valkey app.kubernetes.io/component: datastore app.kubernetes.io/part-of: core-platform app.kubernetes.io/managed-by: kubectl owner: platform-team annotations: description: "Base Valkey configuration (single primary, persistent AOF)" data: valkey.conf: | port 6379 bind 0.0.0.0 protected-mode no dir /data appendonly yes appendfsync everysec save 900 1 save 300 10 save 60 10000 maxmemory 512mb maxmemory-policy allkeys-lru logfile "" loglevel notice cluster-enabled no
apiVersion: v1 kind: Secret metadata: name: valkey-auth labels: app.kubernetes.io/name: valkey app.kubernetes.io/instance: valkey app.kubernetes.io/component: datastore app.kubernetes.io/part-of: core-platform app.kubernetes.io/managed-by: kubectl owner: platform-team type: Opaque data: password: "Y2hhbmdlX21l"
apiVersion: v1 kind: Service metadata: name: valkey labels: app.kubernetes.io/name: valkey app.kubernetes.io/instance: valkey app.kubernetes.io/component: datastore app.kubernetes.io/part-of: core-platform app.kubernetes.io/managed-by: kubectl owner: platform-team annotations: description: "Cluster internal Valkey service" spec: type: ClusterIP selector: app.kubernetes.io/name: valkey app.kubernetes.io/instance: valkey ports: - name: valkey port: 6379 targetPort: 6379 protocol: TCP
apiVersion: apps/v1 kind: StatefulSet metadata: name: valkey labels: app.kubernetes.io/name: valkey app.kubernetes.io/instance: valkey app.kubernetes.io/component: datastore app.kubernetes.io/part-of: core-platform app.kubernetes.io/managed-by: kubectl owner: platform-team spec: serviceName: valkey replicas: 1 selector: matchLabels: app.kubernetes.io/name: valkey app.kubernetes.io/instance: valkey updateStrategy: type: RollingUpdate podManagementPolicy: OrderedReady template: metadata: labels: app.kubernetes.io/name: valkey app.kubernetes.io/instance: valkey app.kubernetes.io/component: datastore app.kubernetes.io/part-of: core-platform annotations: backup.policy/role: primary prometheus.io/scrape: "false" spec: securityContext: runAsNonRoot: true runAsUser: 65532 runAsGroup: 65532 fsGroup: 65532 fsGroupChangePolicy: "OnRootMismatch" containers: - name: valkey image: cgr.dev/chainguard/valkey:latest imagePullPolicy: IfNotPresent command: - sh - -c args: - > exec valkey-server /etc/valkey/valkey.conf --requirepass "$VALKEY_PASSWORD" ports: - name: valkey containerPort: 6379 protocol: TCP env: - name: VALKEY_PASSWORD valueFrom: secretKeyRef: name: valkey-auth key: password resources: requests: cpu: "250m" memory: "512Mi" limits: cpu: "1" memory: "1Gi" volumeMounts: - name: data mountPath: /data - name: config mountPath: /etc/valkey readOnly: true livenessProbe: exec: command: - sh - -c - > valkey-cli -a "$VALKEY_PASSWORD" PING | grep -q PONG initialDelaySeconds: 30 periodSeconds: 15 timeoutSeconds: 5 failureThreshold: 3 readinessProbe: exec: command: - sh - -c - > valkey-cli -a "$VALKEY_PASSWORD" PING | grep -q PONG initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 startupProbe: exec: command: - sh - -c - > valkey-cli -a "$VALKEY_PASSWORD" PING | grep -q PONG initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 18 securityContext: readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: - ALL volumes: - name: config configMap: name: valkey-config items: - key: valkey.conf path: valkey.conf volumeClaimTemplates: - metadata: name: data labels: app.kubernetes.io/name: valkey app.kubernetes.io/instance: valkey app.kubernetes.io/component: datastore app.kubernetes.io/part-of: core-platform owner: platform-team spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi
You are a senior platform engineer responsible for designing production ready workloads on Kubernetes.
Create Kubernetes manifests for running Valkey in a production suitable way, with durable persistence. Your answer must include all YAML required and nothing else.
Requirements:
- Workload and lifecycle
- Use an appropriate Kubernetes workload type for a stateful key value store that needs persistence and stable identities.
- Assume a single primary instance only, not a cluster.
- Ensure the pod can be restarted or rescheduled without data loss.
- Include sensible resource requests and limits suitable for a small production deployment.
- Configure liveness and readiness probes that actually validate Valkey is healthy, not just that the container is running.
- Persistence
- Use a PersistentVolumeClaim for Valkey data so that restarts do not lose state.
- Mount the volume to the correct data directory for Valkey.
- Do not assume a specific storage class name, allow it to be injected by the cluster.
- Configuration and security
- Configure Valkey with:
- Append only persistence enabled.
- A sensible maxmemory setting.
- Use a ConfigMap for non secret configuration and a Secret for the password.
- Ensure the container does not run as root and has an appropriate securityContext.
- Do not hardcode any secrets, passwords, or tokens in plaintext YAML.
- Networking and access
- Expose Valkey inside the cluster using a Service that clients in the same namespace can use.
- Do not expose Valkey directly to the public internet.
- Use labels and selectors consistently so the Service correctly targets the workload.
- Operational details
- Add labels and annotations that would be useful in a production environment, such as app name, component, and owner.
- Make sure the manifests are valid for a recent stable Kubernetes version.
- Parameterize anything that obviously should not be hardcoded, such as image tag and resource sizes, using comments that explain what to change.
Output:
- Provide one or more YAML documents separated with
---that together implement this Valkey deployment. - The manifests must be ready to apply with
kubectl apply -fwithout additional editing, apart from changing configurable values that you clearly mark with comments.