Skip to content

Stateful servicesΒΆ

Redis, OpenSearch, or any service that keeps its own data on its disk. Tell the platform that this service is the only one that may touch it.

compose.yaml
services:
  redis:
    image: redis:7-alpine
    command: [redis-server, --appendonly, "yes"]
    expose: ["6379"]
    volumes:
      - redisdata:/data # (1)!
    healthcheck:
      test: [CMD, redis-cli, ping]
      interval: 5s
    deploy:
      x-kubernetes:
        kind: StatefulSet # (2)!

volumes:
  redisdata:
    x-kubernetes:
      accessModes: [ReadWriteOnce]
      resources:
        requests:
          storage: 2Gi
  1. The disk of the service, declared as any volume.
  2. The only Kubernetes word you write. It means: one copy, its own disk, never two at once on it.

Generated on every release. You never write this file or see it.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    com.docker.compose.project: my-app
    com.docker.compose.service: redis
  name: redis
  namespace: my-app
spec:
  persistentVolumeClaimRetentionPolicy:
    whenDeleted: Retain # (1)!
    whenScaled: Retain
  replicas: 1 # (2)!
  selector:
    matchLabels:
      com.docker.compose.project: my-app
      com.docker.compose.service: redis
  serviceName: redis-headless
  template:
    metadata:
      labels:
        com.docker.compose.project: my-app
        com.docker.compose.service: redis
        com.docker.compose.network.default: 'true'
    spec:
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: com.docker.compose.service
                operator: In
                values:
                - redis
              matchLabels:
                com.docker.compose.project: my-app
            namespaces:
            - my-app
            topologyKey: kubernetes.io/hostname
      containers:
      - args:
        - redis-server
        - --appendonly
        - 'yes'
        image: redis:7-alpine
        imagePullPolicy: IfNotPresent
        name: redis
        readinessProbe:
          exec:
            command:
            - redis-cli
            - ping
          failureThreshold: 3
          initialDelaySeconds: 0
          periodSeconds: 5
          successThreshold: 1
          timeoutSeconds: 30
        volumeMounts:
        - mountPath: /data
          name: redisdata
          readOnly: false
  updateStrategy:
    type: RollingUpdate
  volumeClaimTemplates: # (3)!
  - metadata:
      labels:
        com.docker.compose.project: my-app
        com.docker.compose.service: redis
      name: redisdata
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 2Gi
  1. The disk survives the service: removing the service keeps the data.
  2. One copy. A second one would be a second Redis, not a replica.
  3. Its own disk, with the size you declared.
Behavior Detail
Its own disk A volume mounted only by this service is its disk, and stays its disk when the copy is replaced
Shared volumes stay shared A volume that other services also mount keeps being one disk for all
Same name The other services keep reaching it at redis:6379
One copy deploy.replicas above 1 is rejected: copies of Redis do not replicate data

On your machine, kind has no effect: Docker runs the service with its volume as always.