Concept

![[images/截屏2026-03-24 16.45.32.png]]

A Volume can be used to hold data and state for Pods and containers.

  • A Pod can have multiple Volumes attached to it.
  • Containers rely on a mountPath to access a volume.

Storage Types

  • Volumes
  • PersistentVolumes
  • PersistentVolumeClaims
  • StorageClasses

Volumes

  • A Volume references a storage location
  • Must have a unique name
  • Attached to a Pod and may or may not be tied to the Pod’s lifetime (depending on the Volume type)
  • A Volume Mount references a Volume by name and defines a mountPath

Volume Types

  • emptyDir: Empty directory for storing transient data (shares a Pod’s lifetime) useful for sharing files between containers running in a Pod. (Ephemeral storage)
  • hostPath: Pod mounts into the node’s filesystem.
  • Network File System (nfs): An NFS share mounted into the Pod.
  • configMap/secret: Special types of volumes that provide a Pod with access to Kubernetes resources.
  • persistentVolumeClaim: Provides Pods with a more persistent storage option that is abstracted from the details.
  • cloud: Cluster-wide storage

emptyDir Volume

apiVersion: v1
kind: Pod
metadata:
  name: nginx-alpine-volume
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    volumeMounts:
      - name: html
        mountPath: /usr/share/nginx/html
        readOnly: true
    resources:
  - name: html-updater
    image: alpine
    command: ["/bin/sh", "-c"]
    args:
      - while true; do date >> /html/index.html;sleep 10; done
    resources:
    volumeMounts:
      - name: html
        mountPath: /html
  volumes:
  - name: html
    emptyDir: {} #lifecycle tied to Pod

# kubectl apply -f nginx-alpine-emptyDir.pod.yml
# kubectl port-forward nginx-alpine-volume 8080:80

![[images/截屏2026-03-24 17.14.14.png]]

hostPath Volume

apiVersion: v1
kind: Pod
metadata:
  name: docker-volume
spec:
  containers:
  - name: docker
    image: docker
    command: ["sleep"]
    args: ["100000"]
    volumeMounts:
    - name: docker-socket
      mountPath: /var/run/docker.sock
    resources:
  volumes:
  - name: docker-socket
    hostPath:
      path: /var/run/docker.sock
      type: Socket

# Once Pod is created you can shell into it to run Docker commands:
# kubectl exec [pod-name] -it -- sh

Valid types includes:

  • DirectoryOrCreate
  • Directory
  • FileOrCreate
  • File
  • Socket
  • CharDevice
  • BlockDevice

![[images/截屏2026-03-24 17.22.15.png]]

Cloud Volumes

Cloud providers support different types of Volumes:

  • Azure: Azure Disk and Azure File
  • AWS: Elastic Block Store
  • GCP: GCE Persistent Disk

![[images/截屏2026-03-24 17.26.28.png]]

![[images/截屏2026-03-24 17.27.06.png]]

![[images/截屏2026-03-24 17.27.29.png]]

Check

kubectl describe pod [pod_name]
# Get Pod YAML
kubectl get pod [pod_name] -o yaml

PersistentVolumes and PersistentVolumeClaims

A PersistentVolume (PV) is a cluster-wide storage unit provisioned by an administrator with a lifecycle independent from a Pod.

A PersistentVolumeClaim (PVC) is a request for a storage unit (PV).

![[images/截屏2026-03-25 15.14.44.png]]

  • A PersistentVolume is a cluster-wide storage resource that relies on network-attached storage (NAS).
  • Normally provisioned by a cluster administrator.
  • Available to a Pod even if it gets rescheduled to a different Node.
  • Rely on a storage provider such as NFS, cloud storage, or other options.
  • Associated with a Pod by using a PersistentVolumeClaim.

PersistentVolume Workflow

  1. Create network storage resource (NFS, cloud, …)
  2. Define a PV and send to the Kubernetes API
  3. Create a PVC
  4. Kubernetes binds the PVC to the PV
  5. Pod Volume references the PVC

![[images/截屏2026-03-25 15.18.40.png]]

YAML

Create PV

![[images/截屏2026-03-25 15.22.06.png]]

Create PVC

![[images/截屏2026-03-25 15.22.55.png]]

Create Reference

![[images/截屏2026-03-25 15.24.08.png]]

StorageClasses

A StorageClasses (SC) is a type of storage template that can be used to dynamically provision storage.

![[images/截屏2026-03-25 15.25.59.png]]

  • Used to define different classes of storage
  • Act as a type of storage template
  • Supports dynamic provisioning of PersistentVolumes
  • Don’t need to create PV in advance

StorageClass Workflow

  1. Create Storage Class
  2. Create PVC referencing to SC
  3. Kubernetes uses SC provisioner to provision a PV
  4. Storage provisioned, PV created and bound to PVC
  5. Pod volume references PVC

![[images/截屏2026-03-25 15.29.41.png]]

YAML

Define SC

![[images/截屏2026-03-25 15.31.02.png]]

Define PV

![[images/截屏2026-03-25 15.32.48.png]]

Define PVC

![[images/截屏2026-03-25 15.33.50.png]]

![[images/截屏2026-03-25 15.34.15.png]]

Mongo Example

apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app: mongo-env
  name: mongo-env
data:
  MONGODB_DBNAME: codeWithDan
  #NO - not a good idea to store a password in a ConfigMap (demo only). See the "secrets" folder for another demo of this.
  MONGODB_PASSWORD: password 
  MONGODB_ROLE: readWrite
  #NO - not a good idea to store a password in a ConfigMap (demo only). See the "secrets" folder for another demo of this.
  MONGODB_ROOT_PASSWORD: password
  MONGODB_ROOT_ROLE: root
  MONGODB_ROOT_USERNAME: dbadmin
  MONGODB_USERNAME: webrole

---

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
# The reclaim policy applies to the persistent volumes not the storage class itself. 
# pvs and pvcs that are created using that storage class will inherit the reclaim policy set here.
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer

---

# Note: While a local storage PV works, going with a more durable solution (NFS, cloud option, etc.) is recommended
# Adding this for demo purposes to run on Docker Desktop Kubernetes since it only supports a single Node
# https://kubernetes.io/blog/2018/04/13/local-persistent-volumes-beta/
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mongo-pv
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  # StorageClass has a reclaim policy default so it'll be "inherited" by the PV
  # persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  hostPath:
    path: /private/tmp/data/db
    type: DirectoryOrCreate
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - docker-desktop

---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongo-pvc
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: local-storage
  resources:
    requests:
      storage: 1Gi

---

apiVersion: v1
kind: Service
metadata:
  name: mongo
spec:
  selector:
    app: mongo
  ports:
  - port: 27017
    targetPort: 27017

---

apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app: mongo
  name: mongo
spec:
  serviceName: mongo
  replicas: 1
  selector:
    matchLabels:
      app: mongo
  template:
    metadata:
      labels:
        app: mongo
    spec:
      containers:
        - image: mongo
          name: mongo
          ports:
          - containerPort: 27017
          command:
          - mongod
          - "--auth"
          resources: {}        
          volumeMounts:
          - name: mongo-volume
            mountPath: /data/db
          env:
            - name: MONGODB_DBNAME
              valueFrom:
                configMapKeyRef:
                  key: MONGODB_DBNAME
                  name: mongo-env
            - name: MONGODB_PASSWORD
              valueFrom:
                configMapKeyRef:
                  key: MONGODB_PASSWORD
                  name: mongo-env
            - name: MONGODB_ROLE
              valueFrom:
                configMapKeyRef:
                  key: MONGODB_ROLE
                  name: mongo-env
            - name: MONGODB_ROOT_PASSWORD
              valueFrom:
                configMapKeyRef:
                  key: MONGODB_ROOT_PASSWORD
                  name: mongo-env
            - name: MONGODB_ROOT_ROLE
              valueFrom:
                configMapKeyRef:
                  key: MONGODB_ROOT_ROLE
                  name: mongo-env
            - name: MONGODB_ROOT_USERNAME
              valueFrom:
                configMapKeyRef:
                  key: MONGODB_ROOT_USERNAME
                  name: mongo-env
            - name: MONGODB_USERNAME
              valueFrom:
                configMapKeyRef:
                  key: MONGODB_USERNAME
                  name: mongo-env
      volumes:
      - name: mongo-volume
        persistentVolumeClaim:
          claimName: mongo-pvc