Skip to main content

Configuration & Storage

ConfigMaps, Secrets, Persistent Volumes, and storage management for application configuration and data persistence.

ConfigMaps

ConfigMap Operations

# Create ConfigMap from literals
kubectl create configmap app-config --from-literal=database_url=postgres://localhost:5432/myapp
kubectl create configmap app-config --from-literal=debug=true --from-literal=log_level=info

# Create ConfigMap from file
kubectl create configmap app-config --from-file=config.properties
kubectl create configmap app-config --from-file=app-config=/path/to/config.yml

# Create ConfigMap from directory
kubectl create configmap app-config --from-file=/path/to/config/directory/

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

# Get ConfigMaps
kubectl get configmaps
kubectl get cm
kubectl get cm -o wide

# Describe ConfigMap
kubectl describe configmap app-config

# Edit ConfigMap
kubectl edit configmap app-config

# Delete ConfigMap
kubectl delete configmap app-config

ConfigMap YAML

apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: default
data:
database_url: 'postgres://localhost:5432/myapp'
redis_url: 'redis://localhost:6379'
log_level: 'info'
debug: 'false'
app.properties: |
database.host=localhost
database.port=5432
database.name=myapp
redis.host=localhost
redis.port=6379
nginx.conf: |
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
}
}

Using ConfigMaps in Pods

apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
spec:
containers:
- name: app
image: nginx
# Environment variables from ConfigMap
env:
- name: DATABASE_URL
valueFrom:
configMapKeyRef:
name: app-config
key: database_url
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: log_level
# All keys as environment variables
envFrom:
- configMapRef:
name: app-config
# Mount as volume
volumeMounts:
- name: config-volume
mountPath: /etc/config
- name: nginx-config
mountPath: /etc/nginx/conf.d
volumes:
- name: config-volume
configMap:
name: app-config
- name: nginx-config
configMap:
name: app-config
items:
- key: nginx.conf
path: default.conf

Secrets

Secret Operations

# Create Secret from literals
kubectl create secret generic app-secret --from-literal=username=admin --from-literal=password=secret123

# Create Secret from files
kubectl create secret generic app-secret --from-file=username.txt --from-file=password.txt

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

# Create Docker registry Secret
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=user \
--docker-password=password \
--docker-email=user@example.com

# Get Secrets
kubectl get secrets
kubectl get secret
kubectl get secret -o wide

# Describe Secret (values are hidden)
kubectl describe secret app-secret

# Get Secret values (base64 encoded)
kubectl get secret app-secret -o yaml
kubectl get secret app-secret -o jsonpath='{.data.password}' | base64 --decode

# Edit Secret
kubectl edit secret app-secret

# Delete Secret
kubectl delete secret app-secret

Secret YAML

apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
data:
username: YWRtaW4= # base64 encoded 'admin'
password: cGFzc3dvcmQxMjM= # base64 encoded 'password123'
database-url: cG9zdGdyZXM6Ly91c2VyOnBhc3NAaG9zdDo1NDMyL2Ri

---
apiVersion: v1
kind: Secret
metadata:
name: tls-secret
type: kubernetes.io/tls
data:
tls.crt: LS0tLS1CRUdJTi... # base64 encoded certificate
tls.key: LS0tLS1CRUdJTi... # base64 encoded private key

---
apiVersion: v1
kind: Secret
metadata:
name: docker-secret
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: eyJhdXRocyI6eyJyZWdpc3RyeS... # base64 encoded docker config

Using Secrets in Pods

apiVersion: v1
kind: Pod
metadata:
name: secret-pod
spec:
containers:
- name: app
image: nginx
# Environment variables from Secret
env:
- name: DATABASE_USERNAME
valueFrom:
secretKeyRef:
name: app-secret
key: username
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: app-secret
key: password
# All keys as environment variables
envFrom:
- secretRef:
name: app-secret
# Mount as volume
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: app-secret
defaultMode: 0400
# Use Docker registry secret
imagePullSecrets:
- name: docker-secret

Persistent Volumes (PV)

PersistentVolume YAML

apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: fast-ssd
hostPath:
path: /data/mysql

---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle
nfs:
server: nfs-server.example.com
path: /exports/data

---
apiVersion: v1
kind: PersistentVolume
metadata:
name: aws-ebs-pv
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: gp2
awsElasticBlockStore:
volumeID: vol-12345678
fsType: ext4

PV Operations

# Get PersistentVolumes
kubectl get persistentvolumes
kubectl get pv
kubectl get pv -o wide

# Describe PV
kubectl describe pv pv-name

# Delete PV
kubectl delete pv pv-name

Persistent Volume Claims (PVC)

PersistentVolumeClaim YAML

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: fast-ssd

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: shared-data-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 50Gi
selector:
matchLabels:
type: nfs

PVC Operations

# Get PersistentVolumeClaims
kubectl get persistentvolumeclaims
kubectl get pvc
kubectl get pvc -o wide

# Describe PVC
kubectl describe pvc pvc-name

# Create PVC
kubectl apply -f pvc.yaml

# Delete PVC
kubectl delete pvc pvc-name

Using PVC in Pods

apiVersion: v1
kind: Pod
metadata:
name: mysql-pod
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
value: 'password'
volumeMounts:
- name: mysql-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-storage
persistentVolumeClaim:
claimName: mysql-pvc

---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx
volumeMounts:
- name: web-content
mountPath: /usr/share/nginx/html
volumes:
- name: web-content
persistentVolumeClaim:
claimName: shared-data-pvc

Storage Classes

StorageClass YAML

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
fsType: ext4
allowVolumeExpansion: true
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow-hdd
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-standard
replication-type: regional-pd
allowVolumeExpansion: true
reclaimPolicy: Retain

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-storage
provisioner: example.com/nfs
parameters:
server: nfs-server.example.com
path: /exports

StorageClass Operations

# Get StorageClasses
kubectl get storageclasses
kubectl get sc
kubectl get sc -o wide

# Describe StorageClass
kubectl describe sc storage-class-name

# Set default StorageClass
kubectl patch storageclass storage-class-name -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

# Remove default StorageClass
kubectl patch storageclass storage-class-name -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'

Volume Types

EmptyDir

apiVersion: v1
kind: Pod
metadata:
name: emptydir-pod
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: temp-storage
mountPath: /tmp/data
- name: sidecar
image: busybox
volumeMounts:
- name: temp-storage
mountPath: /shared
volumes:
- name: temp-storage
emptyDir:
sizeLimit: 1Gi

HostPath

apiVersion: v1
kind: Pod
metadata:
name: hostpath-pod
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: host-storage
mountPath: /data
volumes:
- name: host-storage
hostPath:
path: /var/data
type: DirectoryOrCreate

NFS

apiVersion: v1
kind: Pod
metadata:
name: nfs-pod
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: nfs-storage
mountPath: /data
volumes:
- name: nfs-storage
nfs:
server: nfs-server.example.com
path: /exports/data

ConfigMap and Secret Volumes

apiVersion: v1
kind: Pod
metadata:
name: config-secret-pod
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: config-volume
mountPath: /etc/config
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: config-volume
configMap:
name: app-config
items:
- key: app.properties
path: application.properties
- name: secret-volume
secret:
secretName: app-secret
defaultMode: 0600

Dynamic Provisioning

Dynamic PVC

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: dynamic-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: fast-ssd
resources:
requests:
storage: 20Gi

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: database
spec:
serviceName: database
replicas: 3
selector:
matchLabels:
app: database
template:
metadata:
labels:
app: database
spec:
containers:
- name: postgres
image: postgres:13
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ['ReadWriteOnce']
storageClassName: 'fast-ssd'
resources:
requests:
storage: 10Gi

Volume Snapshots

VolumeSnapshot YAML

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: mysql-snapshot
spec:
volumeSnapshotClassName: csi-snapclass
source:
persistentVolumeClaimName: mysql-pvc

---
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
name: csi-snapclass
driver: ebs.csi.aws.com
deletionPolicy: Delete

Restore from Snapshot

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: restored-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: fast-ssd
resources:
requests:
storage: 10Gi
dataSource:
name: mysql-snapshot
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io

Quick Reference

Configuration Commands

  • kubectl create configmap name --from-literal=key=value - Create ConfigMap
  • kubectl create secret generic name --from-literal=key=value - Create Secret
  • kubectl get cm - List ConfigMaps
  • kubectl get secrets - List Secrets
  • kubectl describe cm name - ConfigMap details

Storage Commands

  • kubectl get pv - List Persistent Volumes
  • kubectl get pvc - List Persistent Volume Claims
  • kubectl get sc - List Storage Classes
  • kubectl describe pv name - PV details
  • kubectl describe pvc name - PVC details

Configuration Patterns

# Create ConfigMap from file
kubectl create configmap app-config --from-file=config.yml

# Create Secret for TLS
kubectl create secret tls tls-secret --cert=cert.crt --key=cert.key

# Create Docker registry secret
kubectl create secret docker-registry regcred --docker-server=registry.io --docker-username=user --docker-password=pass

# Decode secret value
kubectl get secret app-secret -o jsonpath='{.data.password}' | base64 -d

Volume Best Practices

  • Use PersistentVolumes for stateful applications
  • Implement proper backup strategies for persistent data
  • Use appropriate storage classes for performance requirements
  • Set resource limits for temporary volumes (emptyDir)
  • Use ReadWriteMany for shared storage needs
  • Implement volume snapshots for data protection