Most content in this document comes from "Learn Kubernetes in a Month of Lunches".
1. Environment variables, ConfigMaps, and Secrets
Environment variables are variables applied to your program/application dynamically during runtime, based on which the way your program/application acts is different. Examples of environment variables are a password of the database running for your app, paths for packages/libraries that your code depends on, and go build variables (GOARCH, GOOS) to create a binary file that conforms to your system.
ConfigMaps and Secrets are kubernetes resources to supply environment variables to the Pod your application is running on. They are just storage units intended for small amounts of data. Those storage units can be loaded into a Pod, becoming part of the container environment, so that application in the container can read the data.
2. Four ways to add environment variables in the Pod
Directly specify environment variables in the Pod spec
Create a ConfigMap from literal values and load it into the Pod
Create a ConfigMap populated from the environment file and load it into the Pod
Create a ConfigMap containing key-value pairs and load it into the Pod
2.1. Directly specify environment variables in the Pod spec
In the below example, KIAMOL_CHAPTER is specified at spec.template.spec.containers.env of the Deployment yaml spec.
It is the most straight-forward way to supply environment variables to the Pod. A downside of it is that if you need to make configuration changes you need to perform an update with a replacement Pod, which will results in frequent Pod replacements.
2.2. Create ConfigMaps from literal values and load it into the Pod
Real application usually have more complex configuration requirements, which is when you use ConfigMaps. As mentioned above, ConfigMaps are just a storage unit that has data in the form of key-value pairs. To load a ConfigMap into a Pod, the ConfigMap needs to exist before you deploy the Pod. Below is the kubectl command to create a ConfigMap.
Then deploy the updated app to use the ConfigMap.
After deploying the above yaml spec, check the KIAMOL_SECTION environment variable.
2.3. Create a new ConfigMap populated from the environment file and load it into the Pod
To supply a lot of configuration data in one scoop, create an environment file that can be loaded to create a ConfigMap is a good option to consider. For example, save a file ch04.env with the following content.
# Environment files use a new line for each variable.
KIAMOL_CHAPTER=ch04
KIAMOL_SECTION=ch04-4.1
KIAMOL_EXERCISE=try it now
Then create a ConfigMap with this env file.
Next, update the Pod to use the new ConfigMap.
After deploying a new Deployment yaml spec, print out the environment variables. You will meet the interesting facts.
When the same environment variable is supplied by multiple sources(one by ConfigMap defined under env and the other under envFrom in this example), the environment variables defined with env in the Pod spec override the values defined with envFrom.
2.3. Create a ConfigMap containing key-value pairs and load it into the Pod
This will be the most common way to use a ConfigMap. Key-value pairs for environment variables will be specified in the data section inside of ConfigMap. Please refer to the below example.
The Pod bound with todo-web Deployment(see the spec below) will load this ConfigMap and mount config.json file onto the path /app/config in the container. The ConfigMap is treated like a directory.
3. Hierarchy of configuration sources
Default settings are baked into the container image.
The actual settings for each environment are stored in a ConfigMap and surfaced into the container filesystem.
Any settings that need to be tweaked can be applied as environment variables in the Pod spec for the Deployment.
4. Two ways to configure sensitive data with Secrets
Reference a Secret object directly in the Pod
Load a sensitive data into a file and reference the file location in the Pod
4.1. Reference a Secret object directly in the Pod
Creating Secrets from a literal value is equivalent to base64 encoding, which isn’t really a security feature but just does prevent accidental exposure of secrets to someone looking over your shoulder.
The way to load Secrets to the Pod is almost the same with ConfigMaps, as you can see below.
Confirm that KIAMOL_SECRET is supplied to the Pod.
As you can observe in this case, the sensitive data provided by a literal Secret is easily exposed. Providing a sensitive data in a Secret yaml spec like below has the same issue.
4.2. Load a sensitive data into a file and reference the file location in the Pod
Look at the above Pod spec. The value for POSTGRES_PASSWORD_FILE is not a sensitive data itself but a path where the data is stored. When this Pod is deployed, Kubernetes loads the value of the Secret item into a file at the path /secrets/postgres_password. That file will be set with 0400 permissions, which means it can be read by the container user but not by any other users, which effectively minimizes the exposure of the sensitive data.