Dynamic Volume Provisionining in AWS EKS using EBS

Dynamic Volume Provisionining in AWS EKS using EBS

Pods in Kubernetes need to store data which gets lost if kubelet restarts the pod or pods are intentionally deleted or recreated.

Empty Dir volume or Host path volume use the local disk of the node to mount the volume. Cloud volumes like AWS EBS mount the disk in the same manner but with different implementation.

In this tutorial we will learn the concept of Persistent Volume and Persistent Volume Claim and its implementation on AWS EKS using EBS.

Persistent volume (PV)

As we saw that Empty Dir or Host path are tightly coupled with pods as they use the local disk of the node to mount the volume. It is a piece of storage in the cluster that has been provisioned by an administrator or dynamically provisioned using Storage Classes.

Important things to remember is:

  • It is a resource in the cluster just like a node is a cluster resource.
  • PVs are volume plugins like Volumes, but have a lifecycle independent of any individual Pod that uses the PV.
  • PV is used in the same manner as emptyDir or hostPath but not provisioned by pods.
  • It removes provisioning burden from developers to admin.

Screenshot from 2022-01-24 12-20-33.png

Persistent volume claim (PVC)

Cluster administrator creates the volumes as we saw previously and now pods can access them through PVC. It's a level of abstraction between the volume and its storage mechanism. Once PVC is created requirements of your application only matters eg. space, type, permission.

We can also give different level of access permission in PVC.

  • ReadWriteOnce - where only one node is allowed access to the volume.
  • ReadOnlyMany - where one is allowed full access and other nodes are allowed read-only permission
  • ReadWriteMany - for volumes that can be shared among many nodes and all of them have full access to it

Screenshot from 2022-01-24 12-20-55.png

Dynamic Volume Provisionining in AWS EKS using EBS

  • Create a StorageClass with the following settings.
$ cat storage-class.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: aws-standard
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
  fsType: ext4
  • Create StorageClass with kubectl apply command.
$ kubectl apply -f storage-class.yaml
storageclass.storage.k8s.io/aws-standard created
  • Explain the default storageclass
$ kubectl get storageclass
NAME                     PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
aws-standard (default)   kubernetes.io/aws-ebs   Delete          Immediate              false                  37s
gp2 (default)            kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   false                  112m
  • Create a persistentvolumeclaim with the following settings and show that new volume is created on aws management console.
$ cat pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pv-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi
  storageClassName: aws-standard
$ kubectl apply -f pvc.yaml
persistentvolumeclaim/pvc created
  • List the pv and pvc and explain the connections.
$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                     STORAGECLASS   REASON   AGE
pvc-250719ae-36b8-441a-ad04-f6f69c1a11f0   3Gi        RWO            Delete           Bound    default/pv-claim   aws-standard            18s
$ kubectl get pvc
NAME              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pv-claim   Bound    pvc-250719ae-36b8-441a-ad04-f6f69c1a11f0   3Gi        RWO            aws-standard   2m30s
  • Create a pod with the following settings.
$ cat dynamic-storage-aws.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-eks-dynamic-storage
  labels:
    app : web-nginx
spec:
  containers:
  - image: nginx:latest
    ports:
    - containerPort: 80
    name: test-aws
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: aws-pd
  volumes:
  - name: aws-pd
    persistentVolumeClaim:
      claimName: pv-claim
$ kubectl apply -f dynamic-storage-aws.yaml
pod/test-eks-dynamic-storage created
  • Enter the pod and see that ebs is mounted to /usr/share/nginx/html path. As it can be seen EBS has been mounted to the path and once we are done we can delete this.

    $ kubectl exec -it test-aws -- bash
    root@test-eks-dynamic-storage:/# df -kh
    Filesystem      Size  Used Avail Use% Mounted on
    overlay         8.0G  4.3G  3.7G  54% /
    tmpfs            64M     0   64M   0% /dev
    tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
    /dev/xvda1      8.0G  4.3G  3.7G  54% /etc/hosts
    shm              64M     0   64M   0% /dev/shm
    /dev/xvdbq      2.9G  9.0M  2.9G   1% /usr/share/nginx/html
    tmpfs           2.0G   12K  2.0G   1% /run/secrets/kubernetes.io/serviceaccount
    tmpfs           2.0G     0  2.0G   0% /proc/acpi
    tmpfs           2.0G     0  2.0G   0% /proc/scsi
    tmpfs           2.0G     0  2.0G   0% /sys/firmware
    root@test-eks-dynamic-storage:/#
    
  • Delete the storageclass that we created once done.

$ kubectl get storageclass
NAME                     PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
aws-standard (default)   kubernetes.io/aws-ebs   Delete          Immediate              false                  16m
gp2 (default)            kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   false                  39m
$ kubectl delete storageclass gp2
storageclass.storage.k8s.io "gp2" deleted
$ kubectl get storageclass
NAME                     PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
aws-standard (default)   kubernetes.io/aws-ebs   Delete          Immediate           false                  16m
  • Delete the pod as well once done
$ kubectl delete -f dynamic-storage-aws.yaml 
pod "test-eks-dynamic-storage" deleted

Conclusion

As we saw Kubernetes volume provides an easy solution to solve the problem of ephemeral nature of storage in the container and secondly allows sharing files between containers.