How can I mount a dynamically generated file into a pod without creating a ConfigMap?

1/6/2020

In my application, I have a control plane component which spawns Jobs on my k8s cluster. I'd like to be able to pass in a dynamically generated (but read-only) config file to each Job. The config file will be different for each Job.

One way to do that would be to create, for each new Job, a ConfigMap containing the desired contents of the config file, and then set the ConfigMap as a VolumeMount in the Job spec when launching the Job. But now I have two entities in the cluster which are semantically tied together but don't share a lifetime, i.e. if the Job ends, the ConfigMap won't automatically go away.

Is there a way to directly "mount a string" into the Job's Pod, without separately creating some backing entity like a ConfigMap to store it? I could pass it in as an environment variable, I guess, but that seems fragile due to length restrictions.

-- kini
kubernetes

2 Answers

1/7/2020

If you want to work around using configmaps and environment variables for passing configuration, the options you are left with are command line arguments and configuration files.

You can pass the config as command line argument to each of your Job.

You can also mount the config as file in to your Job pod. But since your controller which generates the config and Job which consumes it might be running on different nodes, you need a way to pass the config to the Job pod. If you have a network attached storage which is accessible for all nodes, your controller can write to location on shared storage and Job can read from it. Else, if you have a service(database, cache etc) that can act like a data store, your controller can write to the datastore and Job can read from there.

If you do not want to modify your Job to read the config from various sources, you can have an initContainer which does the job of reading the configuration from a certain source and writes it to a local pod volume(emptyDir) and Job can just read from the local file.

-- Shashank V
Source: StackOverflow

1/7/2020

The way that is traditionally done is via an initContainer and an emptyDir volumeMount that allows the two containers to "communicate" over a private shared piece of disk:

spec:
  initContainers:
  - name: config-gen
    image: docker.io/library/busybox:latest
    command:
    - /bin/sh
    - -ec
    # now you can use whatever magick you wish to generate the config
    - |
      echo "my-config: is-generated"   > /generated/sample.yaml
      echo "some-env: ${SOME_CONFIG}" >> /generated/sample.yaml
    env:
    - name: SOME_CONFIG
      value: subject to injection like any other kubernetes env var
    volumeMounts:
    - name: shared-space
      mountPath: /generated
  containers:
  - name: main
    image: docker.example.com:1234
    # now you can do whatever you want with the config file
    command:
    - /bin/cat
    - /config/sample.yaml
    volumeMounts:
    - name: shared-space
      mountPath: /config
  volumes:
  - name: shared-space
    emptyDir: {}
-- mdaniel
Source: StackOverflow