Ubuntu 20.04
Sponsored Link

Kubernetes : Dynamic Volume Provisioning (NFS)
2020/08/24
 
To use Dynamic Volume Provisioning feature when using Persistent Storage, it's possible to create PV (Persistent Volume) dynamically without creating PV manually by Cluster Administrator when created PVC (Persistent Volume Claim) by users.
This example is based on the environment like follows.
For example, run NFS Server on Master Node and configure dynamic volume provisioning with NFS provisioner.
-----------+---------------------------+--------------------------+------------
           |                           |                          |
       eth0|10.0.0.30              eth0|10.0.0.51             eth0|10.0.0.52
+----------+-----------+   +-----------+----------+   +-----------+----------+
|   [ dlp.srv.world ]  |   | [ node01.srv.world ] |   | [ node02.srv.world ] |
|      Master Node     |   |      Worker Node     |   |      Worker Node     |
+----------------------+   +----------------------+   +----------------------+

[1]
Run NFS Server on Master Node, refer to here.
On this example, configure [/home/nfsshare] directory as NFS share.
[2]
[3] Install NFS Client Provisioner with Helm.
# nfs.server = (NFS server's hostname or IP address)

# nfs.path = (NFS share Path)

root@dlp:~#
helm install nfs-client -n kube-system --set nfs.server=10.0.0.30 --set nfs.path=/home/nfsshare stable/nfs-client-provisioner
NAME: nfs-client
LAST DEPLOYED: Mon Aug 23 19:00:38 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

root@dlp:~#
kubectl get pods -n kube-system

NAME                                                 READY   STATUS    RESTARTS   AGE
.....
.....
nfs-client-nfs-client-provisioner-767d689897-pcl2t   1/1     Running   0          39s
[4] This is an example to use dynamic volume provisioning by a Pod.
root@dlp:~#
kubectl get pv

No resources found in default namespace.
root@dlp:~#
kubectl get pvc

No resources found in default namespace.
root@dlp:~#
kubectl get storageclass


NAME         PROVISIONER                                       RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-client   cluster.local/nfs-client-nfs-client-provisioner   Delete          Immediate           true                   11m

# create PVC

root@dlp:~#
vi my-pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-provisioner
  annotations:
    # specify StorageClass name
    volume.beta.kubernetes.io/storage-class: nfs-client
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      # volume size
      storage: 5Gi

root@dlp:~#
kubectl apply -f my-pvc.yml

persistentvolumeclaim/my-provisioner created
root@dlp:~#
kubectl get pvc

NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
my-provisioner   Bound    pvc-8230bde9-6f4e-40fd-9d7f-ed999e1b4412   5Gi        RWO            nfs-client     13s

# PV is generated dynamically

root@dlp:~#
kubectl get pv

NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                    STORAGECLASS   REASON   AGE
pvc-8230bde9-6f4e-40fd-9d7f-ed999e1b4412   5Gi        RWO            Delete           Bound    default/my-provisioner   nfs-client              15s

root@dlp:~#
vi my-pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: my-mginx
spec:
  containers:
    - name: my-mginx
      image: nginx
      ports:
        - containerPort: 80
          name: web
      volumeMounts:
      - mountPath: /usr/share/nginx/html
        name: nginx-pvc
  volumes:
    - name: nginx-pvc
      persistentVolumeClaim:
        # PVC name you created
        claimName: my-provisioner

root@dlp:~#
kubectl apply -f my-pod.yml

pod/my-mginx created
root@dlp:~#
kubectl get pod my-mginx -o wide

NAME       READY   STATUS    RESTARTS   AGE     IP            NODE               NOMINATED NODE   READINESS GATES
my-mginx   1/1     Running   0          8m23s   10.244.2.14   node02.srv.world   <none>           <none>

root@dlp:~#
kubectl exec my-mginx -- df /usr/share/nginx/html

Filesystem                                                                               1K-blocks    Used Available Use% Mounted on
10.0.0.30:/home/nfsshare/default-my-provisioner-pvc-8230bde9-6f4e-40fd-9d7f-ed999e1b4412  80440320 4859904  72251392   7% /usr/share/nginx/html

# verify accessing to create test index file

root@dlp:~#
echo "Nginx Index" > index.html

root@dlp:~#
kubectl cp index.html my-mginx:/usr/share/nginx/html/index.html

root@dlp:~#
curl 10.244.2.14

Nginx Index
# when removing, to remove PVC, then PV is also removed dynamically

root@dlp:~#
kubectl delete pod my-mginx

pod "my-mginx" deleted
root@dlp:~#
kubectl delete pvc my-provisioner

persistentvolumeclaim "my-provisioner" deleted
root@dlp:~#
kubectl get pv

No resources found in default namespace.
[5] To use StatefulSet, it's possible to specify [volumeClaimTemplates].
root@dlp:~#
kubectl get pv

No resources found in default namespace.
root@dlp:~#
kubectl get pvc

No resources found in default namespace.
root@dlp:~#
kubectl get storageclass


NAME         PROVISIONER                                       RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-client   cluster.local/nfs-client-nfs-client-provisioner   Delete          Immediate           true                   11m

root@dlp:~#
vi statefulset.yml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: my-mginx
spec:
  serviceName: my-mginx
  replicas: 1
  selector:
    matchLabels:
      app: my-mginx
  template:
    metadata:
      labels:
        app: my-mginx
    spec:
      containers:
      - name: my-mginx
        image: nginx
        volumeMounts:
        - name: data
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      # specify StorageClass name
      storageClassName: nfs-client
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 5Gi

root@dlp:~#
kubectl apply -f statefulset.yml

statefulset.apps/my-mginx created
root@dlp:~#
kubectl get statefulset

NAME       READY   AGE
my-mginx   1/1     17s

root@dlp:~#
kubectl get pods -o wide

NAME                                                 READY   STATUS    RESTARTS   AGE   IP            NODE               NOMINATED NODE   READINESS GATES
my-mginx-0                                           1/1     Running   0          47s   10.244.2.15   node02.srv.world   <none>           <none>
nfs-client-nfs-client-provisioner-767d689897-pcl2t   1/1     Running   0          58m   10.244.1.21   node01.srv.world   <none>           <none>

root@dlp:~#
kubectl get pvc

NAME              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
data-my-mginx-0   Bound    pvc-f1c770d6-0d08-4c99-bdda-bde6a7b6549a   5Gi        RWO            nfs-client     64s

root@dlp:~#
kubectl get pv

NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                     STORAGECLASS   REASON   AGE
pvc-f1c770d6-0d08-4c99-bdda-bde6a7b6549a   5Gi        RWO            Delete           Bound    default/data-my-mginx-0   nfs-client              65s
Matched Content