This article will guide you about how to create HostPath persistent volume in Kubernetes.

You might be knowing that data in the Pod exists till the life time of the Pod. If the Pod dies all your data that belongs to the Pod is also goes away along with Pod. So if you want to persist your data beyond the life cycle of the Pod then you must have some thing called as a Persistent volume in Kubernetes.
So lets study how to How to create HostPath persistent volume which is very easy to experiment. Also to gain knowledge about the fundamentals about the Persistent volume.
There are following types of Persistent volume types available to use within kubernetes by different vendors.

GCEPersistentDisk
AWSElasticBlockStore
AzureFile
AzureDisk
CSI
FC (Fibre Channel)
FlexVolume
Flocker
NFS
iSCSI
RBD (Ceph Block Device)
CephFS
Cinder (OpenStack block storage)
Glusterfs
VsphereVolume
Quobyte Volumes
HostPath (Single node testing only — local storage is not supported in any way and WILL NOT WORK in a multi-node cluster)
Portworx Volumes
ScaleIO Volumes
StorageOS

As you can see for the HostPath it should be used only for the testing purpose. Also it does not support multi-node cluster. In case you want to explore more about the Persistent volumes you may follow this link.
The Basic process for Persistent volumes is as follows:

K8s admin create the persistence volume in cluster.
User will claim it using Persistent volume claim once they claimed it status becomes “Bound”.
Then Pod use that volume for storing out the data which will persist across the life-cycle of Pod.

Enough for the theory Part Lets jump the Technical steps towards it:

Create the persistent volume

In this step we are using following manifest yaml file to achieve the same.
# cat hostpath-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-hostpath
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 1Gi
accessModes:
– ReadWriteOnce
hostPath:
path: “/tmp/kube”

As shown in the above definition file it is for the size 1GB. Path is “/tmp/kube”. Lets create the PV as below:
# kubectl create -f hostpath-pv.yaml
persistentvolume/pv-hostpath created

Recheck the PV and persistent volume claim using below command:
# kubectl get pv,pvc -o wide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv-hostpath 1Gi RWO Retain Available manual 6s Filesystem

As you can see the PV is created having status as Available and since we haven’t specified the reclaim policy default is applied which is “Retain” meaning that the even if the pvc (Persistent volume claim) gets deleted the PV and data wont get deleted automatically. We will test it out that also in a bit.

Create the Persistent volume claim

In order to use the PV we need to create the Persistent volume claim or pvc to use it.  Here is the manifest yaml file for the same.
# cat pvc-hostpath.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-hostpath
spec:
storageClassName: manual
accessModes:
– ReadWriteOnce
resources:
requests:
storage: 100Mi

Kindly note in the above definition that the claim is only for the 100mb(>= size of PV) also the Access mode is “ReadWriteOnce” which is same as that of PV. Hence we can able to create the PVC as below:
# kubectl create -f pvc-hostpath.yaml
persistentvolumeclaim/pvc-hostpath created

Check the status of pv and pvc.
# kubectl get pv,pvc -o wide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv-hostpath 1Gi RWO Retain Bound default/pvc-hostpath manual 20s Filesystem

NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc-hostpath Bound pv-hostpath 1Gi RWO manual 4s Filesystem

You will see that the status of the pv becomes Bound from Available which was earlier.

Create the Pod to utilize this PV as a mount point inside it.

# cat busybox-pv-hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox
spec:
volumes:
– name: host-volume
persistentVolumeClaim:
claimName: pvc-hostpath
containers:
– image: busybox
name: busybox
command: [“/bin/sh”]
args: [“-c”, “sleep 600”]
volumeMounts:
– name: host-volume
mountPath: /tmp/mydata

As describe in the Pod definition file it will create the mount point /tmp/mydata inside the Pod. Lets create the Pod using above definition file.
# kubectl create -f busybox-pv-hostpath.yaml
pod/busybox created

Check the status and inspect the Pod:
# kubectl get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/busybox 1/1 Running 0 2m4s 10.244.1.114 kworker01 <none> <none>

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 35d <none>

# kubectl describe pod busybox
Name: busybox
Namespace: default
Priority: 0
Node: kworker01/10.253.121.32
Start Time: Mon, 06 Jul 2020 02:43:16 -0400
Labels: <none>
Annotations: <none>
Status: Running
IP: 10.244.1.114
IPs:
IP: 10.244.1.114
Containers:
busybox:
Container ID: docker://6d1cfa9b6440efe2770244d1edc6a78c0dd7649bbf905121e70a013ad3b1dd1e
Image: busybox
Image ID: docker-pullable://busybox@sha256:9ddee63a712cea977267342e8750ecbc60d3aab25f04ceacfa795e6fce341793
Port: <none>
Host Port: <none>
Command:
/bin/sh
Args:
-c
sleep 600
State: Running
Started: Mon, 06 Jul 2020 02:43:25 -0400
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/tmp/mydata from host-volume (rw)
/var/run/secrets/kubernetes.io/serviceaccount from default-token-49xz2 (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
host-volume:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: pvc-hostpath
ReadOnly: false
default-token-49xz2:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-49xz2
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
—- —— —- —- ——-
Normal Scheduled <unknown> default-scheduler Successfully assigned default/busybox to kworker01
Normal Pulling 64s kubelet, kworker01 Pulling image “busybox”
Normal Pulled 58s kubelet, kworker01 Successfully pulled image “busybox”
Normal Created 58s kubelet, kworker01 Created container busybox
Normal Started 57s kubelet, kworker01 Started container busybox

In the describe output you can see that, /tmp/mydata volume got created using host-volume from the claim pvc-hostpath. Also the Pod is scheduled/create on the node “kworker01”.
Lets login inside the Pod to create the sample file. In order to demonstrate the life cycle of the data even if the Pod dies.
# kubectl exec -it busybox — sh
/ # hostname
busybox
/ # cd /tmp/
/tmp # ls
mydata
/tmp # cd mydata/
/tmp/mydata # echo “hello from K8S” > Hello.txt
/tmp/mydata # ls -ltr
total 4
-rw-r–r– 1 root root 15 Jul 6 06:46 Hello.txt
/tmp/mydata #

In the above demo we have created file “Hello.txt” inside /tmp/mydata. Now lets delete the Pod.
# kubectl delete pod busybox
pod “busybox” deleted
root@vbhost:~/kubernetes/yamls# kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 35d

Pod got deleted successfully lets login to the node “kworker01” where Pod got scheduled earlier to check if the data still persist after the deletion of the Pod.
sh-4.2# hostname
kworker01
sh-4.2# cd /tmp
sh-4.2# ls
kube
sh-4.2# cd kube/
sh-4.2# ls
Hello.txt
sh-4.2# cat Hello.txt
hello from K8S
sh-4.2# exit

You can see that our file “Hello.txt” still exists on the Node even the Pod dies.
So this is all about “How to create HostPath persistent volume” in Kubernetes.
 

- A word from our sposor -

How to create HostPath persistent volume in Kubernetes