'Required value: must specify a volume type when statically provisioning PV

Trying to statically provision a PV with GCP SSD storage. Errors out with the following message:

The PersistentVolume "monitoring" is invalid: spec: Required value: must specify a volume type

Steps to reproduce:

$ cat storage.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ssd
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd
reclaimPolicy: Retain


$ kubectl apply -f storage.yaml
storageclass.storage.k8s.io/ssd created


$ cat pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: monitoring
spec:
  storageClassName: ssd
  capacity:
    storage: 50Gi
  persistentVolumeReclaimPolicy: Retain
  accessModes:
    - ReadWriteOnce


$ kubectl apply -f pv.yaml
The PersistentVolume "monitoring" is invalid: spec: Required value: must specify a volume type

Kubernetes version:

Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.1", GitCommit:"b7394102d6ef778017f2ca4046abbaa23b88c290", GitTreeState:"clean", BuildDate:"2019-04-08T17:11:31Z", GoVersion:"go1.12.1", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"12+", GitVersion:"v1.12.6-gke.10", GitCommit:"aaf0906400b5fc1d858ce0566a571e4f3ed06b9f", GitTreeState:"clean", BuildDate:"2019-03-30T19:30:48Z", GoVersion:"go1.10.8b4", Compiler:"gc", Platform:"linux/amd64"}


Solution 1:[1]

If using a provisioner, you usually don't create the PV on your own. Just create a PVC requiring that created storage class and GKE will provide the PV with the requested storage size and kind for you:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: my-retain-ssd-storage
  namespace: default
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 50Gi
  storageClassName: ssd

Solution 2:[2]

No need to create Storage Class, just correct your requirements

see my file, Here HostPath is added.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: log-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  hostPath:
    path: "/opt/volume/nginx"

and PVC as

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: log-claim
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 200Mi
  storageClassName: manual

Solution 3:[3]

If the storageClass provisioner is set to kubernetes.io/no-provisioner

~> kubectl describe storageclass harbor-registry-persistent-storage
Name:            harbor-registry-persistent-storage
...
Provisioner:           kubernetes.io/no-provisioner

you can create your PV as:

apiVersion: v1
kind: PersistentVolume
metadata:
  finalizers:
  - kubernetes.io/pv-protection
  labels:
    component: harbor
  name: jobservice
spec:
  accessModes:
  - ReadWriteOnce
  - ReadWriteMany
  capacity:
    storage: 10Gi
  local:                                             <------ mandatory field
    path: /mnt/kubernetes/persistent_volumes/harbor_registry_pv_0   <---- Note this path should exists in your kubernetes node 
  persistentVolumeReclaimPolicy: Retain
  nodeAffinity:                                      <------ mandatory field
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: harbor-registry
          operator: In
          values:
          - harbor-registry-pv-0
  storageClassName: harbor-registry-persistent-storage

and your PVC should be able to attach with the above create PV:

k get pvc disable-pvc -o yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  finalizers:
  - kubernetes.io/pvc-protection
  name: disable-pvc
  namespace: default
spec:
  accessModes:
  - ReadWriteOnce
  - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  storageClassName: harbor-registry-persistent-storage
  volumeMode: Filesystem
  volumeName: jobservice
status:
  accessModes:
  - ReadWriteOnce
  - ReadWriteMany
  capacity:
    storage: 10Gi                  <------ The size should match with your PV storage
  phase: Bound

Solution 4:[4]

References:

The issue:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: minio-tenant-log-minio-tenant-log-0
spec:
  capacity:
    storage: 10Gi
  persistentVolumeReclaimPolicy: Retain
  accessModes:
    - ReadWriteOnce
  storageClassName: thin
$ kubectl apply -f pv.yaml
The PersistentVolume "minio-tenant-log-minio-tenant-log-0" is invalid: spec: Required value: must specify a volume type

One possible solution:

  1. PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: minio-tenant-log-minio-tenant-log-0
  labels:
      keylabel: valuelabel
spec:
  capacity:
    storage: 10Gi
  persistentVolumeReclaimPolicy: Retain
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/opt/volume/nginx"
$ kubectl apply -f pv.yaml
persistentvolume/minio-tenant-log-minio-tenant-log-0 created
  1. PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: thin
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  volumeName: "minio-tenant-log-minio-tenant-log-0"
$ kubectl apply -f pvc.yaml
persistentvolumeclaim/thin created
$ kubectl get pvc                                    
NAME   STATUS   VOLUME                                CAPACITY   ACCESS MODES   STORAGECLASS   AGE
thin   Bound    minio-tenant-log-minio-tenant-log-0   10Gi       RWO                           44s

Explanation:

Removed the spec.storageClassName from the PersistentVolume but added the hostPath to where we are going to locate the data; then created the PersistentVolumeClaim to include spec.volumeName so that PVC binds a specific PV. Problem solved!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jbndlr
Solution 2 engineerbaz
Solution 3 Vishrant
Solution 4