How to get values from Helm locally without separate environment variable system?

12/17/2019

I have a Python application that is deployed using Helm and Kubernetes. I want to take hard-coded variables out of main.py and make them configurable in Helm. The trouble is if I pull them out of main.py then I lose the ability to run my code with python3 main.py. Then I lose the ability to test and iterate quickly because I need to maintain two separate systems for every parameter in 3-4 places.

main.py Before Extracting Hard-Coded Variables:

HOST = "http://host" 
PORT = 1234
if __name__ == '__main__':
    connect_to_server(HOST, PORT)

Newly created values.yaml

host: "http://host"
port: "1234"

Newly Template (e.g., bottom of containers in cronjob.yaml):

Using string for environment variable integer as per Helm docs.

env:
  - name: HOST
    value: {{ required "host is required!" .Values.host | quote }}
  - name: PORT
    value: {{ required "port is required!" .Values.port | quote }}

main.py After Extracting Hard-Coded Variables::

if __name__ == '__main__':
    try:
        HOST = os.environ['HOST']
        PORT = int(os.environ['PORT'])
        connect_to_server(HOST, PORT)
    except IndexError as e:
        print("Unable to run app! No env vars defined outside Helm!")
        raise e

If I leave this setup above as is it will not run when I execute python main.py. If I want to get this to run using plain old python3 main.py then I need to set up an entirely separate and parallel system to manage my environment variables locally. This is less than ideal and feels like an uber-pain to manage. I want to be able to continue to test things quickly locally without adding a bunch of try/catch exceptions for environment variables throughout the application. I know I can import env vars all sorts of ways, but I don't want to maintain two different systems with the same info. How can I add env vars in Helm Charts while still being nimble in my Python application locally? Is there a way to import my local values.yaml and set them as environment variables with the same name as in cronjob.yaml (i.e., HOST)? Or is there another solution I am not aware of for this use-case?

-- Scott Skiles
environment-variables
kubernetes
kubernetes-helm
python

1 Answer

12/17/2019

One option you could take is to continue to allow the environment variables, but provide a default in the case that the environment variable is not set. You can do this easily with the get() method:

if __name__ == '__main__':
    HOST = os.environ.get('HOST', 'http://host')
    PORT = int(os.environ.get('PORT', '1234'))
    connect_to_server(HOST, PORT)
-- jordanm
Source: StackOverflow