Persistent volume type: HOST PATH

  • the correct choice for databases, such as MySQL;
  • mounts a volume (file or directory) from the host node’s file system into the Pod;
  • accessible from all pods in the same node;
  • not accessible from other nodes of the cluster;
  • if the node crashes, the data is lost.

Create the nginx-deployment-hostpath.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx-instance
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-instance
  template:
    metadata:
      labels:
        app: nginx-instance
    spec:
      containers:
      - name: nginx-instance
        image: nginx
        imagePullPolicy: Always
        ports:
        - containerPort: 80
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
      volumes:
      - name: www
        hostPath:
          path: /mnt/data

The page may show a forbidden error because the mounted directory (/usr/share/nginx/html) inside the pod is empty. The data is physically stored in (/mnt/data) on the host node.

Create the nginx-loadbalancer.yaml:

apiVersion: v1
kind: Service
metadata:
  name: nginx-loadbalancer
  annotations:
    service.beta.kubernetes.io/linode-loadbalancer-throttle: "5"
  labels:
    app: nginx-loadbalancer
spec:
  type: LoadBalancer
  selector:
    app: nginx-instance
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80
  sessionAffinity: None

Apply everything:

export KUBECONFIG=kube1-kubeconfig.yaml
kubectl apply -f nginx-deployment-hostpath.yaml
kubectl apply -f nginx-loadbalancer.yaml 
kubectl get services

Get the public IP of the load balancer and open it in the browser.

Get the pod names and create a file inside the mounted volume using one of the pods (the bold part is the random suffix appended to the name):

kubectl get pods
kubectl exec -ti nginx-deployment-6fb5f9998b-qngbk -- /bin/bash -c "echo 'TEST 1' > /usr/share/nginx/html/index.html"

To open a shell inside the pod:

kubectl exec -ti nginx-deployment-6fb5f9998b-qngbk -- /bin/bash

Persistent volume type: NFS

  • mounts a shared directory from the NFS Server’s file system into the Pod;
  • accessible from all pods on the same network, regardless of node or cluster;
  • not inside the cluster and must be set up manually;
  • if the node or cluster crashes, the data remains;
  • requires manual backup and management on the NFS Server.

Configure an Ubuntu NFS server (a virtual machine outside the Kubernetes cluster):

sudo apt-get update
sudo apt-get install nfs-kernel-server rpcbind -y
sudo ufw allow nfs
sudo nano /etc/exports

Append:

/files *(rw,sync,no_subtree_check,insecure)

This configuration is insecure and should only be used for proof of concept. At minimum, replace * with the IP of the Kubernetes cluster, for example 192.168.1.7 or 192.168.1.0/24.

Activate the NFS shares:

sudo exportfs -ra

Create the nginx-deployment-nfs.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx-instance
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-instance
  template:
    metadata:
      labels:
        app: nginx-instance
    spec:
      containers:
      - name: nginx-instance
        image: nginx
        imagePullPolicy: Always
        ports:
        - containerPort: 80
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html/
      volumes:
      - name: www
        persistentVolumeClaim:
          claimName: www-pvc

Create the nginx-nfs-pv.yaml:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: www-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 192.168.1.1
    path: "/data/share"

Replace the server IP (192.168.1.1) and path (/data/share) with the correct values.

Create the nginx-nfs-pvc.yaml:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: www-pvc
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: ""
  resources:
    requests:
      storage: 10Gi

Create the nginx-loadbalancer.yaml as in the previous example.

Apply everything:

export KUBECONFIG=kube1-kubeconfig.yaml
kubectl apply -f nginx-nfs-pv.yaml
kubectl apply -f nginx-nfs-pvc.yaml
kubectl apply -f nginx-deployment-nfs.yaml
kubectl apply -f nginx-loadbalancer.yaml
kubectl get services

Get the public IP of the load balancer and open it in the browser.


Persistent volume type: Linode Block Storage (Volume)

  • a drive that can be mounted into pods of the same cluster;
  • physically located outside the cluster but created through kubectl;
  • if the node or cluster crashes, the data remains;
  • can also be attached to a virtual machine when not attached to a node.

Create the nginx-deployment-vol.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx-instance
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-instance
  template:
    metadata:
      labels:
        app: nginx-instance
    spec:
      containers:
      - name: nginx-instance
        image: nginx
        imagePullPolicy: Always
        ports:
        - containerPort: 80
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html/
      volumes:
      - name: www
        persistentVolumeClaim:
          claimName: www-pvc

Create the nginx-vol-pvc.yaml:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: www-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: linode-block-storage

Create the nginx-loadbalancer.yaml as in the previous example.

Note that linode-block-storage is limited to ReadWriteOnce and supports sizes from 10Gi to 10240Gi.

  • ReadWriteOnce – Can only be attached to one node.
  • ReadWriteMany – Can be attached to multiple nodes; used with NFS, for example.

Apply everything:

export KUBECONFIG=kube1-kubeconfig.yaml
kubectl apply -f nginx-vol-pvc.yaml
kubectl apply -f nginx-deployment-vol.yaml
kubectl apply -f nginx-loadbalancer.yaml
kubectl get services

The block storage will be created automatically.

Get the public IP of the load balancer and open it in the browser.


OTHER POSTS

Minikube on Ubuntu 22.04 [Link].

MicroK8s on Ubuntu 22.04 [Link].

K3s on Ubuntu 22.04 [Link].

Kubernetes Persistent Volumes [Link].

Kubernetes Cheat Sheet [Link].

Kubernetes Dashboard [Link].