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 ConfigMapkubectl create secret generic name --from-literal=key=value- Create Secretkubectl get cm- List ConfigMapskubectl get secrets- List Secretskubectl describe cm name- ConfigMap details
Storage Commands
kubectl get pv- List Persistent Volumeskubectl get pvc- List Persistent Volume Claimskubectl get sc- List Storage Classeskubectl describe pv name- PV detailskubectl 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