Lab Guide: Secrets & ConfigMaps
Three hands-on exercises to practise templating ConfigMaps, Secrets, and the checksum rollout trick.
Prerequisites
A running Kubernetes cluster (minikube, kind, or k3d), Helm 3.12+, and kubectl configured to talk to the cluster.
Exercise 1 — ConfigMap from Values and Files
Create a chart that templates a ConfigMap with entries from values.yaml and loads an external configuration file using .Files.Get.
Step 1
Scaffold a new chart and clean up the default templates:
helm create configdemo
cd configdemo
rm templates/tests -rf
rm templates/hpa.yaml templates/ingress.yaml templates/serviceaccount.yaml
Step 2
Create a files/ directory and add a sample config file:
mkdir files
cat > files/app.conf <<'EOF'
[server]
port = 8080
workers = 4
[logging]
level = info
format = json
EOF
Step 3
Add configuration values to values.yaml:
# values.yaml (add to the bottom)
config:
env: production
logLevel: info
maxConnections: "100"
Step 4
Create the ConfigMap template at templates/configmap.yaml:
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "configdemo.fullname" . }}-config
labels:
{{- include "configdemo.labels" . | nindent 4 }}
data:
APP_ENV: {{ .Values.config.env | quote }}
LOG_LEVEL: {{ .Values.config.logLevel | quote }}
MAX_CONNECTIONS: {{ .Values.config.maxConnections | quote }}
app.conf: |-
{{ .Files.Get "files/app.conf" | indent 4 }}
Step 5
Render the template locally and verify the output:
helm template configdemo . | grep -A 20 "kind: ConfigMap"
You should see all four data keys rendered correctly, with the file content indented under app.conf.
Step 6
Install the chart and verify the ConfigMap exists in the cluster:
helm install configdemo .
kubectl get configmap configdemo-config -o yaml
Checkpoint
The ConfigMap should contain four keys: APP_ENV, LOG_LEVEL, MAX_CONNECTIONS, and app.conf. The app.conf key should contain the full INI file content.
Exercise 2 — Secrets with b64enc and stringData
Add a Secret to the chart using both data (with b64enc) and stringData fields, then mount it as environment variables in the Deployment.
Step 1
Add secret values to values.yaml:
# values.yaml (add to the bottom)
secrets:
dbPassword: "s3cret-p@ssw0rd"
apiKey: "ak_live_abc123def456"
Step 2
Create templates/secret.yaml:
apiVersion: v1
kind: Secret
metadata:
name: {{ include "configdemo.fullname" . }}-secret
labels:
{{- include "configdemo.labels" . | nindent 4 }}
type: Opaque
data:
DB_PASSWORD: {{ .Values.secrets.dbPassword | b64enc | quote }}
stringData:
API_KEY: {{ .Values.secrets.apiKey | quote }}
Step 3
Update templates/deployment.yaml to inject the secrets as environment variables. Add the following to the container spec (inside containers[0]):
envFrom:
- secretRef:
name: {{ include "configdemo.fullname" . }}-secret
- configMapRef:
name: {{ include "configdemo.fullname" . }}-config
Step 4
Upgrade the release and verify the secret:
helm upgrade configdemo .
kubectl get secret configdemo-secret -o jsonpath='{.data.DB_PASSWORD}' | base64 -d
# Should output: s3cret-p@ssw0rd
kubectl get secret configdemo-secret -o jsonpath='{.data.API_KEY}' | base64 -d
# Should output: ak_live_abc123def456
Step 5
Confirm the pod has the environment variables:
POD=$(kubectl get pod -l app.kubernetes.io/name=configdemo -o jsonpath='{.items[0].metadata.name}')
kubectl exec $POD -- env | grep -E "DB_PASSWORD|API_KEY|APP_ENV"
Checkpoint
The pod should show DB_PASSWORD, API_KEY, and APP_ENV in its environment. Both secret values should decode correctly.
Exercise 3 — Checksum Annotation for Auto-Rollout
Add checksum annotations to the Deployment so that changes to the ConfigMap or Secret trigger a rolling update automatically.
Step 1
Edit templates/deployment.yaml. In the pod template metadata.annotations section, add:
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
Step 2
Upgrade without changing any values and note the current pod name:
helm upgrade configdemo .
kubectl get pods -l app.kubernetes.io/name=configdemo
# Note the pod name and AGE
Step 3
Now change a config value and upgrade again:
helm upgrade configdemo . --set config.logLevel=debug
Step 4
Verify that a new pod was created (rolling update triggered):
kubectl get pods -l app.kubernetes.io/name=configdemo
# The pod name should be different and AGE should be very recent
Step 5
Inspect the annotation to confirm the checksum changed:
kubectl get deployment configdemo -o jsonpath='{.spec.template.metadata.annotations}' | python3 -m json.tool
Checkpoint
Changing config.logLevel should result in a new pod. The checksum/config annotation value should differ between the two upgrades.
Cleanup
helm uninstall configdemo
cd .. && rm -rf configdemo
What you practised
Creating ConfigMaps from values and files, templating Secrets with b64enc and stringData, mounting both as environment variables, and using checksum annotations for automatic rollouts on config changes.