Kubernetes Storage - NFS

 


Post shows how to use NFS as Persistent volumes and claim in Kubernetes pod.

Setting up NFS Server:

Install the NFS package.

root@glusterfs:/# apt install -y nfs-server

root@glusterfs:/# mkdir /data

root@glusterfs:/# cat /etc/exports | grep -v "^#"

/data *(rw,no_subtree_check,no_root_squash)

root@glusterfs:/#

root@glusterfs:/# systemctl status nfs-server

root@glusterfs:/# systemctl enable  nfs-server

root@glusterfs:/# exportfs -arv

exporting *:/data

root@glusterfs:/#

root@glusterfs:/# chmod -R 777 /data/


We are done with the NFS server and lets mount it on the client.

root@master:/# cat /etc/fstab | grep -i data

192.168.163.129:/data /data nfs4 defaults 0 0

root@master:/#

You may have to install - nfs-client on the client side.

root@master:/# mount -a

root@master:/# df -TH /data

Filesystem            Type  Size  Used Avail Use% Mounted on

192.168.163.129:/data nfs4   21G  8.5G   11G  44% /data

root@master:/#

Connecting to NFS directly with Pod manifest:

apiVersion: v1

kind: Pod

metadata:

  name: nfs-pod

spec:

  containers:

    - name: nginx

      image: nginx

      volumeMounts:

        - name: nfs-volume

          mountPath: /data

  volumes:

    - name: nfs-volume

      nfs:

        server: 192.168.163.129

        path: /data

        readOnly: no


root@master:/kube# kubectl get pods

NAME      READY   STATUS    RESTARTS   AGE

nfs-pod   1/1     Running   0          9s

root@master:/kube# 


root@master:/kube# kubectl exec -it nfs-pod sh -- ls -l /data

total 0

root@master:/kube# kubectl exec -it nfs-pod sh -- df -TH /data

Filesystem            Type  Size  Used Avail Use% Mounted on

192.168.163.129:/data nfs4   21G  8.5G   11G  44% /data

root@master:/kube#


By default nginx serves files from the /usr/share/nginx/html directory which we can verify from our running container.


Lets map this location from the NFS.

root@master:/data# cat index.html

This page loaded from NFS.

root@master:/data#

root@master:/kube# cat nfs_pod.yml

apiVersion: v1

kind: Pod

metadata:

  name: nfs-pod

spec:

  containers:

    - name: nginx

      image: nginx

      volumeMounts:

        - name: nfs-volume

          mountPath: /usr/share/nginx/html/

  volumes:

    - name: nfs-volume

      nfs:

        server: 192.168.163.129

        path: /data

        readOnly: no

root@master:/kube#


root@master:/kube# kubectl get pods

NAME      READY   STATUS    RESTARTS   AGE

nfs-pod   1/1     Running   0          2m43s

root@master:/kube#

root@master:/kube# kubectl expose pod nfs-pod --type=NodePort --port=80

error: couldn't retrieve selectors via --selector flag or introspection: the pod has no labels and cannot be exposed

root@master:/kube#


Let me recreate a pod with label.

root@master:/kube# cat nfs_pod.yml

apiVersion: v1

kind: Pod

metadata:

  name: nfs-pod

  labels:

    app: web-server

spec:

  containers:

    - name: nginx

      image: nginx

      volumeMounts:

        - name: nfs-volume

          mountPath: /usr/share/nginx/html/

  volumes:

    - name: nfs-volume

      nfs:

        server: 192.168.163.129

        path: /data

        readOnly: no

root@master:/kube#


root@master:/kube# kubectl expose pod nfs-pod --type=NodePort --port=80

service/nfs-pod exposed

root@master:/kube#


root@master:/kube# kubectl get ep

NAME         ENDPOINTS              AGE

kubernetes   192.168.163.128:6443   9d

nfs-pod      10.244.0.19:80         15s

root@master:/kube# curl 10.244.0.19

This page loaded from NFS.

root@master:/kube#


Connecting using the PersistentVolume resource:

To create the PersistentVolume object for the NFS volume, use the following manifest. You should note that the storage size does not take any effect.

root@master:/kube# cat nfspv.yml

apiVersion: v1

kind: PersistentVolume

metadata:

  name: nfs-volume

  labels:

    storage.k8s.io/name: nfs

    storage.k8s.io/part-of: kubernetes-volumes

    storage.k8s.io/created-by: Rajasekar

spec:

  accessModes:

    - ReadWriteOnce

    - ReadOnlyMany

    - ReadWriteMany

  capacity:

    storage: 1Gi

  storageClassName: ""

  persistentVolumeReclaimPolicy: Recycle

  volumeMode: Filesystem

  nfs:

    server: 192.168.163.129

    path: /data

    readOnly: no

root@master:/kube#


root@master:/kube# kubectl apply -f nfspv.yml

persistentvolume/nfs-volume created

root@master:/kube#


root@master:/kube# kubectl get pv

NAME         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE

nfs-volume   1Gi        RWO,ROX,RWX    Recycle          Available                                   16s

root@master:/kube#

And we'll create a Persistent Volume claim to bind to the PV we just created.

root@master:/kube# cat pvc.yml

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

  name: nfs-pvc

spec:

  storageClassName: ""

  volumeName: nfs-volume

  accessModes:

    - ReadWriteMany

  volumeMode: Filesystem

  resources:

    requests:

      storage: 1G

root@master:/kube#


root@master:/kube# kubectl get pv

NAME         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE

nfs-volume   1Gi        RWO,ROX,RWX    Recycle          Bound    default/nfs-pvc                           16m

root@master:/kube# kubectl get pvc

NAME      STATUS    VOLUME       CAPACITY   ACCESS MODES   STORAGECLASS   AGE

nfs-pvc   Pending   nfs-volume   0                                        5s

root@master:/kube#


root@master:/kube# cat nfs_pod.yml

apiVersion: v1

kind: Pod

metadata:

  name: nfs-pod

  labels:

    app: web-server

spec:

  containers:

    - name: nginx

      image: nginx

      volumeMounts:

        - name: nfs-volume

          mountPath: /usr/share/nginx/html/

  volumes:

    - name: nfs-volume

      persistentVolumeClaim:

        claimName: nfs-pvc

root@master:/kube#


root@master:/kube# kubectl apply -f nfs_pod.yml

pod/nfs-pod created

root@master:/kube# kubectl get pods

NAME      READY   STATUS    RESTARTS   AGE

nfs-pod   1/1     Running   0          4s

root@master:/kube#


root@master:/# kubectl get pv

NAME         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE

nfs-volume   1Gi        RWO,ROX,RWX    Recycle          Bound    default/nfs-pvc                           19m

root@master:/# kubectl get pvc

NAME      STATUS   VOLUME       CAPACITY   ACCESS MODES   STORAGECLASS   AGE

nfs-pvc   Bound    nfs-volume   1Gi        RWO,ROX,RWX                   3m11s

root@master:/#


root@nfs-pod:/# ls -l /usr/share/nginx/html

total 4

-rw-r--r-- 1 root root 27 Jun  1 22:05 index.html

root@nfs-pod:/#


root@master:/# kubectl delete pod nfs-pod

pod "nfs-pod" deleted

root@master:/#


root@master:/# kubectl get pv

NAME         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE

nfs-volume   1Gi        RWO,ROX,RWX    Recycle          Bound    default/nfs-pvc                           20m

root@master:/# kubectl get pvc

NAME      STATUS   VOLUME       CAPACITY   ACCESS MODES   STORAGECLASS   AGE

nfs-pvc   Bound    nfs-volume   1Gi        RWO,ROX,RWX                   4m11s

root@master:/#


Comments

Popular posts from this blog

SRE/DevOps Syllabus

AWS Code Commit - CI/CD Series Part 1

Docker - Preventing IP overlapping