Lab 17 - ConfigMaps and Secrets
Lab 17 - ConfigMaps and Secrets
Goal: same image, different configuration - and learn which changes need a restart. Chapter: ConfigMaps and Secrets
# 1 - from literals and from a file
cd ~
printf 'color=blue\nretries=3\n' > app.properties
kubectl create cm app-cfg \
--from-literal=DATACENTER=dc01 \
--from-file=app.properties
kubectl get cm app-cfg -o yaml
--from-literal makes one key; --from-file makes a key named after the file
whose value is the whole file. Both live in the same data map.
# 2 - consume it both ways at once
cat > cfgpod.yaml <<'YAML'
apiVersion: v1
kind: Pod
metadata:
name: cfgpod
spec:
containers:
- name: box
image: busybox
command: ["sh", "-c", "env | sort; sleep 3600"]
env:
- name: DATACENTER
valueFrom:
configMapKeyRef:
name: app-cfg
key: DATACENTER
volumeMounts:
- name: cfg
mountPath: /etc/appcfg
volumes:
- name: cfg
configMap:
name: app-cfg
YAML
kubectl apply -f cfgpod.yaml
kubectl logs cfgpod | grep DATACENTER
kubectl exec cfgpod -- ls /etc/appcfg
kubectl exec cfgpod -- cat /etc/appcfg/app.properties
Every key became a file in /etc/appcfg, and one key also became an environment
variable.
# 3 - change the ConfigMap and wait
printf 'color=green\nretries=5\n' > app.properties
kubectl create cm app-cfg --from-literal=DATACENTER=dc02 \
--from-file=app.properties --dry-run=client -o yaml | kubectl apply -f -
sleep 70
kubectl exec cfgpod -- cat /etc/appcfg/app.properties # green - updated
kubectl exec cfgpod -- printenv DATACENTER # dc01 - NOT updated
This is the single most useful fact in the chapter. Mounted files are refreshed by the kubelet; environment variables are frozen at container start. An application that reads config from env vars needs a restart to see a change.
The kubectl create ... --dry-run=client -o yaml | kubectl apply -f - pattern is
how you update an object that has no kubectl set command.
Secrets
# 4 -
kubectl create secret generic db-cred \
--from-literal=username=app \
--from-literal=password=S3cret
kubectl get secret db-cred -o yaml
kubectl get secret db-cred -o jsonpath='{.data.password}' | base64 -d; echo
Base64 is encoding, not encryption. Anyone who can read Secrets in this namespace can read the password - protection comes from RBAC and encryption at rest.
# 5 - inject the whole Secret as environment variables
cat > secpod.yaml <<'YAML'
apiVersion: v1
kind: Pod
metadata:
name: secpod
spec:
containers:
- name: box
image: busybox
command: ["sh", "-c", "sleep 3600"]
envFrom:
- secretRef:
name: db-cred
YAML
kubectl apply -f secpod.yaml
kubectl exec secpod -- sh -c 'echo $username / $password'
envFrom takes every key at once; the key names become the variable names.
# 6 - the restart that picks up a change
kubectl create deploy web --image nginx:1.27
kubectl set env deploy/web --from=configmap/app-cfg
kubectl rollout status deploy/web
kubectl exec deploy/web -- printenv DATACENTER # dc02
kubectl create cm app-cfg --from-literal=DATACENTER=dc03 \
--from-file=app.properties --dry-run=client -o yaml | kubectl apply -f -
kubectl exec deploy/web -- printenv DATACENTER # still dc02
kubectl rollout restart deploy/web
kubectl rollout status deploy/web
kubectl exec deploy/web -- printenv DATACENTER # dc03
kubectl rollout restart after a config change is a habit worth forming.
Clean up
kubectl delete -f cfgpod.yaml -f secpod.yaml
kubectl delete deploy web
kubectl delete cm app-cfg
kubectl delete secret db-cred