Kubernetes : Dynamic Volume Provisioning (NFS)2024/11/06 |
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 Control Plane 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 ] | | Control Plane | | Worker Node | | Worker Node | +----------------------+ +----------------------+ +----------------------+ |
[1] |
Run NFS Server on Control Plane Node, refer to here. |
[2] |
Worker Nodes need to be able to mount NFS share on NFS server. |
[3] | Install NFS Client Provisioner. |
[root@dlp ~]#
dnf -y install helm
[root@dlp ~]#
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
# 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 nfs-subdir-external-provisioner/nfs-subdir-external-provisioner
NAME: nfs-client LAST DEPLOYED: Wed Nov 6 11:33:19 2024 NAMESPACE: kube-system STATUS: deployed REVISION: 1 TEST SUITE: None[root@dlp ~]# kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE ..... ..... nfs-client-nfs-subdir-external-provisioner-779f4566db-md7t5 1/1 Running 0 21s |
[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-subdir-external-provisioner Delete Immediate true 63s apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-provisioner spec: accessModes: - ReadWriteOnce resources: requests: # volume size storage: 5Gi # specify StorageClass name storageClassName: nfs-client
[root@dlp ~]#
[root@dlp ~]# kubectl apply -f my-pvc.yml persistentvolumeclaim/my-provisioner created kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE my-provisioner Bound pvc-42743b06-0794-41eb-8f0e-5372385bd632 5Gi RWO nfs-client <unset> 4s # PV is generated dynamically [root@dlp ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE pvc-42743b06-0794-41eb-8f0e-5372385bd632 5Gi RWO Delete Bound default/my-provisioner nfs-client <unset> 2m15s
[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
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 14s 192.168.40.198 node01.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-42743b06-0794-41eb-8f0e-5372385bd632 80674816 5331968 75342848 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 192.168.40.198 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-subdir-external-provisioner Delete Immediate true 9m42s
[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
kubectl apply -f statefulset.yml statefulset.apps/my-mginx created [root@dlp ~]# kubectl get statefulset NAME READY AGE my-mginx 1/1 13s[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 29s 192.168.40.199 node01.srv.world <none> <none>[root@dlp ~]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE data-my-mginx-0 Bound pvc-149e89de-0bd6-4e6b-b229-50706494f426 5Gi RWO nfs-client <unset> 63s[root@dlp ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE pvc-149e89de-0bd6-4e6b-b229-50706494f426 5Gi RWO Delete Bound default/data-my-mginx-0 nfs-client <unset> 87s |
Sponsored Link |