Kubernetes : Dynamic Volume Provisioning (NFS)2023/10/20 |
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. +----------------------+ +----------------------+ | [ mgr.srv.world ] | | [ dlp.srv.world ] | | Manager Node | | Control Plane | +-----------+----------+ +-----------+----------+ eth0|10.0.0.25 eth0|10.0.0.30 | | ------------+--------------------------+----------- | | eth0|10.0.0.51 eth0|10.0.0.52 +-----------+----------+ +-----------+----------+ | [ node01.srv.world ] | | [ node02.srv.world ] | | Worker Node#1 | | Worker Node#2 | +----------------------+ +----------------------+ |
For example, configure dynamic volume provisioning with NFS provisioner that NFS storage is provided from [nfs.srv.world (10.0.0.35)]. |
|
[1] |
Run NFS Server, refer to here. |
[2] |
Worker Nodes need to be able to mount NFS share on NFS server. |
[3] | Install NFS Client Provisioner with Helm. |
[root@mgr ~]#
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@mgr ~]# helm install nfs-client -n kube-system --set nfs.server=10.0.0.35 --set nfs.path=/home/nfsshare nfs-subdir-external-provisioner/nfs-subdir-external-provisioner
NAME: nfs-client LAST DEPLOYED: Fri Oct 20 15:46:59 2023 NAMESPACE: kube-system STATUS: deployed REVISION: 1 TEST SUITE: None[root@mgr ~]# kubectl get deployment -n kube-system NAME READY UP-TO-DATE AVAILABLE AGE calico-kube-controllers 1/1 1 1 27h coredns 2/2 2 2 27h metrics-server 1/1 1 1 55m nfs-client-nfs-subdir-external-provisioner 1/1 1 1 3m2s |
[4] | This is an example to use dynamic volume provisioning by a Pod. |
[root@mgr ~]# kubectl get pv No resources found in default namespace. [root@mgr ~]# kubectl get pvc No resources found in default namespace. [root@mgr ~]# kubectl get storageclass NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE nfs-client cluster.local/nfs-client-nfs-subdir-external-provisioner Delete Immediate true 4m51s apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-provisioner spec: accessModes: - ReadWriteOnce # specify StorageClass name storageClassName: nfs-client resources: requests: # volume size storage: 5Gi
[root@mgr ~]#
[root@mgr ~]# kubectl apply -f my-pvc.yml persistentvolumeclaim/my-provisioner created kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE my-provisioner Bound pvc-6b2fb244-4a22-4f0e-a507-50fb213e20d0 5Gi RWO nfs-client 2m33s # PV is generated dynamically [root@mgr ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-6b2fb244-4a22-4f0e-a507-50fb213e20d0 5Gi RWO Delete Bound default/my-provisioner nfs-client 3m8s
[root@mgr ~]#
vi my-pod.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 1
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
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 deployment.apps/my-nginx created [root@mgr ~]# kubectl get pods NAME READY STATUS RESTARTS AGE my-nginx-66fc75ffb8-vflks 1/1 Running 0 39s[root@mgr ~]# kubectl exec my-nginx-66fc75ffb8-vflks -- df /usr/share/nginx/html Filesystem 1K-blocks Used Available Use% Mounted on 10.0.0.35:/home/nfsshare/default-my-provisioner-pvc-6b2fb244-4a22-4f0e-a507-50fb213e20d0 167689728 1202688 166487040 1% /usr/share/nginx/html # verify accessing to create test index file [root@mgr ~]# echo "Nginx Index" > index.html [root@mgr ~]# kubectl cp index.html my-nginx-66fc75ffb8-vflks:/usr/share/nginx/html/index.html [root@mgr ~]# kubectl expose deployment my-nginx --type="NodePort" --port 80 [root@mgr ~]# kubectl port-forward service/my-nginx --address 127.0.0.1 80:80 & [root@mgr ~]# curl localhost Handling connection for 80 Nginx Index # when removing, to remove PVC, then PV is also removed dynamically [root@mgr ~]# kubectl delete deployment my-nginx deployment.apps "my-nginx" deleted [root@mgr ~]# kubectl delete pvc my-provisioner persistentvolumeclaim "my-provisioner" deleted [root@mgr ~]# kubectl get pv No resources found |
[5] | To use StatefulSet, it's possible to specify [volumeClaimTemplates]. |
[root@mgr ~]# kubectl get pv No resources found in default namespace. [root@mgr ~]# kubectl get pvc No resources found in default namespace. [root@mgr ~]# kubectl get storageclass NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE nfs-client cluster.local/nfs-client-nfs-subdir-external-provisioner Delete Immediate true 50m
[root@mgr ~]#
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@mgr ~]# kubectl get statefulset NAME READY AGE my-mginx 1/1 9s[root@mgr ~]# kubectl get pods NAME READY STATUS RESTARTS AGE my-mginx-0 1/1 Running 0 66s[root@mgr ~]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE data-my-mginx-0 Bound pvc-6a9bd00f-c3f6-45b8-8b76-2cdeab655eab 5Gi RWO nfs-client 82s[root@mgr ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-6a9bd00f-c3f6-45b8-8b76-2cdeab655eab 5Gi RWO Delete Bound default/data-my-mginx-0 nfs-client 91s |
Sponsored Link |