others-how to solve 'error validating data: ValidationError(Deployment.spec): unknown field volumeClaimTemplates in io.k8s.api.apps.v1.DeploymentSpec ' error?

Problem

When we install application in kubernetes(k8s), sometimes, we get the following error:

root@launch-advisor:~# kubectl apply -f deployment-redis.yaml

error: error validating "deployment-redis.yaml": error validating data: ValidationError(Deployment.spec): unknown field "volumeClaimTemplates" in io.k8s.api.apps.v1.DeploymentSpec; if you choose to ignore these errors, turn validation off with --validate=false

The content of deployment-redis.yaml is:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  namespace: ns-bswen
  labels:
    app: redis
spec:
  selector:
    matchLabels:
      app: redis
  replicas: 1
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis
          image: redis:6.0.9
          ports:
            - containerPort: 6379
          command: ["redis-server", "/etc/redis/redis.conf"]
          volumeMounts:
            - name: "redis-conf"
              mountPath: /etc/redis/redis.conf
              subPath: redis_conf
            - name: "redis-data"
              mountPath: "/var/lib/redis"
      volumes:
        - name: "redis-conf"
          configMap:
            name: "redis"
        - name: "redis-data"
          persistentVolumeClaim:
            claimName: redis-pvc
  volumeClaimTemplates:
    - metadata:
        name: redis-pvc
        annotations:
          volume.beta.kubernetes.io/storage-class: "my-nfs-storage"
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 100Mi

Environment

  • Docker: Server Version: 19.03.13

  • Kubectl version

    Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.3", GitCommit:"06ad960bfd03b39c8310aaf92d1e7c12ce618213", GitTreeState:"clean", BuildDate:"2020-02-13T18:06:54Z", GoVersion:"go1.13.8", Compiler:"gc", Platform:"darwin/amd64"}
      
    Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.6", GitCommit:"dff82dc0de47299ab66c83c626e08b245ab19037", GitTreeState:"clean", BuildDate:"2020-07-15T16:51:04Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
    

Reason

volumeClaimTemplates can ONLY be used in StatefulSets

  • Deployment - PersistentVolumeClaim is shared by all pod replicas. In other words, shared volume.

  • StatefulSet - You specify a volumeClaimTemplates so that each replica pod gets a unique PersistentVolumeClaim associated with it. In other words, no shared volume.

StatefulSet is useful for running things in cluster e.g Hadoop cluster, MySQL cluster, where each node has its own storage.

Solution

You can switch from Deployment to StatefulSet as follows:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
  namespace: ns-bswen
  labels:
    app: redis
spec:
  serviceName: redis
  selector:
    matchLabels:
      app: redis
  replicas: 1
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis
          image: redis:6.0.9
          ports:
            - containerPort: 6379
          command: ["redis-server", "/etc/redis/redis.conf"]
          volumeMounts:
            - name: "redis-conf"
              mountPath: /etc/redis/redis.conf
              subPath: redis_conf
            - name: "redis-data"
              mountPath: "/var/lib/redis"
      volumes:
        - name: "redis-conf"
          configMap:
            name: "redis"
        - name: "redis-data"
          persistentVolumeClaim:
            claimName: redis-pvc
  volumeClaimTemplates:
    - metadata:
        name: redis-pvc
        annotations:
          volume.beta.kubernetes.io/storage-class: "my-nfs-storage"
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 100Mi