'Kubernetes mountPropagation clarifications

I have a docker image A that contains a folder I need to share with another container B in the same K8s pod.

At first I decided to use a shared volume (emptyDir) and launched A as an init container to copy all the content of the folder into the shared volume. This works fine.

Then looking at k8s doc I realised I could use mountPropagation between the containers. So I changed the initContainer to a plain container (side car) in the same pod and performed a mount of the container A folder I want to share with container B. This works fine but I need to keep the container running A up with a wait loop. Or not...

Then I decided to come back to the InitContainer pattern and do the same, meaning mount the folder in A inside the shared volume and then the container finishes cause it is an InitContainer and then use the newly mounted folder in container B. And it works !!!!

So my question is, can someone explains me if this is expected on all Kubernetes clusters ? and explain to me why the mounted folder from A that is no longer running as a container can still be seen by my other container ?

Here is a simple manifest to demonstrate it.

apiVersion: v1
kind: Pod
metadata:
  name: testvol
spec:
  initContainers:
    - name: busybox-init
      image: busybox
      securityContext:
        privileged: true
      command: ["/bin/sh"]
      args: ["-c", "mkdir -p /opt/connectors; echo \"bar\" > /opt/connectors/foo.txt;  mkdir -p /opt/connectors_new; mount --bind /opt/connectors /opt/connectors_new; echo connectors mount is ok"]
      volumeMounts:
        - name: connectors
          mountPath: /opt/connectors_new
          mountPropagation: Bidirectional

  containers:
    - name: busybox
      image: busybox
      command: ["/bin/sh"]
      args: ["-c", "cat /opt/connectors/foo.txt; trap : TERM INT; (while true; do sleep 1000; done) & wait"]
      volumeMounts:
        - name: connectors
          mountPath: /opt/connectors
          mountPropagation: HostToContainer
  volumes:
    - name: connectors
      emptyDir: {}

here the manifest to reproduce the behavior



Solution 1:[1]

This works because your containers run in a pod. The pod is where your volume is defined, not the container. So you are creating a volume in your pod that is an empty directory. Then you are mounting it in your init container and making changes. That makes changes to the volume on the pod.

Then when your init container finishes, the files at the pod level don't go away, they are still there, so your second container picks up the files when it mounts the same volume from the pod.

This is expected behavior and doesn't need mountPropagation fields at all. The mountPropagation fields may have some effect on emptyDir volumes, but it is not related to preserving the files:

https://kubernetes.io/docs/concepts/storage/volumes/#emptydir

All containers in the Pod can read and write the same files in the emptyDir volume, though that volume can be mounted at the same or different paths in each container. When a Pod is removed from a node for any reason, the data in the emptyDir is deleted permanently.

Note: A container crashing does not remove a Pod from a node. The data in an emptyDir volume is safe across container crashes.

The note here doesn't explicitly state it, but this implies it is also safe across initContainer to Container transitions. As long as your pod exists on the node, your data will be there in the volume.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Speeddymon