ConfigMaps and Secrets
Keep settings in ConfigMaps and passwords in Secrets, pass them to a container as environment variables or files, and know when a change reaches a running Pod.
Key ideas in this lesson · tap one for a simple explanation
What you will be able to do
- Create a ConfigMap or a Secret from literals, a file or an env file in one command, and decode any Secret value.
- Pass one key with env.valueFrom, every key with envFrom, and files with a configMap or secret volume, including items and subPath.
- Say which of these ways picks up a change, and what immutable: true does.
Your app needs settings: a mode, a color, a database password. You should not build them into the image, because then every change needs a new image. Kubernetes keeps them in two objects instead:
- A holds plain settings, such as
APP_MODE=production. - A holds sensitive values, such as the password of your Django app's database.
Both are a list of keys with values. A gets them in one of two ways: as environment variables, or as files in a folder.
ConfigMap or Secret
keys and values
Two ways in
Environment variable
read once, at start
Mounted file
one file per key
Container
your app reads them
Exam tasks here are short and very literal: a named object with named keys, used in a set way by a set container. The grader reads the object, then the spec. It often runs env or cat inside the container too. Every detail in the task can be checked, so read it twice.
Create them with one command
Each source has its own flag, and the same flags work for ConfigMaps and Secrets.
# ConfigMaps
kubectl -n wl-config create configmap app-config --from-literal=APP_MODE=production --from-literal=APP_COLOR=blue
kubectl -n wl-config create configmap nginx-conf --from-file=default.conf=./site.conf # key=path sets the key name
kubectl -n wl-config create configmap app-env --from-env-file=./app.env # one key per KEY=VALUE line
kubectl -n wl-config create configmap scripts --from-file=./scripts/ # one key per file in the directory
# Secrets: same flags, plus a type
kubectl -n wl-config create secret generic db --from-literal=username=app --from-literal=password='s3cr3t!'
# Look before you mount
kubectl -n wl-config describe configmap app-config
kubectl -n wl-config get secret db -o yamlMixing up the last two is the most common reason a file or a variable comes out wrong. Take a Django app's .env file. --from-env-file=.env gives you DEBUG, SECRET_KEY and so on as separate keys. --from-file=.env gives you one key, .env, holding the whole file.
Secrets also have a type. For your own apps it is Opaque, which kubectl create secret generic makes. Other types each have one set job, and each is taught where it is used. TLS certificates are in Ingress, registry logins in Application failures, and tokens in RBAC.
base64 is an encoding, not protection
Secret values are stored in base64. That is an encoding, not encryption: anyone can turn it back into the original text with one command.
kubectl -n wl-config get secret db -o jsonpath='{.data.password}' | base64 -d; echo
echo -n 's3cr3t!' | base64 # -n matters: without it the trailing newline is encoded too
kubectl -n wl-config create secret generic db2 --from-literal=password='s3cr3t!' --dry-run=client -o yaml- In a Secret's ,
datatakes base64 values. stringDatatakes plain text. The encodes it when it saves the Secret, and never showsstringDataback to you.
Secrets are not encrypted by default. Anyone allowed to create Pods in a can read every Secret there, just by mounting it. So the real protection is : who may read Secrets, and who may create Pods.
As environment variables
There are two ways to turn keys into environment variables:
envwithvalueFrom: one key, and you choose the variable's name.envFrom: every key in the object, each as a variable with the key's name.
apiVersion: v1
kind: Pod
metadata:
name: env-demo
namespace: wl-config
spec:
containers:
- name: app
image: busybox:1.36
command: ["sleep", "3600"]
env:
- name: MODE # one key, under a new name
valueFrom:
configMapKeyRef:
name: app-config
key: APP_MODE
- name: DB_PASS
valueFrom:
secretKeyRef:
name: db
key: password
envFrom: # every key becomes a variable
- configMapRef:
name: app-config
- prefix: DB_ # username becomes DB_username
secretRef:
name: db- If the ConfigMap, the Secret or the key does not exist, the container does not start. The Pod shows
CreateContainerConfigError, andkubectl describe podnames the missing piece. - Add
optional: trueto a reference only when the task allows the value to be missing. - If
envandenvFromset the same name, the one underenvwins.
As files
A ConfigMap or Secret can also be a volume. Each key becomes a file, and the value becomes the file's contents. For example, a ConfigMap key default.conf becomes a file default.conf that nginx reads as its config.
spec:
containers:
- name: nginx
image: nginx:1.27
volumeMounts:
- name: conf # one file dropped into an existing directory
mountPath: /etc/nginx/conf.d/default.conf
subPath: default.conf
- name: creds # the whole Secret as a directory of files
mountPath: /etc/creds
readOnly: true
volumes:
- name: conf
configMap:
name: nginx-conf # configMap uses "name" ...
items: # only these keys, under these file names
- key: default.conf
path: default.conf
- name: creds
secret:
secretName: db # ... secret uses "secretName"
defaultMode: 0400 # octal in YAML; the API stores it as 256Watch out: a volume mounted on a folder hides whatever the image had in that folder. That is fine for an empty folder such as /etc/creds. On /etc/nginx it breaks nginx, because its main config file disappears. To add one file to a folder that already has content, use subPath. It has a cost, shown in the next table.
Which changes reach a running Pod
You edit a ConfigMap. Does the running app see the change? It depends on how the container gets it:
immutable: true on a ConfigMap or Secret is a one-way door. You cannot unset it; you can only delete the object. In return, the stops watching the object, which takes load off the API server in big clusters. And no one can change the config under a running app by accident.
In the official docs· open on exam day too
- Configure a Pod to Use a ConfigMapsearch: configure pod configmap
- Distribute Credentials Securely Using Secretssearch: distribute credentials secrets
- Secretssearch: secret types
- ConfigMapssearch: configmap
Configure a Deployment from a ConfigMap and a Secret
wl-config: create a ConfigMap app-config with the keys APP_MODE=production and APP_COLOR=blue, and a Secret app-secret of type Opaque with the key DB_PASSWORD=s3cr3t-pass. Then create a Deployment app with 2 replicas, image busybox:1.36, container name app, running sleep 3600. The container must get an environment variable MODE from the key APP_MODE of app-config, every key of app-secret as an environment variable, and every key of app-config as a file under /etc/app.Cluster:kubectl config use-context kind-cka
- 1
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/wl-config-1/setup | bash - 2
Solve it in your terminal
Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under
/tmp/cka/. - 3
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/wl-config-1/verify | bashGot FAIL? Read which check failed, fix it, run it again. - 4
Clean up (optional)
curl -fsSL https://codewithmuh.com/labs/cka/t/wl-config-1/cleanup | bash
Replace a config file and mount a Secret with strict permissions
/tmp/cka/wl-config/default.conf. In namespace wl-config, create a ConfigMap proxy-conf from that file with the key default.conf, and a Secret proxy-token with the key token set to abc123. Then create a Pod proxy (image nginx:1.27) in which the ConfigMap's file replaces /etc/nginx/conf.d/default.conf, so that http://localhost:8080/healthz inside the Pod returns healthy, and the Secret is available as the file /etc/proxy/token with permissions 0400.Cluster:kubectl config use-context kind-cka
- 1
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/wl-config-2/setup | bash - 2
Solve it in your terminal
Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under
/tmp/cka/. - 3
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/wl-config-2/verify | bashGot FAIL? Read which check failed, fix it, run it again. - 4
Clean up (optional)
curl -fsSL https://codewithmuh.com/labs/cka/t/wl-config-2/cleanup | bash
Finished this lesson?
0 of 2 tasks passed. Your readiness counts tasks, so run them before you move on.