It's about damn time, Google! I've been working on a number of GCP projects this year and have consistently bumped up against the awkwardness that was Google's (former?) preference for configuration files over environment variables.
It's about damn time, Google! I've been working on a number of GCP projects this year and have consistently bumped up against the awkwardness that was Google's (former?) preference for configuration files over environment variables.
How can you 'store' anything in something as ephemeral as environment variables? Where do these environment variables come from? When are they set?
You should of course store everything in version control; the point of this guideline is that the scope should not be the same as the app or an instance.
There is particular tension between this guideline and X. environments should be a similar as possible and I. there should be a single codebase for all deployments.
This doesn't work for everyones infrastructure setups, but it's worked well for mine.
That works fine if there's a limited number of environments, but it becomes a pain if you're running the same app in too many, or if someone else needs to deploy it independently of the developers.
No it doesn't. It's trivial to generate the full set of configs using a script, if you have too many to manage manually.
or if someone else needs to deploy it independently of the developers
And how exactly do envvars help with that? The set of envvars still needs to get pushed with each deployment. envvars are just a special config file.
> requires strict separation of config from code. Config varies substantially across deploys, code does not.
What's the difference between config and code? Config is that which changes between deployments / environments.
Basically, you'd have a git repo for code, and a separate git repo for environment scripts. I've seen organizations use a whole separate infrastructure for config, but that always seemed like overkill to me.
It's definitely more convenient to use the same repo, especially in the declarative containerized world; you can make sweeping changes or roll them back in a single atomic commit.
That said, if open source is the intent, certainly use multiple repos from the beginning so you avoid git gardening when releasing later.
Set at build time. They come from a build config file/script as part of the build. They're not perfect, but just about every tool ever made has a way of understanding environment variables - the same can't be said for any given config file.
Here's a real world example: I want one source of truth for my build configuration, but my build itself pulls together libraries and binaries in a number of different languages and build systems. How would you handle that with anything but environment variables and a master shell script?
But the script is in VC surely?
> How would you handle that with anything but environment variables and a master shell script?
Again, where is that master shell script? What args do you give it?
My preference is that you have one environment variable, and your config is keyed off that.
If that environment variable is not supplied, fail noisily.
You can take it one step further and define a single ConfigMap resource per environment, containing all of the required variables across your application, and then have all the various containers reference it ‘blindly’ when they are deployed. Said configuration resource would exist in version control but deploy independently from the functional codebase(s).
The idea is that the application environment / infrastructure should own the config data, not the application code itself. 12 factor practices require that devs draw a boundary between app and infrastructure.
Given a config file per 'environment', with environment being an arbitrary identifier, what benefit do environment variables have over it? I've read some docs on 12 factor apps looking for an answer but didn't really find anything. Just curious what I'm overlooking
1. Bash, Python, C, Java...super easy to access; no libraries needed.
2. They automatically propagate through shell scripts and worker processes.
3. They are also super easy to specify when starting programs, in shell, docker, child process from programming languages, Lambda functions, etc.
4. They can easily exist independently of other env variables on the same system.
5. The model is dead simple. Key-value. Simplicity is a feature.
If you need to specify something complex (e.g. hundreds of tuned timeouts), consider using files or code for the heavy parts and env vars to select parts.
For #4, what do you mean? If running in a container it's not really an issue, but if I'm loading a couple of different dependencies/apps in the same container, or running without containers, name collisions have always been a concern. Set up a chroot, or start renaming things (i.e., "PORT" conflicts really quickly). Or are you saying supply them in the shell, or...?
I mean that one process can have COLOR=blue and another can have COLOR=red with no conflict.
PORT=123 COLOR=blue ./myapp
PORT=456 COLOR=red ./myapp
Yes you can chroot, run in containers, use only relative file paths, etc.There aren't any irremovable differences between env vars and files; env vars are basically /proc/ files with widespread runtime support.
Sometimes that location is communicated through an env var, and that point why not just set all config that way?
Environment variables had the early upside of being first class in any virtually any deployment strategy - from Bash wrappers, supervisord to Docker and Kubernetes - so it's pretty much plug and play. For example, Docker has config files, but they're mounted to a specific place in your container, so that means your application is now married to that location.