Search code examples
kubernetespersistent-volumeskubernetes-pvc

Is there a way to share existing data between containers in a pod?


I have 2 containers in a pod. 1. Webapp 2. Nginx I would like to share the data from Webapp container /var/www/webapp/ with the nginx container. /var/www/html

/var/www/webapp ( folder structure )
│   index.php
│       
│
└───folder1
│   │   service1.php
│   │   
│   └───subfolder1
│       │   app.php
│   
└───folder2
    │   service2.php  

The folder is mounted properly but all the files are missing.

apiVersion: apps/v1
kind: Deployment
    spec:
      volumes:
      - name: webapp-data
        persistentVolumeClaim:
          claimName: webapp-data
      containers:
      - name: webapp
        image: webapp
        imagePullPolicy: Always 
        volumeMounts:
        - name: webapp-data
          mountPath: /var/www/webapp/
       - name: nginx
        imagePullPolicy: Always
        image: nginx
        volumeMounts:
        - name: webapp-data
          mountPath: /var/www/html/
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: webapp-data
spec:
  storageClassName: local
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

When mounting a volume under docker all the folders and files from within the container are available but not in k8s.


Solution

  • Kubernetes will not automatically populate an empty volume with contents from an image. (This is a difference from docker run.) Your application needs to figure out how to set up the shared-data directory itself, if it's empty.

    For standard database containers this doesn't really matter since they typically start off with some sort of initdb type call which will create the required file structure. Similarly, if you're using a persistent volume as a cache or upload space, it doesn't matter.

    For the use case you're describing where you want one container to just have a copy of files from the other, you don't really need a persistent volume. I'd use an emptyDir volume that can be shared between the two containers, and then an init container to copy data into the volume. Do not mount anything over the application content.

    This would roughly look like (in reality use a Deployment):

    apiVersion: v1
    kind: Pod
    metadata:
      name: ...
    spec:
      volumes:
        - name: webapp-data
          emptyDir: {}
      initContainers:
        - name: populate
          image: webapp
          volumeMounts:
            - name: webapp-data
              mountPath: /data
          command: [cp, -a, /var/www/webapp, /data]
      containers:
        - name: webapp
          image: webapp
          # no volumeMounts; default command
        - name: nginx
          image: nginx
          volumeMounts:
            - name: webapp-data
              mountPath: /var/www/html
    

    With this setup there's also not a hard requirement that the two containers run in the same pod; you could have one deployment that runs the back-end service, and a second deployment that runs nginx (starting up by copying data from the back-end image).

    (The example in Configure Pod Initialization in the Kubernetes docs is very similar, but fetches the nginx content from an external site.)