Belajar Kubernetes - Sharing Volume Between Pods
Episode 22 of 47

Belajar Kubernetes - Sharing Volume Between Pods

Di episode ini kita akan coba bahas cara sharing volume antara Pod di Kubernetes. Kita akan mempelajari PersistentVolume, PersistentVolumeClaim, StorageClass, dan strategi untuk sharing data across Pod.

Arman Dwi Pangestu
Arman Dwi PangestuMarch 28, 2026
0 views
8 min read

Pendahuluan

Di episode sebelumnya kita sudah belajar tentang Secret. Selanjutnya di episode 22 kali ini, kita akan coba bahas Sharing Volume Between Pod, exploring cara share data across multiple Pod menggunakan PersistentVolume dan PersistentVolumeClaim.

Catatan: Disini saya akan menggunakan Kubernetes Cluster yang di install melalui K3s.

Sementara volume di episode sebelumnya adalah Pod-scoped, sharing data antara Pod require different approach. PersistentVolume menyediakan cluster-level storage resource yang bisa claimed oleh multiple Pod, enable data sharing dan persistence beyond Pod lifecycle.

Apa Itu Volume Sharing?

Volume Sharing adalah kemampuan untuk multiple Pod access storage resource yang sama. Ini enable scenario seperti shared file storage, collaborative workload, dan data exchange antara application.

Bayangkan shared volume seperti network drive di office - multiple employee (Pod) bisa access file yang sama, collaborate di document, dan share data tanpa duplicate storage.

Karakteristik kunci Shared Volume:

  • Multi-Pod access - Multiple Pod bisa mount volume yang sama
  • Data persistence - Data survive Pod deletion dan recreation
  • Cluster-scoped - Storage exist independently dari Pod
  • Access mode - Control read/write permission
  • Dynamic provisioning - Automatic volume creation
  • Storage abstraction - Decouple storage dari Pod

Kenapa Share Volume Between Pod?

Sharing volume solve beberapa important use case:

  • Shared file storage - Multiple Pod accessing common file
  • Data exchange - Transfer data antara application
  • Collaborative workload - Multiple worker processing shared data
  • Centralized logging - Aggregate log dari multiple Pod
  • Shared configuration - Common config file across Pod
  • Media storage - Shared upload, image, video
  • Database replication - Shared storage untuk database cluster
  • Backup dan restore - Centralized backup storage

Tanpa shared volume, setiap Pod butuh storage sendiri, making data sharing complex dan inefficient.

PersistentVolume (PV)

PersistentVolume adalah cluster-level storage resource yang di provision oleh administrator atau dynamically created oleh StorageClass.

Karakteristik PersistentVolume

  • Cluster resource - Independent dari any Pod
  • Lifecycle independent - Survive Pod deletion
  • Provisioned storage - Pre-allocated atau dynamically created
  • Access mode - Define bagaimana volume bisa mounted
  • Reclaim policy - Apa yang terjadi ketika released
  • Storage capacity - Size dari volume

Membuat PersistentVolume

Contoh: NFS PersistentVolume

Kubernetesnfs-pv.yml
apiVersion: v1
kind: PersistentVolume
metadata:
    name: nfs-pv
spec:
    capacity:
        storage: 10Gi
    accessModes:
        - ReadWriteMany
    persistentVolumeReclaimPolicy: Retain
    nfs:
        server: nfs-server.example.com
        path: /shared/data

Contoh: HostPath PersistentVolume (untuk testing)

Kuberneteshostpath-pv.yml
apiVersion: v1
kind: PersistentVolume
metadata:
    name: hostpath-pv
spec:
    capacity:
        storage: 5Gi
    accessModes:
        - ReadWriteOnce
    persistentVolumeReclaimPolicy: Delete
    hostPath:
        path: /mnt/data
        type: DirectoryOrCreate

Warning

Warning: hostPath PersistentVolume hanya suitable untuk single-node testing. Gunakan network storage untuk production.

PersistentVolume Access Mode

Access mode determine bagaimana volume bisa mounted:

ReadWriteOnce (RWO)

  • Mounted read-write oleh single node
  • Multiple Pod di node yang sama bisa access
  • Paling common untuk block storage
Kubernetesyml
accessModes:
    - ReadWriteOnce

ReadOnlyMany (ROX)

  • Mounted read-only oleh many node
  • Useful untuk shared configuration atau static content
Kubernetesyml
accessModes:
    - ReadOnlyMany

ReadWriteMany (RWX)

  • Mounted read-write oleh many node
  • Required untuk true multi-Pod sharing
  • Butuh network filesystem (NFS, CephFS, GlusterFS)
Kubernetesyml
accessModes:
    - ReadWriteMany

ReadWriteOncePod (RWOP)

  • Mounted read-write oleh single Pod saja
  • Kubernetes 1.22+ feature
Kubernetesyml
accessModes:
    - ReadWriteOncePod

Reclaim Policy

Define apa yang terjadi ke volume ketika claim deleted:

Retain

  • Volume tidak deleted
  • Data preserved
  • Manual cleanup required
Kubernetesyml
persistentVolumeReclaimPolicy: Retain

Delete

  • Volume automatically deleted
  • Data lost
  • Common untuk dynamically provisioned volume
Kubernetesyml
persistentVolumeReclaimPolicy: Delete

Recycle (Deprecated)

  • Volume scrubbed dan made available lagi
  • Not recommended, gunakan Delete instead

PersistentVolumeClaim (PVC)

PersistentVolumeClaim adalah request untuk storage oleh user. Seperti Pod requesting CPU dan memory, tapi untuk storage.

Karakteristik PersistentVolumeClaim

  • Storage request - Specify size dan access mode
  • Namespace-scoped - Belong ke namespace
  • Binding - Automatically bound ke matching PV
  • Dynamic provisioning - Bisa trigger automatic PV creation
  • Used by Pod - Pod reference PVC, bukan PV directly

Membuat PersistentVolumeClaim

Contoh: Basic PVC

Kubernetesbasic-pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: data-pvc
spec:
    accessModes:
        - ReadWriteOnce
    resources:
        requests:
            storage: 5Gi

Contoh: PVC dengan StorageClass

Kubernetespvc-with-storageclass.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: fast-storage-pvc
spec:
    accessModes:
        - ReadWriteOnce
    storageClassName: fast-ssd
    resources:
        requests:
            storage: 10Gi

Contoh: Shared Storage PVC

Kubernetesshared-pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: shared-data-pvc
spec:
    accessModes:
        - ReadWriteMany
    resources:
        requests:
            storage: 20Gi

PVC Binding

Ketika kalian create PVC, Kubernetes find matching PV:

  1. Match criteria: capacity, access mode, storage class
  2. Binding: PVC bound ke PV
  3. Exclusive: Satu PVC per PV (kecuali ReadWriteMany)
  4. Status: PVC show "Bound" ketika successful

Check PVC status:

Kubernetesbash
sudo kubectl get pvc

Output:

Kubernetesbash
NAME           STATUS   VOLUME      CAPACITY   ACCESS MODES   STORAGECLASS   AGE
data-pvc       Bound    pv-001      5Gi        RWO            standard       2m
shared-pvc     Bound    nfs-pv      20Gi       RWX            nfs            1m

Menggunakan PVC di Pod

Pod reference PVC untuk mount persistent storage.

Single Pod dengan PVC

Kubernetespod-with-pvc.yml
apiVersion: v1
kind: Pod
metadata:
    name: app-pod
spec:
    containers:
        - name: app
          image: nginx:1.25
          volumeMounts:
              - name: data
                mountPath: /usr/share/nginx/html
    volumes:
        - name: data
          persistentVolumeClaim:
              claimName: data-pvc

Multiple Pod Sharing PVC (ReadWriteMany)

Kubernetesshared-pods.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: shared-storage
spec:
    accessModes:
        - ReadWriteMany
    resources:
        requests:
            storage: 10Gi
---
apiVersion: v1
kind: Pod
metadata:
    name: writer-pod
spec:
    containers:
        - name: writer
          image: busybox:1.36
          command:
              - sh
              - -c
              - while true; do date >> /data/log.txt; sleep 5; done
          volumeMounts:
              - name: shared
                mountPath: /data
    volumes:
        - name: shared
          persistentVolumeClaim:
              claimName: shared-storage
---
apiVersion: v1
kind: Pod
metadata:
    name: reader-pod
spec:
    containers:
        - name: reader
          image: busybox:1.36
          command:
              - sh
              - -c
              - tail -f /data/log.txt
          volumeMounts:
              - name: shared
                mountPath: /data
    volumes:
        - name: shared
          persistentVolumeClaim:
              claimName: shared-storage

Kedua Pod bisa access data yang sama simultaneously.

StorageClass

StorageClass menyediakan cara untuk describe different storage type dan enable dynamic provisioning.

Karakteristik StorageClass

  • Dynamic provisioning - Automatically create PV
  • Storage type - Define different performance tier
  • Parameter - Configure storage backend
  • Default class - Used ketika no class specified
  • Provisioner - Backend yang create volume

Membuat StorageClass

Contoh: Local Storage

Kuberneteslocal-storageclass.yml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
    name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

Contoh: NFS Storage

Kubernetesnfs-storageclass.yml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
    name: nfs-storage
provisioner: nfs.csi.k8s.io
parameters:
    server: nfs-server.example.com
    share: /shared
reclaimPolicy: Retain
volumeBindingMode: Immediate

Contoh: AWS EBS (untuk AWS)

Kubernetesaws-ebs-storageclass.yml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
    name: fast-ssd
provisioner: ebs.csi.aws.com
parameters:
    type: gp3
    iops: "3000"
    throughput: "125"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer

Default StorageClass

Set default StorageClass:

Kubernetesdefault-storageclass.yml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
    name: standard
    annotations:
        storageclass.kubernetes.io/is-default-class: "true"
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

Check default StorageClass:

Kubernetesbash
sudo kubectl get storageclass

Output:

Kubernetesbash
NAME                 PROVISIONER                    RECLAIMPOLICY   VOLUMEBINDINGMODE      AGE
standard (default)   kubernetes.io/no-provisioner   Delete          WaitForFirstConsumer   5d
fast-ssd             ebs.csi.aws.com                Delete          WaitForFirstConsumer   2d

Contoh Praktis

Contoh 1: Shared Web Content

Kubernetesshared-web-content.yml
# PersistentVolume
apiVersion: v1
kind: PersistentVolume
metadata:
    name: web-content-pv
spec:
    capacity:
        storage: 10Gi
    accessModes:
        - ReadWriteMany
    persistentVolumeReclaimPolicy: Retain
    nfs:
        server: nfs-server.example.com
        path: /web/content
---
# PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: web-content-pvc
spec:
    accessModes:
        - ReadWriteMany
    resources:
        requests:
            storage: 10Gi
---
# Deployment dengan multiple replica sharing volume
apiVersion: apps/v1
kind: Deployment
metadata:
    name: web-server
spec:
    replicas: 3
    selector:
        matchLabels:
            app: web
    template:
        metadata:
            labels:
                app: web
        spec:
            containers:
                - name: nginx
                  image: nginx:1.25
                  ports:
                      - containerPort: 80
                  volumeMounts:
                      - name: content
                        mountPath: /usr/share/nginx/html
            volumes:
                - name: content
                  persistentVolumeClaim:
                      claimName: web-content-pvc

Semua tiga replica share web content yang sama.

Contoh 2: Shared Upload Storage

Kubernetesshared-uploads.yml
# PVC untuk shared upload
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: uploads-pvc
spec:
    accessModes:
        - ReadWriteMany
    resources:
        requests:
            storage: 50Gi
---
# API server yang receive upload
apiVersion: apps/v1
kind: Deployment
metadata:
    name: api-server
spec:
    replicas: 2
    selector:
        matchLabels:
            app: api
    template:
        metadata:
            labels:
                app: api
        spec:
            containers:
                - name: api
                  image: myapi:latest
                  ports:
                      - containerPort: 8080
                  volumeMounts:
                      - name: uploads
                        mountPath: /var/uploads
            volumes:
                - name: uploads
                  persistentVolumeClaim:
                      claimName: uploads-pvc
---
# Worker yang process upload
apiVersion: apps/v1
kind: Deployment
metadata:
    name: upload-processor
spec:
    replicas: 3
    selector:
        matchLabels:
            app: processor
    template:
        metadata:
            labels:
                app: processor
        spec:
            containers:
                - name: processor
                  image: processor:latest
                  volumeMounts:
                      - name: uploads
                        mountPath: /var/uploads
                        readOnly: true
            volumes:
                - name: uploads
                  persistentVolumeClaim:
                      claimName: uploads-pvc

API server write upload, processor read mereka.

Contoh 3: Shared Configuration

Kubernetesshared-config.yml
# PVC untuk shared configuration
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: config-pvc
spec:
    accessModes:
        - ReadOnlyMany
    resources:
        requests:
            storage: 1Gi
---
# Config manager (write config)
apiVersion: v1
kind: Pod
metadata:
    name: config-manager
spec:
    containers:
        - name: manager
          image: config-manager:latest
          volumeMounts:
              - name: config
                mountPath: /config
    volumes:
        - name: config
          persistentVolumeClaim:
              claimName: config-pvc
---
# Application (read config)
apiVersion: apps/v1
kind: Deployment
metadata:
    name: app
spec:
    replicas: 5
    selector:
        matchLabels:
            app: myapp
    template:
        metadata:
            labels:
                app: myapp
        spec:
            containers:
                - name: app
                  image: myapp:latest
                  volumeMounts:
                      - name: config
                        mountPath: /etc/app/config
                        readOnly: true
            volumes:
                - name: config
                  persistentVolumeClaim:
                      claimName: config-pvc

Contoh 4: StatefulSet dengan Shared dan Individual Storage

Kubernetesstatefulset-mixed-storage.yml
# Shared PVC untuk common data
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: shared-data-pvc
spec:
    accessModes:
        - ReadWriteMany
    resources:
        requests:
            storage: 20Gi
---
# StatefulSet dengan both shared dan individual storage
apiVersion: apps/v1
kind: StatefulSet
metadata:
    name: database
spec:
    serviceName: database
    replicas: 3
    selector:
        matchLabels:
            app: db
    template:
        metadata:
            labels:
                app: db
        spec:
            containers:
                - name: postgres
                  image: postgres:15
                  volumeMounts:
                      # Individual storage per Pod
                      - name: data
                        mountPath: /var/lib/postgresql/data
                      # Shared storage across semua Pod
                      - name: shared
                        mountPath: /shared
            volumes:
                - name: shared
                  persistentVolumeClaim:
                      claimName: shared-data-pvc
    # Individual PVC per Pod
    volumeClaimTemplates:
        - metadata:
              name: data
          spec:
              accessModes:
                  - ReadWriteOnce
              resources:
                  requests:
                      storage: 10Gi

Volume Expansion

Expand existing PVC size (jika supported oleh StorageClass).

Enable Volume Expansion

Kubernetesexpandable-storageclass.yml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
    name: expandable-storage
provisioner: kubernetes.io/no-provisioner
allowVolumeExpansion: true

Expand PVC

Edit PVC untuk increase size:

Kubernetesbash
sudo kubectl edit pvc data-pvc

Change storage request:

Kubernetesyml
spec:
    resources:
        requests:
            storage: 20Gi  # Increased dari 10Gi

Atau patch directly:

Kubernetesbash
sudo kubectl patch pvc data-pvc -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'

Important

Penting: Volume expansion hanya increase size, never decrease. Beberapa storage type require Pod restart untuk recognize new size.

Kesalahan Umum dan Pitfall

Kesalahan 1: Wrong Access Mode untuk Sharing

Problem: Gunakan ReadWriteOnce untuk multi-Pod sharing.

Solusi: Gunakan ReadWriteMany untuk true sharing:

Kubernetesyml
# Buruk: Tidak bisa share across node
accessModes:
    - ReadWriteOnce
 
# Bagus: Bisa share across node
accessModes:
    - ReadWriteMany

Kesalahan 2: No Matching PV

Problem: PVC stay di Pending state.

Solusi: Create matching PV atau gunakan dynamic provisioning:

Kubernetesbash
# Check PVC status
sudo kubectl describe pvc <pvc-name>
 
# Look for event explaining kenapa binding failed

Kesalahan 3: Insufficient Storage

Problem: PVC request lebih dari PV provide.

Solusi: Match PVC request ke available PV capacity:

Kubernetesyml
# PV capacity
capacity:
    storage: 10Gi
 
# PVC request (harus <= PV capacity)
resources:
    requests:
        storage: 10Gi

Kesalahan 4: Gunakan hostPath untuk Multi-Node

Problem: hostPath hanya work di single node.

Solusi: Gunakan network storage untuk multi-node cluster:

Kubernetesyml
# Buruk: hostPath untuk production
hostPath:
    path: /data
 
# Bagus: NFS untuk production
nfs:
    server: nfs-server.example.com
    path: /shared/data

Kesalahan 5: Lupa Reclaim Policy

Problem: Data deleted ketika PVC removed.

Solusi: Gunakan Retain untuk important data:

Kubernetesyml
persistentVolumeReclaimPolicy: Retain

Best Practice

Gunakan StorageClass

Define storage tier untuk different need:

Kubernetesyml
# Fast SSD untuk database
storageClassName: fast-ssd
 
# Standard HDD untuk log
storageClassName: standard
 
# Shared NFS untuk upload
storageClassName: nfs-storage

Set Appropriate Access Mode

Pilih based on sharing requirement:

Kubernetesyml
# Single Pod, single node
accessModes:
    - ReadWriteOnce
 
# Multiple Pod, multiple node
accessModes:
    - ReadWriteMany
 
# Read-only sharing
accessModes:
    - ReadOnlyMany

Gunakan Retain untuk Production Data

Protect important data:

Kubernetesyml
persistentVolumeReclaimPolicy: Retain

Label PV dan PVC

Organize storage resource:

Kubernetesyml
metadata:
    name: database-pv
    labels:
        type: database
        environment: production
        tier: fast

Monitor Storage Usage

Check PVC usage regularly:

Kubernetesbash
sudo kubectl get pvc
sudo kubectl describe pvc <pvc-name>

Plan untuk Growth

Enable volume expansion:

Kubernetesyml
allowVolumeExpansion: true

Gunakan Separate PVC

Jangan share PVC unnecessarily:

Kubernetesyml
# Bagus: Separate PVC untuk different purpose
- name: database-pvc
- name: logs-pvc
- name: uploads-pvc

Melihat Storage Resource

Get PersistentVolume

Kubernetesbash
sudo kubectl get pv

Get PersistentVolumeClaim

Kubernetesbash
sudo kubectl get pvc
sudo kubectl get pvc -A  # Semua namespace

Describe PV

Kubernetesbash
sudo kubectl describe pv <pv-name>

Describe PVC

Kubernetesbash
sudo kubectl describe pvc <pvc-name>

Get StorageClass

Kubernetesbash
sudo kubectl get storageclass

Check Volume Usage

Kubernetesbash
sudo kubectl exec <pod-name> -- df -h

Troubleshooting Shared Volume

PVC Pending

Check kenapa PVC tidak binding:

Kubernetesbash
sudo kubectl describe pvc <pvc-name>

Common cause:

  • No matching PV available
  • Insufficient capacity
  • Access mode mismatch
  • StorageClass not found

Permission Denied

Set proper security context:

Kubernetesyml
securityContext:
    fsGroup: 2000
    runAsUser: 1000

Data Tidak Visible

Verify PVC bound dan mounted:

Kubernetesbash
sudo kubectl get pvc
sudo kubectl describe pod <pod-name>

Volume Full

Check disk usage dan expand jika needed:

Kubernetesbash
sudo kubectl exec <pod-name> -- df -h
sudo kubectl patch pvc <pvc-name> -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'

Penutup

Pada episode 22 ini, kita telah membahas Sharing Volume Between Pod di Kubernetes. Kita sudah belajar tentang PersistentVolume, PersistentVolumeClaim, StorageClass, dan strategi untuk sharing data across Pod.

Key takeaway:

  • PersistentVolume (PV) adalah cluster-level storage resource
  • PersistentVolumeClaim (PVC) adalah request untuk storage
  • Pod reference PVC, bukan PV directly
  • ReadWriteMany access mode enable true multi-Pod sharing
  • StorageClass enable dynamic provisioning
  • Reclaim policy control data retention (Retain, Delete)
  • Gunakan network storage (NFS, CephFS) untuk multi-node sharing
  • Volume expansion allow growing storage size
  • Access mode control bagaimana volume mounted (RWO, ROX, RWX, RWOP)
  • Default StorageClass used ketika none specified
  • Label dan organize storage resource
  • Monitor storage usage regularly
  • Gunakan Retain policy untuk production data

Sharing volume antara Pod essential untuk collaborative workload dan data exchange di Kubernetes. Dengan memahami PersistentVolume dan PersistentVolumeClaim, kalian bisa design robust storage architecture untuk application kalian.

Bagaimana, makin jelas kan tentang Sharing Volume di Kubernetes? Jadi, pastikan tetap semangat belajar dan nantikan episode selanjutnya!