Introduction
In software, hard-coding settings such as database URLs or passwords into application code is a bad practice. It makes changes harder and increases security risk.
Kubernetes addresses this with two objects:
- ConfigMap: Think of this as a Public Notice Board. You pin information here (like "The background color is blue" or "The database address is 10.0.0.1"). Anyone in the office (Pods) can read it.
- Secret: Used for sensitive values such as passwords or tokens.
This separation between application code and runtime configuration is a major platform design principle, not just a Kubernetes feature.
In this lab, you will:
- Write a note on the Notice Board (ConfigMap).
- Put a password in the Safe (Secret).
- Teach a Pod how to read both.
Create a ConfigMap
Let's create a configuration file for a web server. Instead of baking it into the image, we will store it in a ConfigMap.
This pattern is part of a bigger container design principle: build one reusable image, then supply environment-specific configuration at runtime. That keeps the image more portable because development, staging, and production can use the same container but different settings.
First, create a simple Nginx configuration file named nginx.conf:
echo 'events {} http { server { listen 80; location / { return 200 "Hello from ConfigMap!"; } } }' > nginx.conf
Now, create a ConfigMap named nginx-config from this file. This effectively "pins" the file to the Kubernetes cluster's notice board.
kubectl create configmap nginx-config --from-file=nginx.conf
Verify it exists:
kubectl describe configmap nginx-config
You should see the content of your nginx.conf listed under the "Data" section.
Create a Secret
Now, let's store something sensitive. A Secret works similarly to a ConfigMap, but Kubernetes treats it with extra care (it obfuscates the data in storage).
It is important to be precise here: a Secret is safer than hard-coding passwords into manifests or images, but base64 encoding is not real encryption. In production, Secret handling is often combined with encryption at rest, tighter RBAC, and external secret-management systems.
Create a Secret named app-secret to store a dummy password:
kubectl create secret generic app-secret --from-literal=password=SuperSecretPass123
Verify it exists:
kubectl get secret app-secret
If you look at the details, you won't see the password directly. It will be hidden (encoded).
kubectl get secret app-secret -o yaml
Notice the password field is a scramble of characters. This is base64 encoding, designed to prevent "shoulder surfing" or accidental display in logs.
Mount ConfigMap as File
Now, let's teach a Pod how to read the Notice Board.
The most common way to use a ConfigMap is to Mount it as a file. It appears inside the container just like a regular file on disk.
This file-based approach is useful when an application already expects a configuration file at a certain path. Kubernetes projects the ConfigMap data into the container filesystem so the application can keep using its normal file-reading behavior.
Create a file named pod-config.yaml:
nano pod-config.yaml
Paste the following. This Pod mounts the nginx-config map into /etc/nginx/nginx.conf.
apiVersion: v1
kind: Pod
metadata:
name: config-pod
spec:
containers:
- name: nginx
image: nginx:alpine
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
volumes:
- name: config-volume
configMap:
name: nginx-config
Save and exit (Ctrl+X, Y, Enter).
Apply it:
kubectl apply -f pod-config.yaml
Wait a few seconds for it to start. Now, let's peek inside the container to see if the file is there:
kubectl exec config-pod -- cat /etc/nginx/nginx.conf
You should see your custom configuration! The Pod essentially "read the notice board" and used that file.
Inject Secret as Env Var
Now for the Secret. A common way to pass passwords is via Environment Variables.
This method is convenient, but it also teaches a tradeoff. Environment variables are easy for applications to read, yet they can be exposed by diagnostic commands or process inspection. Kubernetes supports both file-based and environment-variable injection because different applications and risk profiles need different approaches.
Create a file named pod-secret.yaml:
nano pod-secret.yaml
Paste the following. This Pod grabs the password from the app-secret and assigns it to an environment variable called APP_PASSWORD.
apiVersion: v1
kind: Pod
metadata:
name: secret-pod
spec:
containers:
- name: busybox
image: busybox
command: ["sleep", "3600"]
env:
- name: APP_PASSWORD
valueFrom:
secretKeyRef:
name: app-secret
key: password
Save and exit (Ctrl+X, Y, Enter).
Apply it:
kubectl apply -f pod-secret.yaml
Once running, let's check the environment variables inside the container:
kubectl exec secret-pod -- env | grep APP_PASSWORD
You should see APP_PASSWORD=SuperSecretPass123.
The magic here is that the Pod definition doesn't contain the password. The password lives in the "Safe" (Secret), and the Pod just has a key to open it at runtime.
Summary
In this lab, you practiced separating code from configuration.
You successfully:
- Used a ConfigMap (Notice Board) to inject a config file into a server.
- Used a Secret (Safe) to inject a hidden password into an application.
By doing this, you can now update your configuration or rotate your passwords without ever having to rebuild your Docker images!


