create an empty file inside a volume in Kubernetes pod

2/10/2021

I have a legacy app which keep checking an empty file inside a directory and perform certain action if the file timestamp is changed.

I am migrating this app to Kubernetes so I want to create an empty file inside the pod. I tried subpath like below but it doesn't create any file.

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  containers:
    - name: demo
      image: alpine
      command: ["sleep", "3600"]
      volumeMounts:
      - name: volume-name
        mountPath: '/volume-name-path'
        subPath: emptyFile
  volumes:
    - name: volume-name
      emptyDir: {} 

describe pods shows

Containers:
  demo:
    Container ID:  containerd://0b824265e96d75c5f77918326195d6029e22d17478ac54329deb47866bf8192d
    Image:         alpine
    Image ID:      docker.io/library/alpine@sha256:08d6ca16c60fe7490c03d10dc339d9fd8ea67c6466dea8d558526b1330a85930
    Port:          <none>
    Host Port:     <none>
    Command:
      sleep
      3600
    State:          Running
      Started:      Wed, 10 Feb 2021 12:23:43 -0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-4gp4x (ro)
      /volume-name-path from volume-name (rw,path="emptyFile")

ls on the volume also shows nothing. k8 exec -it demo-pod -c demo ls /volume-name-path

any suggestion??

PS: I don't want to use a ConfigMap and simply wants to create an empty file.

-- nothing_authentic
kubernetes
kubernetes-pod

2 Answers

2/10/2021

If the objective is to create a empty file when the Pod starts, then the most easy way is to either use the entrypoint of the docker image or an init container.

With the initContainer, you could go with something like the following (or with a more complex init image which you build and execute a whole bash script or something similar):

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  initContainers:
    - name: create-empty-file
      image: alpine
      command: ["touch", "/path/to/the/directory/empty_file"]
      volumeMounts:
      - name: volume-name
        mountPath: /path/to/the/directory
  containers:
    - name: demo
      image: alpine
      command: ["sleep", "3600"]
      volumeMounts:
      - name: volume-name
        mountPath: /path/to/the/directory
  volumes:
    - name: volume-name
      emptyDir: {}

Basically the init container gets executed first, runs its command and if it is successful, then it terminates and the main container starts running. They share the same volumes (and they can also mount them at different paths) so in the example, the init container mount the emptyDir volume, creates an empty file and then complete. When the main container starts, the file is already there.

Regarding your legacy application which is getting ported on Kubernetes:

If you have control of the Dockerfile, you could simply change it create an empty file at the path you are expecting it to be, so that when the app starts, the file is already created there, empty, from the beginning, just exactly as you add the application to the container, you can add also other files.

For more info on init container, please check the documentation (https://kubernetes.io/docs/concepts/workloads/pods/init-containers/)

-- AndD
Source: StackOverflow

2/11/2021

I think you may be interested in Container Lifecycle Hooks.
In this case, the PostStart hook may help create an empty file as soon as the container is started:

This hook is executed immediately after a container is created.

In the example below, I will show you how you can use the PostStart hook to create an empty file-test file.

First I created a simple manifest file:

# demo-pod.yml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: demo-pod
  name: demo-pod
spec:
  containers:
  - image: alpine
    name: demo-pod
    command: ["sleep", "3600"]
    lifecycle:
      postStart:
        exec:
          command: ["touch", "/mnt/file-test"]

After creating the Pod, we can check if the demo-pod container has an empty file-test file:

$ kubectl apply -f demo-pod.yml
pod/demo-pod created
$ kubectl exec -it demo-pod -- sh
/ # ls -l /mnt/file-test
-rw-r--r--    1 root     root             0 Feb 11 09:08 /mnt/file-test
/ # cat /mnt/file-test
/ #
-- matt_j
Source: StackOverflow