Lab 05: ConfigMaps & Secrets

Objectives

  • ✅ Create ConfigMaps from files and literals
  • ✅ Create Secrets for sensitive data
  • ✅ Mount ConfigMaps as environment variables
  • ✅ Mount Secrets as volumes
  • ✅ Update configurations without redeploying

Prerequisites

  • Lab 04 complete
  • ~1 hour

Step 1: Create ConfigMap

# Create from literals
kubectl create configmap app-config \
  --from-literal=LOG_LEVEL=INFO \
  --from-literal=ENVIRONMENT=development \
  --from-literal=DATABASE_HOST=postgres.default.svc.cluster.local

# Verify
kubectl get configmap app-config
kubectl describe configmap app-config

Step 2: Create Secret

# Create from literals
kubectl create secret generic app-secret \
  --from-literal=DB_PASSWORD=secretpassword123 \
  --from-literal=API_KEY=mysecretkey789

# Verify
kubectl get secret app-secret
kubectl describe secret app-secret

# Note: Secrets are base64 encoded, NOT encrypted by default
# In production, use Sealed Secrets or Vault

Step 3: Use ConfigMap as Environment Variables

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-with-config
spec:
  replicas: 2
  selector:
    matchLabels:
      app: api-config
  template:
    metadata:
      labels:
        app: api-config
    spec:
      containers:
      - name: api
        image: YOUR_USERNAME/myapp:1.0.0
        ports:
        - containerPort: 5000
        env:
        # From ConfigMap
        - name: LOG_LEVEL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: LOG_LEVEL
        - name: ENVIRONMENT
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: ENVIRONMENT
        - name: DATABASE_HOST
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: DATABASE_HOST
        # From Secret
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secret
              key: DB_PASSWORD

Deploy and verify:

kubectl apply -f api-with-config.yaml

# Check env variables in pod
kubectl exec <pod-name> -- env | grep LOG_LEVEL
# Should output: LOG_LEVEL=INFO

Step 4: Mount ConfigMap as Volume

Create app.conf:

server:
  port: 5000
  debug: false

database:
  host: postgres
  port: 5432

Create ConfigMap from file:

kubectl create configmap app-config-file --from-file=app.conf

# Verify
kubectl get configmap app-config-file
kubectl describe configmap app-config-file

Use in Pod:

apiVersion: v1
kind: Pod
metadata:
  name: api-with-volume
spec:
  containers:
  - name: api
    image: YOUR_USERNAME/myapp:1.0.0
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
  volumes:
  - name: config-volume
    configMap:
      name: app-config-file

Deploy and verify:

kubectl apply -f api-with-volume.yaml

# Check mounted file
kubectl exec api-with-volume -- cat /etc/config/app.conf
# Should show file contents

Step 5: Update ConfigMap (Without Redeeploy)

# Edit ConfigMap
kubectl edit configmap app-config
# Change LOG_LEVEL from INFO to DEBUG

# Verify change
kubectl describe configmap app-config | grep LOG_LEVEL

# Pod will NOT auto-update environment variables
# (Only mounts as volume are auto-updated)

# To force pod restart:
kubectl rollout restart deployment/api-with-config

# Now new pods get new env vars
kubectl exec <new-pod-name> -- env | grep LOG_LEVEL
# Should show: LOG_LEVEL=DEBUG

Validation

# ConfigMaps exist
kubectl get configmaps

# Secrets exist
kubectl get secrets

# Pods receive configuration
kubectl exec $(kubectl get pod -l app=api-config -o jsonpath='{.items[0].metadata.name}') -- env | grep LOG_LEVEL
# Returns: LOG_LEVEL=INFO

# Volumes are mounted
kubectl exec api-with-volume -- ls /etc/config
# Returns: app.conf

Challenge (Optional)

Create Kustomization to manage multiple environments:

# Create patches for prod
mkdir -p kustomize/prod
cat > kustomize/prod/kustomization.yaml <<EOF
bases:
  - ../base

configMapGenerator:
- name: app-config
  literals:
  - LOG_LEVEL=ERROR
  - ENVIRONMENT=production
EOF

# Apply
kubectl apply -k kustomize/prod/

Cleanup

kubectl delete deployment api-with-config api-with-volume
kubectl delete configmap app-config app-config-file
kubectl delete secret app-secret

Next: Lab 06: Helm Charts