Lab_03 - Persisting Data
Lab 03: Persisting Data
In this lab, we will see how we can keep our data, even though our containers are (and should be!) ephemeral.
emptyDir
We will start with a very simple example - the emptyDir
volume type. This simply uses a directory on the node the pod is running on.
Connect to the master node with your user credentials. Make sure that there are no pods already running on the system (in the default namespace).
Copy the 02-alpine.yaml
file to a new file: 09-emptydir.yaml
Edit the new file to add an emptyDir
volume. Name the volume empty-volume
, and mount it in /scratch
Create a pod based on this specification.
Solution
09-emptydir.yaml
:
Get a shell inside the pod. Create a file inside the /scratch directory, with a text contents of your choosing.
Hint
you can connect to the existing shell (kubectl attach
), or you can open a new one (kubectl exec
). Which one you choose is very relevant when you exit the pod!
Solution
Inside the container:
Exit the pod and delete it.
Solution
Inside the container:
Create a new pod based on the same yaml file.
Solution
Get a shell inside the new pod. Is your file still inside?
Solution
Note
While emptyDir
volumes wil survive a pod crash/restart, they will be removed when the pod itself is removed.
Exit the pod and delete it.
hostPath
A more relevant (more… persistent) example is the hostPath volume type. This will actually persist across pod deletions, but has another disadvantage - it makes the pod dependent on a specific host (a specific host directory structure). So in order to make sure that the pods will find that directory structure, we will force them to always run on a specific host.
Needless to say, this is not something you would generally want to do in production. However, it is a useful exercise for dealing with labels and selectors.
In order to make testing easier, we want to force our pod to run on one specific node (it is easier this way than chasing the pods across multiple nodes). In order to do this, we will use a label. Label your first worker node (k8s-ID-02
) with pathConfiguredID=true
(replace ID
with your user ID).
Solution
Make sure that the label has been correctly applied.
Solution
Copy the 09-emptydir.yaml
file to 10-hostpath.yaml
.
Edit the 10-hostpath.yaml
file to add the following:
A node selector that forces the pod to run only on nodes labeled with pathConfiguredID=true. (under
.spec.nodeSelector
).A volume named host-volume mapped to the host directory
/tmp/hostpath
A volumeMount for the container that tells it to mount the volume under /hostvol
Create a pod based on this new specification file.
Solution
10-hostpath.yaml
:
Get a shell into the pod, and create a test file in /hostvol
. Use a content of your choosing.
Solution
Inside the pod:
Exit the pod. Check the /tmp/hostpath
directory. You should see your newly-created file.
Solution
Delete the pod, and create a new one based on the same YAML file. Get a shell into the pod. The file should still be in /hostvol
.
Solution
Inside the pod:
Delete the pod.
Optional: NFS Volume
Getting closer to a real-life deployment - we will be using an NFS mount that we connect to over the network. The task is marked as optional because it has a prerequisite that cannot always be satisfied - a server that has been preconfigured to export an NFS mount over the network. The NFS mount has also been prepopulated with an index.html file, so that you can test whether your configuration is correct.
Note
While closer to a real-life example, we are not there yet! We are still using volumes defined at the pod level, which are closely coupled to the pods themselves. A real life scenario would actually be using PVs/PVCs (see the next section).
Copy 10-hostpath.yaml
to 11-nfs.yaml
.
Edit the 11-nfs.yaml file to change the following:
the pod should be running nginx (which also means that stdin and tty are no longer necessary)
the nodeSelector is no longer necessary (all nodes have equal access to the NFS datastore)
the pod name should be nginx-01
the volume type is now nfs, on server 10.10.17.34, path /NFS_STUDENTS (remember that file and directory names are case sensitive!)
the volume name is nfs-vol-xx (with xx being your user ID)
the volume is mounted inside the container as /usr/share/nginx/html (the default nginx web server root)
Create a pod based on this specification.
Solution
10-hostpath.yaml
:
Make sure that the pod is running correctly.
If the pod seems to be stuck in „Pending” or „ContainerCreating”, it is likely that the NFS mount has failed. Use kubectl
describe to get more details, and ask your instructor for assistance.
Solution
Get the pod IP address. Connect to the pod IP address using curl. You should get a page confirming that you have successfully completed this task.
Solution
Delete the pod.
Solution
Bonus: PVs
For the most complex scenario, we will use the NFS mount to provision multiple persistent volumes for our various pods. We will work with persistent volumes, persistent volume claims, and pods. To keep things simpler, we will define the components in separate files.
Create a YAML file (12-nfs-pv.yaml
) for the NFS persistent volume. The details are below:
name: nfs-pv01-ID (replace
ID
with your assigned ID).spec.capacity.storage: 2Mi
.spec.accessModes: [ ReadWriteOnce ]
type: nfs
.spec.nfs.server: 10.10.17.34
.spec.nfs.path: /NFS_STUDENTS
Note
If you have not seen the „Mi” notation before, that is a „mebibyte”. The kibi/mebi/gibi notation has been introduced to differentiate between regular SI prefixes (powers of 10) and binary prefixes (powers of 2). More details here: https://en.wikipedia.org/wiki/Binary_prefix
Hint
Solution
12-nfs-pv.yaml
:
Apply the file to create a PersistentVolume.
Solution
Check the list of PersistentVolumes to verify that the new volume has been successfully created.
Solution
Create another YAML file ( 13-nfs-pvc.yaml ), that defines a PersistentVolumeClaim. The claim will be named nfs-pvc01
, and will request a PV with a size of 2Mi.
Hint
Create a PVC based on this new file.
Solution
13-nfs-pvc.yaml
:
Verify that the PVC has been successfully created, and that Kubernetes has bound it to the available NFS PV ( nfs-pv01 ).
Solution
Create a YAML file ( 14-nfs-pod.yaml ) for a pod that mounts the PVC as a volume:
The pod should run nginx
The name of the pod should be nginx-nfs
The pod should mount a volume under /usr/share/nginx/html
The volume should be the PVC we created earlier ( nfs-pvc01 )
Hint
Create a pod based on this file. Check that the pod has successfully started.
Solution
14-nfs-pod.yaml
:
Get the pod IP address and connect to it using curl
. What do you see?
Solution
Note
You should get the exact same congratulatory file you have seen in the previous exercise. And it is normal - after all, we are mounting the exact same volume! The difference is that this time the allocation of the volume is done dynamically, based on the volume size (specified in the PV) and the size requested by the pod (via PVC).
Cleaning Up
Delete all PVs, PVCs, and pods.
Solution
Last updated