Docker and Kubernetes course menu
Kubernetes ConfigMaps, Secrets and Health Probes
Configure Kubernetes apps with ConfigMaps and Secrets, keep data with persistent volumes, and add liveness and readiness probes. Then see where Helm fits.
ConfigMaps#
A ConfigMap stores settings outside the image, so that the same image works in every environment:
kubectl create configmap app-config --from-literal=APP_ENV=staging --from-literal=LOG_LEVEL=debug
kubectl get configmap app-config -o jsonpath='{.data}{"\n"}'configmap/app-config created
{"APP_ENV":"staging","LOG_LEVEL":"debug"}Secrets#
A Secret is similar, but for sensitive values:
kubectl create secret generic db-secret --from-literal=password='s3cret'
kubectl get secret db-secret -o jsonpath='{.data.password}{"\n"}'
kubectl get secret db-secret -o jsonpath='{.data.password}' | base64 -d
echosecret/db-secret created
czNjcmV0
s3cretUse them in a pod#
cat > app.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
restartPolicy: Never
containers:
- name: app
image: alpine:3.24
command: ["sh", "-c", "echo $APP_ENV $LOG_LEVEL; echo password has ${#DB_PASSWORD} characters; cat /etc/app/LOG_LEVEL; echo"]
envFrom:
- configMapRef:
name: app-config
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
volumeMounts:
- name: config
mountPath: /etc/app
volumes:
- name: config
configMap:
name: app-config
EOF
kubectl apply -f app.yaml
kubectl wait --for=jsonpath='{.status.phase}'=Succeeded pod/app --timeout=60s > /dev/null
kubectl logs app
kubectl delete pod app --wait=false > /dev/nullpod/app created
staging debug
password has 6 characters
debugThe values can arrive as environment variables, or as files. Files update while a pod runs, and environment variables need a restart.
Probes#
Kubernetes checks your container with probes.
cat > probes.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: probed
spec:
replicas: 1
selector:
matchLabels:
app: probed
template:
metadata:
labels:
app: probed
spec:
containers:
- name: web
image: nginx:1.30-alpine
readinessProbe:
httpGet:
path: /
port: 80
periodSeconds: 2
livenessProbe:
httpGet:
path: /
port: 80
periodSeconds: 2
failureThreshold: 2
EOF
kubectl apply -f probes.yaml
kubectl rollout status deployment/probed --timeout=90s | tail -n 1
pod=$(kubectl get pods -l app=probed -o name)
kubectl get "$pod" -o jsonpath='restarts={.status.containerStatuses[0].restartCount}{"\n"}'deployment.apps/probed created
deployment "probed" successfully rolled out
restarts=0Now we break the app, by deleting its home page. The liveness probe fails, and Kubernetes restarts the container, which brings the file back from the image:
kubectl exec "$pod" -- rm /usr/share/nginx/html/index.html
sleep 15
kubectl get "$pod" -o jsonpath='restarts={.status.containerStatuses[0].restartCount}{"\n"}'
kubectl describe "$pod" | grep -m1 -o 'Container web failed liveness probe, will be restarted'
kubectl delete deployment probed > /dev/nullrestarts=1
Container web failed liveness probe, will be restartedStoring data#
Pods are disposable, so data needs a PersistentVolumeClaim (PVC), a request for storage:
cat > pvc.yaml <<'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 100Mi
---
apiVersion: v1
kind: Pod
metadata:
name: writer
spec:
containers:
- name: c
image: alpine:3.24
command: ["sh", "-c", "echo saved > /data/file; sleep 60"]
volumeMounts:
- name: store
mountPath: /data
volumes:
- name: store
persistentVolumeClaim:
claimName: data
EOF
kubectl apply -f pvc.yaml
kubectl wait --for=condition=Ready pod/writer --timeout=60s > /dev/null
kubectl exec writer -- cat /data/file
kubectl get pvc data --no-headers | awk '{print $1, $2}'
kubectl delete -f pvc.yaml --wait=false > /dev/null
kubectl delete configmap app-config > /dev/null
kubectl delete secret db-secret > /dev/nullpersistentvolumeclaim/data created
pod/writer created
saved
data BoundFor databases, a StatefulSet gives each pod a stable name and its own storage. Many teams use a managed database service instead.
Helm#
Real apps need many YAML files. Helm is a package manager for Kubernetes. A chart bundles those files with settings:
helm repo add bitnami https://charts.bitnami.com/bitnami
helm install my-db bitnami/postgresql --set auth.database=shop
helm upgrade my-db bitnami/postgresql
helm uninstall my-dbKustomize, built into kubectl, is another way to manage environments.
Where to go next#
- Run a cluster on a cloud provider: EKS, GKE or AKS.
- Learn RBAC, to control who can do what.
- Look at GitOps tools such as Argo CD, which deploy from Git.
- Consider the CKA or CKAD certifications.
Key takeaway#
Finished this lesson?
Related lessons
Recommended Docker and Kubernetes resources
- Docker Deep Dive by Nigel Poulton
A practical guide to how Docker works, for readers who have finished the basics.
Some links are affiliate links. If you buy through them, Laviyx Learn may earn a commission at no extra cost to you. As an Amazon Associate, we earn from qualifying purchases.