Qingular

ConfigMap and Secret

·CKAk8s练习

Creating, injecting, and mounting ConfigMaps and Secrets

← Back to CKA Practice Index

Overview

ConfigMap and Secret are used to decouple configuration data from container images. ConfigMap stores non-sensitive data, while Secret stores sensitive data (Base64 encoded).


1. ConfigMap

1.1 Creating ConfigMaps

kubectl create configmap app-config --from-literal=APP_COLOR=blue --from-literal=APP_MODE=production

# Create from a file (filename becomes the key)
kubectl create configmap app-config --from-file=app.properties

# Create from a file (custom key)
kubectl create configmap app-config --from-file=custom-key=app.properties

# Create from an env-file
kubectl create configmap app-config --from-env-file=app.env

# Create from a directory
kubectl create configmap app-config --from-dir=config/

# Generate YAML
kubectl create configmap app-config --from-literal=APP_COLOR=blue --dry-run=client -o yaml

1.2 ConfigMap YAML Example

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_COLOR: blue
  APP_MODE: production
  app.properties: |
    key1=value1
    key2=value2
# View ConfigMaps
kubectl get configmaps
kubectl get cm
kubectl describe cm app-config
kubectl get cm app-config -o yaml

2. Secret

Data in Secrets is stored as Base64 encoding.

2.1 Creating Secrets

# generic: Create from literal values
kubectl create secret generic db-secret \
  --from-literal=DB_USER=admin \
  --from-literal=DB_PASSWORD=supersecret

# generic: Create from a file
kubectl create secret generic db-secret --from-file=db.env

# tls: Create a TLS certificate Secret
kubectl create secret tls tls-secret \
  --cert=path/to/tls.crt \
  --key=path/to/tls.key

# docker-registry: Image registry authentication
kubectl create secret docker-registry regcred \
  --docker-server=https://index.docker.io/v1/ \
  --docker-username=<user> \
  --docker-password=<password> \
  --docker-email=<email>

# Generate YAML
kubectl create secret generic db-secret --from-literal=DB_PASSWORD=pass123 --dry-run=client -o yaml

2.2 Secret YAML Example

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  DB_USER: YWRtaW4=          # base64 encoded
  DB_PASSWORD: c3VwZXJzZWNyZXQ=

2.3 Base64 Encoding and Decoding

# Encode
echo -n "admin" | base64
echo -n "supersecret" | base64

# Decode
echo "YWRtaW4=" | base64 -d
echo "c3VwZXJzZWNyZXQ=" | base64 -d

# Use stringData in Secret YAML directly (plain text, K8s auto-encodes)
# Using stringData (stored as plain text, auto-converted to data on creation)
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
stringData:
  DB_USER: admin
  DB_PASSWORD: supersecret

3. Injecting into Pod Environment Variables

3.1 Using env (Individual Injection)

apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
  - name: app
    image: nginx
    env:
    - name: APP_COLOR           # Environment variable name in the container
      valueFrom:
        configMapKeyRef:
          name: app-config      # ConfigMap name
          key: APP_COLOR        # Key in the ConfigMap
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: DB_PASSWORD

3.2 Using envFrom (Batch Injection)

apiVersion: v1
kind: Pod
metadata:
  name: envfrom-pod
spec:
  containers:
  - name: app
    image: nginx
    envFrom:
    - configMapRef:
        name: app-config           # Inject all ConfigMap entries
        optional: true             # Don't error if ConfigMap doesn't exist
    - secretRef:
        name: db-secret            # Inject all Secret entries

3.3 Prefix Handling

envFrom:
- configMapRef:
    name: app-config
  prefix: CONFIG_     # Add CONFIG_ prefix to all variable names

4. Mounting as Volumes

4.1 ConfigMap Mounted as a Volume

apiVersion: v1
kind: Pod
metadata:
  name: configmap-volume
spec:
  volumes:
  - name: config-volume
    configMap:
      name: app-config
      items:                      # Optional: only mount specific keys
      - key: app.properties
        path: myapp.properties    # Filename after mounting
  containers:
  - name: app
    image: nginx
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config

4.2 Secret Mounted as a Volume

apiVersion: v1
kind: Pod
metadata:
  name: secret-volume
spec:
  volumes:
  - name: secret-volume
    secret:
      secretName: db-secret
      defaultMode: 0400           # File permissions (default is 0644)
  containers:
  - name: app
    image: nginx
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/secret
# Inspect the mounted Secret (each key becomes a file)
kubectl exec secret-volume -- ls /etc/secret
kubectl exec secret-volume -- cat /etc/secret/DB_PASSWORD

# Note: Secrets mounted as volumes are automatically decoded to plain text

4.3 Hot Reload (Automatic Updates)

When ConfigMap/Secret is mounted as a volume, updating the ConfigMap/Secret will automatically update the files in the Pod (with a delay of seconds to minutes).

# Update ConfigMap
kubectl edit cm app-config

# Verify the file in the volume has been updated
kubectl exec configmap-volume -- cat /etc/config/APP_COLOR

Note: Environment variables injected via env/envFrom are not hot-reloaded; a Pod restart is required.


5. Immutable ConfigMap/Secret

Kubernetes 1.21+ supports immutable ConfigMaps/Secrets, improving performance and preventing accidental modification.

apiVersion: v1
kind: ConfigMap
metadata:
  name: immutable-config
data:
  APP_COLOR: blue
immutable: true
apiVersion: v1
kind: Secret
metadata:
  name: immutable-secret
type: Opaque
stringData:
  DB_PASSWORD: supersecret
immutable: true
# Once set to immutable, you must delete and recreate to modify
kubectl delete cm immutable-config
kubectl create cm immutable-config --from-literal=APP_COLOR=red

6. Practical Exam Commands

# Quickly create and inject a ConfigMap
kubectl create configmap app-env --from-literal=DEBUG=true --from-literal=LOG_LEVEL=info
kubectl run nginx --image=nginx --dry-run=client -o yaml > pod.yaml
# Add envFrom in pod.yaml

# Create a Secret and use it in a Pod
kubectl create secret generic my-secret --from-literal=SECRET_KEY=abc123
kubectl run secret-pod --image=busybox --dry-run=client -o yaml -- sleep 3600 > secret-pod.yaml
# Add env/volume referencing the Secret

# Check Secret contents
kubectl get secret my-secret -o jsonpath='{.data.SECRET_KEY}' | base64 -d

# Inject all keys from a ConfigMap/Secret as environment variables
kubectl create configmap full-config --from-env-file=./app.env
kubectl run app --image=nginx --restart=Never -o yaml --dry-run=client > app.yaml
# Edit to add envFrom.configMapRef

# Load from Secret and verify
kubectl create secret generic creds --from-literal=user=admin --from-literal=pass=secret123
kubectl run secret-test --image=busybox --restart=Never -it --rm -- env | grep user

🧪 Complete Hands-on Example: Create ConfigMap and Secret and Inject into a Pod

Scenario Description

Create an application configuration ConfigMap and a database password Secret, then inject them into a Pod via both environment variables and volume mounts.

Prerequisites

  • A working Kubernetes cluster
  • kubectl configured to connect to the cluster

Steps

Step 1: Create ConfigMap and Secret

# Create ConfigMap (application configuration)
kubectl create configmap app-config \
  --from-literal=APP_COLOR=blue \
  --from-literal=APP_MODE=production \
  --from-literal=LOG_LEVEL=info
# Expected output: configmap/app-config created

# Create Secret (database credentials)
kubectl create secret generic db-secret \
  --from-literal=DB_USER=admin \
  --from-literal=DB_PASSWORD=Sup3rS3cret!
# Expected output: secret/db-secret created

# View creation results
kubectl get cm app-config -o yaml | head -10
kubectl get secret db-secret -o yaml | head -10

Step 2: Inject via environment variables into a Pod

cat <<'EOF' > pod-env-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-env-demo
spec:
  containers:
  - name: app
    image: busybox:1.28
    command: ["sleep", "3600"]
    env:
    - name: APP_COLOR
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: APP_COLOR
    - name: DB_USER
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: DB_USER
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: DB_PASSWORD
EOF

kubectl apply -f pod-env-demo.yaml
# Expected output: pod/pod-env-demo created

Step 3: Inject via volume mount into a Pod

cat <<'EOF' > pod-volume-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-volume-demo
spec:
  volumes:
  - name: config-volume
    configMap:
      name: app-config
  - name: secret-volume
    secret:
      secretName: db-secret
  containers:
  - name: app
    image: busybox:1.28
    command: ["sleep", "3600"]
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
    - name: secret-volume
      mountPath: /etc/secret
EOF

kubectl apply -f pod-volume-demo.yaml
# Expected output: pod/pod-volume-demo created

Verification Results

# Verify environment variable injection
kubectl exec pod-env-demo -- env | grep -E "APP_COLOR|DB_USER|DB_PASSWORD"
# Expected output:
# APP_COLOR=blue
# DB_USER=admin
# DB_PASSWORD=Sup3rS3cret!

# Verify volume mount injection
kubectl exec pod-volume-demo -- ls /etc/config
# Expected output: APP_COLOR  APP_MODE  LOG_LEVEL

kubectl exec pod-volume-demo -- cat /etc/secret/DB_PASSWORD
# Expected output: Sup3rS3cret!  (Secret auto-decoded to plain text when mounted as a volume)

# Cleanup
kubectl delete pod pod-env-demo pod-volume-demo
kubectl delete cm app-config
kubectl delete secret db-secret
# Expected output: pod "pod-env-demo" deleted
#          pod "pod-volume-demo" deleted
#          configmap "app-config" deleted
#          secret "db-secret" deleted

Exam Tips

  • Values in Secrets are Base64 encoded, not encrypted. Sensitive data should use external key management tools (such as Vault) or enable KMS encryption
  • envFrom can inject all entries from a ConfigMap/Secret in bulk, saving YAML space, but you cannot select specific keys
  • Volume mount method supports hot reload (files in Pod update automatically when ConfigMap/Secret is modified), but env injection does not
  • When mounted as a volume, Secret files default to 0644 permissions; use defaultMode to change to 0400
  • In the exam, commonly use kubectl exec <pod> -- env | grep <key> to quickly verify injection success