State Persistence (8%)

kubernetes.io > Documentation > Tasks > Configure Pods and Containers > Configure a Pod to Use a Volume for Storage

kubernetes.io > Documentation > Tasks > Configure Pods and Containers > Configure a Pod to Use a PersistentVolume for Storage

Define volumes

Create busybox pod with two containers, each one will have the image busybox and will run the ‘sleep 3600’ command. Make both containers mount an emptyDir at ‘/etc/foo’. Connect to the second busybox, write the first column of ‘/etc/passwd’ file to ‘/etc/foo/passwd’. Connect to the first busybox and write ‘/etc/foo/passwd’ file to standard output. Delete pod.

This question is probably a better fit for the ‘Multi-container-pods’ section but I’m keeping it here as it will help you get acquainted with state

Easiest way to do this is to create a template pod with:

kubectl run busybox --image=busybox --restart=Never -o yaml --dry-run=client -- /bin/sh -c 'sleep 3600' > pod.yaml
vi pod.yaml

Copy paste the container definition and type the lines that have a comment in the end:

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: busybox
  name: busybox
spec:
  dnsPolicy: ClusterFirst
  restartPolicy: Never
  containers:
  - args:
    - /bin/sh
    - -c
    - sleep 3600
    image: busybox
    imagePullPolicy: IfNotPresent
    name: busybox
    resources: {}
    volumeMounts: #
    - name: myvolume #
      mountPath: /etc/foo #
  - args:
    - /bin/sh
    - -c
    - sleep 3600
    image: busybox
    name: busybox2 # don't forget to change the name during copy paste, must be different from the first container's name!
    volumeMounts: #
    - name: myvolume #
      mountPath: /etc/foo #
  volumes: #
  - name: myvolume #
    emptyDir: {} #

Connect to the second container:

kubectl exec -it busybox -c busybox2 -- /bin/sh
cat /etc/passwd | cut -f 1 -d ':' > /etc/foo/passwd 
cat /etc/foo/passwd # confirm that stuff has been written successfully
exit

Connect to the first container:

kubectl exec -it busybox -c busybox -- /bin/sh
mount | grep foo # confirm the mounting
cat /etc/foo/passwd
exit
kubectl delete po busybox

Create a PersistentVolume of 10Gi, called ‘myvolume’. Make it have accessMode of ‘ReadWriteOnce’ and ‘ReadWriteMany’, storageClassName ‘normal’, mounted on hostPath ‘/etc/foo’. Save it on pv.yaml, add it to the cluster. Show the PersistentVolumes that exist on the cluster

vi pv.yaml
kind: PersistentVolume
apiVersion: v1
metadata:
  name: myvolume
spec:
  storageClassName: normal
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
    - ReadWriteMany
  hostPath:
    path: /etc/foo

Show the PersistentVolumes:

kubectl create -f pv.yaml
# will have status 'Available'
kubectl get pv

Create a PersistentVolumeClaim for this storage class, called mypvc, a request of 4Gi and an accessMode of ReadWriteOnce, with the storageClassName of normal, and save it on pvc.yaml. Create it on the cluster. Show the PersistentVolumeClaims of the cluster. Show the PersistentVolumes of the cluster

vi pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: mypvc
spec:
  storageClassName: normal
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi

Create it on the cluster:

kubectl create -f pvc.yaml

Show the PersistentVolumeClaims and PersistentVolumes:

kubectl get pvc # will show as 'Bound'
kubectl get pv # will show as 'Bound' as well

Create a busybox pod with command ‘sleep 3600’, save it on pod.yaml. Mount the PersistentVolumeClaim to ‘/etc/foo’. Connect to the ‘busybox’ pod, and copy the ‘/etc/passwd’ file to ‘/etc/foo/passwd’

Create a skeleton pod:

kubectl run busybox --image=busybox --restart=Never -o yaml --dry-run=client -- /bin/sh -c 'sleep 3600' > pod.yaml
vi pod.yaml

Add the lines that finish with a comment:

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: busybox
  name: busybox
spec:
  containers:
  - args:
    - /bin/sh
    - -c
    - sleep 3600
    image: busybox
    imagePullPolicy: IfNotPresent
    name: busybox
    resources: {}
    volumeMounts: #
    - name: myvolume #
      mountPath: /etc/foo #
  dnsPolicy: ClusterFirst
  restartPolicy: Never
  volumes: #
  - name: myvolume #
    persistentVolumeClaim: #
      claimName: mypvc #
status: {}

Create the pod:

kubectl create -f pod.yaml

Connect to the pod and copy ‘/etc/passwd’ to ‘/etc/foo/passwd’:

kubectl exec busybox -it -- cp /etc/passwd /etc/foo/passwd

Create a second pod which is identical with the one you just created (you can easily do it by changing the ‘name’ property on pod.yaml). Connect to it and verify that ‘/etc/foo’ contains the ‘passwd’ file. Delete pods to cleanup. Note: If you can’t see the file from the second pod, can you figure out why? What would you do to fix that?

Create the second pod, called busybox2:

vim pod.yaml
# change 'metadata.name: busybox' to 'metadata.name: busybox2'
kubectl create -f pod.yaml
kubectl exec busybox2 -- ls /etc/foo # will show 'passwd'
# cleanup
kubectl delete po busybox busybox2

If the file doesn’t show on the second pod but it shows on the first, it has most likely been scheduled on a different node.

# check which nodes the pods are on
kubectl get po busybox -o wide
kubectl get po busybox2 -o wide

If they are on different nodes, you won’t see the file, because we used the hostPath volume type. If you need to access the same files in a multi-node cluster, you need a volume type that is independent of a specific node. There are lots of different types per cloud provider (see here), a general solution could be to use NFS.

Create a busybox pod with ‘sleep 3600’ as arguments. Copy ‘/etc/passwd’ from the pod to your local folder

kubectl run busybox --image=busybox --restart=Never -- sleep 3600
kubectl cp busybox:etc/passwd ./passwd # kubectl cp command
# previous command might report an error, feel free to ignore it since copy command works
cat passwd
comments powered by Disqus