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].