Skip to content

StatefulSets

Use a Kubernetes StatefulSet when each copy of an application needs its own persistent storage or a pod name that stays the same when the pod is replaced. StatefulSets also support starting and updating pods in order. They are useful for databases, queues, and model caches where each copy has its own data.

Before you begin

Create a namespace and download its kubeconfig from the console. Use kubectl to create the StatefulSet and the service that gives its pods DNS names in that namespace.

For stateless HTTP apps or workers, use a Deployment. For one-off or scheduled batch work, use a Job or CronJob.

Supported StatefulSet settings

Use these settings when creating a StatefulSet on RemoteGPU:

AreaDescription
Resource typeapps/v1 StatefulSet
Access pathkubectl with namespace kubeconfig
Plan selectionremotegpu.ai/runtime-sku label on the pod template
StoragevolumeClaimTemplates and existing PVC mounts must use a supported RemoteGPU storage profile
NetworkingClusterIP services; use clusterIP: None when the app needs stable pod DNS
ScalingStandard statefulsets/scale behavior with kubectl scale

Create a StatefulSet

This example runs Redis with a separate storage-standard volume for each replica. It also creates a headless service, which gives each pod a DNS name so other applications can connect to a specific replica.

yaml
apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  clusterIP: None
  selector:
    app: redis
  ports:
    - name: redis
      port: 6379
      targetPort: 6379
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
spec:
  replicas: 1
  serviceName: redis
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
        remotegpu.ai/runtime-sku: cpu-shared-8g
    spec:
      automountServiceAccountToken: false
      containers:
        - name: redis
          image: redis:7-alpine
          args: ["redis-server", "--appendonly", "yes"]
          ports:
            - name: redis
              containerPort: 6379
          volumeMounts:
            - name: data
              mountPath: /data
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        storageClassName: storage-standard
        accessModes: ["ReadWriteOnce"]
        volumeMode: Filesystem
        resources:
          requests:
            storage: 8Gi

Save the YAML as statefulset.yaml. The first command creates the resources; the second waits for the StatefulSet rollout to finish:

bash
kubectl --kubeconfig ./kubeconfig-team-ml.yaml apply -f statefulset.yaml
kubectl --kubeconfig ./kubeconfig-team-ml.yaml rollout status statefulset/redis

Use persistent storage

Each entry in volumeClaimTemplates creates one PersistentVolumeClaim (PVC) per replica. A PVC requests storage for the pod to use. In the Redis example, the first replica gets a PVC named data-redis-0.

Each claim template must use a supported storage class, access mode, volume mode, and size. Read Storage for the supported storage profiles and fixed sizes.

Deleting a StatefulSet keeps its PVCs and their data. Storage charges continue while those PVCs exist, even if you delete the StatefulSet or scale it to 0. Delete the PVCs separately when you no longer need their files.

Operate StatefulSets

Use kubectl scale to change the number of replicas. This command asks Kubernetes to run two Redis pods:

bash
kubectl --kubeconfig ./kubeconfig-team-ml.yaml scale statefulset/redis --replicas=2

Scale to 0 to stop pods while keeping the StatefulSet and PVCs:

bash
kubectl --kubeconfig ./kubeconfig-team-ml.yaml scale statefulset/redis --replicas=0

List the StatefulSet, pods, and PVCs to check their status:

bash
kubectl --kubeconfig ./kubeconfig-team-ml.yaml get statefulset,pod,pvc -l app=redis

Delete the StatefulSet and service when you no longer need them:

bash
kubectl --kubeconfig ./kubeconfig-team-ml.yaml delete statefulset redis
kubectl --kubeconfig ./kubeconfig-team-ml.yaml delete service redis

Troubleshooting

SymptomWhat to check
kubectl apply is rejectedCheck the pod template's compute-plan label and use a ClusterIP service
Pods stay pendingCheck the selected plan, namespace quota, storage class, and pod events with kubectl describe pod
PVC creation is rejectedConfirm the storage class, size, access mode, volume mode, and namespace storage quota match a supported storage profile
Stable pod DNS does not resolveConfirm spec.serviceName matches the service name and the service selector matches the pod labels
Scaling is rejectedConfirm the API key has Kubernetes exec access and the command uses the namespace kubeconfig
Data appears missing after cleanupConfirm whether the generated PVCs were deleted; StatefulSet deletion keeps PVCs by default

RemoteGPU customer documentation