Providing configuration to applications via environment variables (env vars) is one of the principles of twelve-factor apps. If that configuration contains sensitive information like credentials, the best way to do that is using Secrets in Kubernetes. There are a lot of different ways to manage env vars and Secrets in Kubernetes. Here are a few things I do to make working with them more convenient.
The versions used in this post at the time of writing are:
- Minikube: 0.21.0
- VirtualBox: 5.1.22
- Kubernetes and kubectl: 1.7.0
Create a minikube and get the code
Setup the configuration
You need to get env vars into apps running on Kubernetes but, at least in your development environment, it can also be really convenient to have those env vars in your terminal session. For that reason, you can store your env vars as simple scripts that can be sourced.
Knowing that you’ll have multiple environments, it’s good to start with a template for that script. To avoid conflicts, prefix all of your env vars with some shorthand for your app.
Create a directory called envs for all of your config. Include a .gitignore to avoid committing any sensitive info and a README.md to let people (and your-later-self) know how to use the template.
envs/
├── .gitignore
├── README.md
├── dev.sh
├── staging.sh
├── template.sh
└── test.sh
Ignore everything except the few initial files in the dir.
Naturally you’d want to expand on these instructions in the README.md.
Setup a development environment
Create the Secrets and a Deployment
You can provide the config as key/value pairs using process substitution.
PS1 Context
If you’re working with many different app envs, it can be helpful to include some context in your PS1. Here’s one example of including a bit more context on your command line. For a more thorough PS1, checkout my .bash_profile.
PS1='(kubernetes:$(kubectl config current-context 2>&1) | foo:$(echo ${FOO_ENV}))\n\W $ '
Coda
Obviously this can be used in many more places than just database configuration. It’s a great way to configure your apps too. These environment variables can even be used in injected executable scripts, which makes for a pretty powerful way to configure containers on the fly.
One improvement I’d like to make to this setup is to always have the env var file encrypted on disk. Whenever you needed the env vars in a terminal session, you would decrypt the file and source it. All in-memory so the decrypted version is never stored on disk.