kubernetesgoogle-kubernetes-enginepersistent-volumeskubernetes-statefulsetkubernetes-pvc

How to set pvc with statefulset in kubernetes?


On GKE, I set a statefulset resource as

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
spec:
  serviceName: "redis"
  selector:
    matchLabels:
      app: redis
  updateStrategy:
    type: RollingUpdate
  replicas: 3
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis
        resources:
          limits:
            memory: 2Gi
        ports:
          - containerPort: 6379
        volumeMounts:
          - name: redis-data
            mountPath: /usr/share/redis
      volumes:
        - name: redis-data
          persistentVolumeClaim:
            claimName: redis-data-pvc

Want to use pvc so created this one. (This step was did before the statefulset deployment)

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: redis-data-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

When check the resource in kubernetes

kubectl get pvc
NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
redis-data-pvc   Bound    pvc-6163d1f8-fb3d-44ac-a91f-edef1452b3b9   10Gi       RWO            standard       132m

The default Storage Class is standard.

kubectl get storageclass
NAME                 PROVISIONER
standard (default)   kubernetes.io/gce-pd

But when check the statafulset's deployment status. It always wrong.

# Describe its pod details
...
Events:
  Type     Reason                  Age                From                     Message
  ----     ------                  ----               ----                     -------
  Warning  FailedScheduling        22s                default-scheduler        persistentvolumeclaim "redis-data-pvc" not found
  Warning  FailedScheduling        17s (x2 over 20s)  default-scheduler        pod has unbound immediate PersistentVolumeClaims (repeated 2 times)
  Normal   Created                 2s (x2 over 3s)    kubelet                  Created container redis
  Normal   Started                 2s (x2 over 3s)    kubelet                  Started container redis
  Warning  BackOff                 0s (x2 over 1s)    kubelet                  Back-off restarting failed container

Why can't it find the redis-data-pvc name?


Solution

  • What you have done, should work. Make sure that the PersistentVolumeClaim and the StatefulSet is located in the same namespace.


    Thats said, this is an easier solution, and that let you easier scale up to more replicas:

    When using StatefulSet and PersistentVolumeClaim, use the volumeClaimTemplates: field in the StatefulSet instead.

    The volumeClaimTemplates: will be used to create unique PVCs for each replica, and they have unique naming ending with e.g. -0 where the number is an ordinal used for the replicas in a StatefulSet.

    So instead, use a SatefuleSet manifest like this:

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: redis
    spec:
      serviceName: "redis"
      selector:
        matchLabels:
          app: redis
      updateStrategy:
        type: RollingUpdate
      replicas: 3
      template:
        metadata:
          labels:
            app: redis
        spec:
          containers:
          - name: redis
            image: redis
            resources:
              limits:
                memory: 2Gi
            ports:
              - containerPort: 6379
            volumeMounts:
              - name: redis-data
                mountPath: /usr/share/redis
      volumeClaimTemplates:                     // this will be used to create PVC
      - metadata:
          name: redis-data
        spec:
          accessModes: [ "ReadWriteOnce" ]
          resources:
            requests:
              storage: 10Gi