Search code examples
kubernetessynchronizationpersistent-volumes

how to sync initial files to persistent volume (e.g., NFS)?


A webapp (docker image) accesses a directory "/usr/local/myapp" at runtime that has initial files:

   /usr/local/myapp/
                    conf/
                        foo.xml
                    web-files/
                        index.html
                        images/
                        

In standalone container, the webapp access files under the directory, including reading configuration files, creating new files, deleting files.

For kubernetes cluster, the directory "/usr/local/myapp" needs to be shared in cluster. If using NFS mounting to all pods, all existing files(e.g. conf/foo.xml) under the shared directory will not be accessible (hidden by volume, not sync-ed to volume).

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my_web
spec:
  template:
    spec:
      containers:
        - image: my-web-app:1.0
          volumeMounts:
            - name: my-volume
              mountPath: /usr/local/myapp

      volumes:
        - name: my-volume
          persistentVolumeClaim:
            claimName: my-pv-claim

For k8s, what is the right way to sync initial existing content from docker image to shared volume(e.g., NFS)? For docker volume, the initial existing content will be sync-ed to the volume if the volume is empty.


Solution

  • Usually, when it comes to moving data into mounted folders or volumes, you run an init container that takes care of it. Sadly, there's not really a better way to do this at the moment. When mounting new volumes, if the path exists, every file and folder in it will disappear into thin air. This is true for PVCs as well. However, if the PVC itself already existed and had files, said files won't be deleted upon mounting the volume.

    You could also run the startup command on container init, but in order to keep it simple and with only one init command, running it in an init container seems best.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my_web
    spec:
      template:
        spec:
          initContainers:
            - image: my-web-app:1.0
              volumeMounts:
                - name: my-volume
                  mountPath: /usr/local/myapp
              command:
                - /bin/sh
                - -c
                - cp -R <source-dir> /usr/local/myapp
          containers:
            - image: my-web-app:1.0
              volumeMounts:
                - name: my-volume
                  mountPath: /usr/local/myapp
          volumes:
            - name: my-volume
              persistentVolumeClaim:
                claimName: my-pv-claim
    

    Note: This example only works if these files will not be updated and thus you don't need persistence, thus I would remove the PVC so as to not waste resources. Instead, use a volume of type emptyDir.

    Also, I don't think NFS in Kubernetes works with PVCs. You can read more about NFS with K8s here.