Kubernetes Persistent Volumes Deployment Guide utilising an external NFS

Step 1: Create a Persistent Volume (PV)

Define a Persistent Volume using the following configuration:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
  labels:
    type: shared
spec:
  storageClassName: manual
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  nfs:
    path: /volume1/k8s/nginx_data
    server: nas.batcave.local

The path and server need to match your NFS server and path.

Step 2: Create a Persistent Volume Claim (PVC)

Define a Persistent Volume Claim to request storage:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: shared-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi

This is stating 'use 1Gb of the 10Gb volume'.

Step 3: Create a Service

Define a NodePort Service to expose the application:

apiVersion: v1
kind: Service
metadata:
  name: app-nginx-service
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 30020
  selector:
    app: app-nginx

Choose any NodePort you would like, I went with 30020 here. This expose my NGINX server on http://<NodeIP>:30020.

Step 4: Create a Deployment

Deploy the NGINX application and mount the Persistent Volume:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: app-nginx
  template:
    metadata:
      labels:
        app: app-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.3
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: shared-storage
      volumes:
      - name: shared-storage
        persistentVolumeClaim:
          claimName: shared-pv-claim

Remember the mountPath is the location within the NGINX container utilised for the default index.html page. The countainerPort 80 is the default listening port of nginx:1.17.3 image.

Step 5: Apply the Configurations

Apply all the YAML configurations to create the resources:

kubectl apply -f pv1.yaml
kubectl apply -f pvc1.yaml
kubectl apply -f nginx_deployment.yaml
kubectl apply -f service.yaml

Feel free to combine the configuration into one yaml or alternately apply all using kubectl apply -f . from within the directory.

Step 6: Verify the Resources

Check the status of the created resources:

kubectl get pv
kubectl get pvc
kubectl get deployments
kubectl get svc
kubectl get pods -o wide

Step 7: Test the Setup

Test the setup by writing to the NGINX data directory and accessing the service:

echo "Nginx running in K8S!" > /mnt/k8s/nginx_data/index.html
curl http://<NodeIP>:30020

The mount location where you create you index.html will need to match your location reference storage of NGINX files (or just create an index.html on the NFS server itself).