Getting data in Kubernetes pod before the container starts

9/28/2018

I have a python program that can control a Kubernetes cluster (from outside). During that program execution, it obtains a byte array.

I have full pod spec ready to be created.

I need to modify the pod spec (adding an init container) so that when the main container starts, there is a file somewhere with those exact bytes.

What's the easiest way to do that?

-- Ark-kun
kubernetes
python

2 Answers

9/28/2018

This is more of an opinion question/answer.

If it happens that your python script generates specific bytes I would go with an initContainer with a volume. Something like this:

initContainers:
- name: init-container
  image: container:version
  command: [ 'your-python.py' ]
  volumeMounts:
  - name: conf
    mountPath: /mnt/conf.d
containers:
- name: app-container
  image: container:version
  command: [ 'your-actual-app' ]
  volumeMounts:
  - name: conf
    mountPath: /mnt/conf.d

If your bytes are straight UTF-8 characters, for example, it's easier to just use a ConfigMap

-- Rico
Source: StackOverflow

10/1/2018

If I understand your question correctly, you want to run a Python script that will extract or derive a byte array from somewhere before your Pod starts, and writes this byte array to a file for your actual application to read from when running inside the Pod.

I can see 2 ways to achieve this:

  • Slightly modify your Docker image to run your script as an entrypoint and then running your application (command: & args: in your Pod spec). You would ship both together and won't need an initContainer.
  • Or as you were tending for: use a combination of initContainer and Volumes

For the later:

template:
  spec:
    volumes:
    - name: byte-array
      emptyDir: {}
    initContainers:
        - name: byte-array-generator
          image: your/init-image:latest
          command: ["/usr/bin/python", "byte_array_generator.py"]
          volumeMounts:
            - mountPath: /my/byte-array/
              name: byte-array
    containers:
    - name: application
      image: your/actual-app:latest
      volumeMounts:
        - name: byte-array
          mountPath: /byte-array/

I condensed all 3 parts:

  • 1 empty volume definition used to pass over the file
  • 1 initContainer with your script generating the byte array and writing it to disk in let's say /my/byte-array/bytearray.bin (where the volume has been mounted)
  • 1 actual container running your application and reading the byte array from /byte-array/bytearray.bin (where the volume has been mounted)

One important note from there you also need to take into consideration is: if you mount your volume on a pre-existing folder with actual files, they will all "overwritten" by your volume. The source will take the destination's place. You might be able to prevent that using subPath but I never tried with this way, I only know it works if you mount ConfigMaps as volumes.

Edit: the answer to your comment is too long

Outside the container or outside the Kubernetes cluster ? Maybe there is a misconception, so just in case: an initContainer doesn't have to use the same image as your Pod's. You could even load your script as a ConfigMap and mount it into the initContainer using Python base image to run it if you want...

But if really your script has to be running outside of the cluster and send a file enabling your Pod to start, I'd suggest you add a logic to your byte generation that will output it to a file taking the Pod hostname for example (from Kubernetes API), and scp it to the Kubernetes node running it (pulled from Kubernetes API too) into a know destination. Just define a folder on each of your nodes, like /var/data/your_app/ and mount it on all your pods.

volumes:
  - hostPath:
       path: /var/data/your_app
      type: Directory
    name: bite-arrays

then mount bite-arrays wherever you want in whatever container needs to read it by reusing its hostname (to allow you to scale if necessary). Since you said your script is controlling the cluster, I assume it's already talking to Kubernetes' API... You might also want to create a logic to cleanup left-overs...

Or maybe we got it all wrong and somehow your script is also generating and applying the Pod spec on the fly, which in this case could just be solved by an environment variable or a ConfigMap shipped alongside...

Pod spec:

volumes:
  - name: byte-array
    configMap:
      name: your-app-bytes

volumeMounts:
  - name: byte-array
    mountPath: /data/your-app/byte-array
    readOnly: true
    subPath: byte-array

ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: your-app-bytes
data:
  byte-array: |-
    WHATEVERBYTESAREGENERATEDHERE
-- Hiruma
Source: StackOverflow