Post

Persistent storage with kubernetes

Persistent storage with kubernetes

Do you think storage is complicated in kubernetes, yes it is.

PV, PVC, StorageClass sounds unfamiliar to you ? I hope this post will help you.

Storage img

Storage components in a cluster

PV : Persistent volume is like a logical volume in LVM which is linked to the physical storage. It’s a resource created manually by administrator or dynamically with storageclass (don’t pay attention about dynamic provisionning for now, I’ll discusss about it later). A PV is a cluster-wide resource.

PVC : A Persistent volume claim consumed the storage in the PV and is requested by a user . You ask for a space size, and PVC is gonna get this space on PV. A PVC is a resource which resides in a namespace.

PV and PVC works together. One provide the storage, the other request the storage.

Kubernetes provides two ways to manage persistent volumes: static and dynamic

Static Provisioning

Static provisioning is when an administrator define the PV beforehand, then create the PVC to consume the storage defined in the PV.

Here the process to attach a volume to a pod

  1. Create manually the PV(s) with the storage capacity and access mode desired.

  2. Create a PVC with the storage size we want to request from the PV

  3. Lastly, we configure the PVC in the pod specification to uses the storage.

Example of static provisionning

Creation of the PV with 10Gi of storage using hostPath type

apiVersion: v1 kind: PersistentVolume metadata: name: task-pv-volume labels: type: local spec: capacity: storage: 10Gi accessModes: - ReadWriteOnce hostPath: path: "/mnt/data"

Creation of the PVC and define a 3G of storage to be request to the PV defined above

kind: PersistentVolumeClaim apiVersion: v1 metadata: name: task-pv-claim spec: accessModes: - ReadWriteOnce resources: requests: storage: 3Gi apiVersion: v1 kind: Pod metadata: name: task-pv-pod spec: volumes: - name: task-pv-storage persistentVolumeClaim: claimName: task-pv-claim #3 Specify the pvc name defined in metadata field (section above) containers: - name: task-pv-container image: nginx ports: - containerPort: 80 name: "http-server" volumeMounts: - mountPath: "/usr/share/nginx/html" name: task-pv-storage

Dynamic Provisioning

To avoid to create the PV beforehand, k8s introduced the concept of StorageClass

Using dynamic provisioning reduces administrative overhead involved in manually creating PV. Automatically allocating and deallocating PV in response to persistent volume claims can help to reduce wasted storage that is allocated but never used.

A StorageClass defines the parameters we want for the dynamic PV creation:

  • provisionner (NFS, GCE PD, Azure Disk, EBS..)

  • Mount options

  • parameters: Depends on the provisioner type. Could be type of volume, type of filesystem, encryption)

To allow dynamic provisioning of a PV, we specify the storage class in the PVC. Specify a storage class will trigger the dynamic provisioning of the PV. So we don’t need to create the PV in advance.

Here the process to attach a volume to a pod:

  1. Create the storageClass first (GCE-PD, AzureDisk, AWS EBS)

  2. Create the PVC and reference the storageclass created before

  3. Then, we configure the PVC in the pod specification to use it. PV is gonna be dynamically created using the provisioner defined in the storageClass.

Example of dynamic provisionning

Creation of a storageClass for GCE persistent disk

apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: my-storageclass provisioner: kubernetes.io/gce-pd parameters: type: pd-standard

Create the PVC, define the desired request storage, reference the storageclass name defined above

kind: PersistentVolumeClaim apiVersion: v1 metadata: name: claim1 spec: accessModes: - ReadWriteOnce storageClassName: my-storageclass resources: requests: storage: 30Gi

Specify the PVC name defined in metadata field

apiVersion: v1 kind: Pod metadata: name: task-pv-pod spec: volumes: - name: task-pv-storage persistentVolumeClaim: claimName: claim1 containers: - name: task-pv-container image: nginx ports: - containerPort: 80 name: "http-server" volumeMounts: - mountPath: "/usr/share/nginx/html" name: task-pv-storage

After applying these changes, a new PV will be created and the pod will use it.

A PV can have different status and reclaim policies, they are here to define the lifecycle of a volume :

Conclusion

Storage is a whole topic itself, and you defintely need expertise before using a database with persistent volumes.

I skept status and reclaim policy as it would bring more complexity to this post.

I would recommend to avoid using persistent storage for the first workloads that you are going to create/migrate and put stateless applications first.

Then, when you’ll need, use dynanic volume provisionning instead of the static way for an easier management.

This post is licensed under CC BY 4.0 by the author.