• Decoupled from Pod lifecycle: change config without redeploying
  • Volume mount: auto-refreshes (~60s); env: needs Pod restart to pick up changes
  • env: single key; envFrom: all keys from ConfigMap/Secret

ConfigMap: create

TaskCommand
From literal valueskubectl create configmap app-config --from-literal=DB_HOST=mysql --from-literal=DB_PORT=3306
From a filekubectl create configmap app-config --from-file=app.properties
From a directorykubectl create configmap app-config --from-file=./config-dir/
From env filekubectl create configmap app-config --from-env-file=.env
Viewkubectl get configmap app-config -o yaml

Mount ConfigMap: 3 ways

# Way 1: envFrom: all keys as env vars
spec:
  containers:
  - name: app
    envFrom:
    - configMapRef:
        name: app-config

# Way 2: env.valueFrom: single key
env:
- name: DATABASE_HOST
  valueFrom:
    configMapKeyRef:
      name: app-config
      key: DB_HOST

# Way 3: volume mount: keys become files
spec:
  volumes:
  - name: config-vol
    configMap:
      name: app-config
  containers:
  - name: app
    volumeMounts:
    - name: config-vol
      mountPath: /etc/config

# Way 3b: subPath: mount ONE key as a specific file
volumeMounts:
- name: config-vol
  mountPath: /etc/nginx/nginx.conf
  subPath: nginx.conf            # key name in ConfigMap
  readOnly: true

Optional references

env:
- name: FEATURE_FLAG
  valueFrom:
    configMapKeyRef:
      name: feature-flags
      key: enabled
      optional: true          # missing CM → env var omitted, Pod still starts

volumes:
- name: config-vol
  configMap:
    name: app-config
    optional: true            # missing CM → volume skipped
  • Without optional: true: missing ConfigMap → Pod stuck in CreateContainerConfigError

Secret: create

TaskCommand
Generic from literalkubectl create secret generic db-secret --from-literal=password=mysecret
Generic from filekubectl create secret generic tls-cert --from-file=tls.crt
TLS secretkubectl create secret tls my-tls --cert=tls.crt --key=tls.key
Docker registrykubectl create secret docker-registry regcred --docker-server=registry.io --docker-username=user --docker-password=pass
View (base64)kubectl get secret db-secret -o yaml
Decodekubectl get secret db-secret -o jsonpath='{.data.password}' | base64 -d

Secret types

Secret Typekubectl shorthand
Opaque (generic)--from-literal / --from-file
kubernetes.io/tlskubectl create secret tls
kubernetes.io/dockerconfigjsonkubectl create secret docker-registry
kubernetes.io/service-account-tokenAuto-created for ServiceAccounts

Mount Secret: same 3 ways as ConfigMap

envFrom:
- secretRef:
    name: db-secret

env:
- name: DB_PASSWORD
  valueFrom:
    secretKeyRef:
      name: db-secret
      key: password

volumes:
- name: secret-vol
  secret:
    secretName: db-secret
containers:
- volumeMounts:
  - name: secret-vol
    mountPath: /etc/secrets

# imagePullSecrets (pod-level, not container-level)
spec:
  imagePullSecrets:
  - name: regcred
data:
  pwd: czNjcmUh        # base64 in live object
stringData:
  pwd: s3cre!          # plain text in manifest: K8s encodes on create

imagePullSecrets on ServiceAccount (preferred for teams)

apiVersion: v1
kind: ServiceAccount
metadata:
  name: puller
  namespace: dev
imagePullSecrets:
- name: regcred
---
spec:
  serviceAccountName: puller  # inherits pull secret

Failures

SymptomCause
Env empty / app misconfigWrong key name
CreateContainerConfigError / crashConfigMap/Secret missing or not mounted
ImagePullBackOff on private imageMissing or wrong imagePullSecrets

Exam gotchas

  • immutable: true → ConfigMap cannot be changed; delete and recreate only
  • --from-env-file--from-file
  • imagePullSecrets is Pod-level: not container-level
  • Mount one key as a file: subPath: <key> + mountPath: /path/to/file
  • Missing ConfigMap blocks Pod start unless optional: true

Practice scenario: ConfigMaps and Secrets

Tasks

  • ConfigMap app-config: LOG_LEVEL=info, APP_PORT=8080
  • Secret db-secret: DB_PASSWORD=s3cr3t
  • Pod config-pod (nginx): inject ConfigMap as env vars, Secret as volume at /etc/db
Solution
kubectl create configmap app-config --from-literal=LOG_LEVEL=info --from-literal=APP_PORT=8080
kubectl create secret generic db-secret --from-literal=DB_PASSWORD=s3cr3t

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: config-pod
spec:
  volumes:
  - name: db-vol
    secret:
      secretName: db-secret
  containers:
  - name: app
    image: nginx
    envFrom:
    - configMapRef:
        name: app-config
    volumeMounts:
    - name: db-vol
      mountPath: /etc/db
      readOnly: true
EOF

kubectl exec config-pod -- env | grep -E 'LOG_LEVEL|APP_PORT'
kubectl exec config-pod -- ls /etc/db

Concepts: envFrom vs env.valueFrom; secretName (not name) in volume spec.