PersistentVolume dan PersistentVolumeClaim adalah pasangan objek yang memisahkan penyediaan penyimpanan dari kebutuhan aplikasi, sehingga Pod tidak perlu mengetahui detail teknis di belakang disknya. Topik ini membahas peran masing-masing objek, alur binding dari claim ke volume nyata, arti setiap accessModes, serta siklus hidup lengkap dari provisioning sampai reclaim. Alur bindingnya juga disimulasikan secara terprogram agar aturan pencocokannya terlihat jelas.
PersistentVolume sebagai sumber daya kluster#
PersistentVolume, yang selanjutnya disebut PV, adalah sumber daya tingkat kluster berupa kapasitas penyimpanan nyata yang sudah tersedia. Objek ini dibuat oleh pengelola kluster atau oleh sistem provisioning otomatis, dan hidup terlepas dari Pod maupun namespace yang menggunakannya. Manifest PV memuat tiga kelompok informasi yang menentukan kecocokannya, yaitu kapasitas, accessModes, dan penyimpanan di belakangnya:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-arsip-1
labels:
jenis: arsip
spec:
capacity:
storage: 2Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
hostPath:
path: /data/pv/arsip-1
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-arsip-2
labels:
jenis: arsip
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
hostPath:
path: /data/pv/arsip-2
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-bersama
labels:
jenis: bersama
spec:
capacity:
storage: 3Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
hostPath:
path: /data/pv/bersamaKetiga PV di atas menyusun kapasitas kluster sebesar 10 Gi dalam tiga bagian. Penyimpanan di belakangnya berupa hostPath yang cocok untuk lab lokal, sedangkan kluster produksi menggantinya dengan backend jaringan seperti NFS atau driver CSI. Label jenis tidak menuntut aturan apa pun dari Kubernetes, tetapi berguna sebagai penanda yang dirujuk selector pada claim.
Status PV melewati Available ketika siap diikat, Bound ketika terikat pada claim, dan Released setelah claimnya dihapus. Nilai-nilai tersebut terbaca langsung pada kolom STATUS keluaran kubectl, sehingga keadaan kapasitas kluster dapat ditinjau tanpa masuk ke backend penyimpanannya.
PersistentVolumeClaim sebagai permintaan#
PersistentVolumeClaim, yang selanjutnya disebut PVC, adalah permintaan kapasitas dari sisi pengguna, dan pembuatannya berada di dalam namespace. Permintaan menyatakan ukuran minimum, accessModes yang diinginkan, dan selektor label untuk mempersempit kandidat PV:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: arsip-catatan
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
selector:
matchLabels:
jenis: arsip
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: arsip-besar
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 4Gi
selector:
matchLabels:
jenis: arsip
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: laporan-bersama
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 2Gi
selector:
matchLabels:
jenis: laporanPod tidak menyentuh PV secara langsung. Bidang volumes pada Pod menunjuk PVC melalui persistentVolumeClaim.claimName, dan sistem menerjemahkan permintaan itu menjadi mount pada container. Lapisan tidak langsung ini membuat aplikasi tetap berjalan meskipun penyimpanan di belakangnya diganti, karena yang berubah hanya PVC tanpa menyentuh manifest Pod.
Bidang storageClassName pada claim juga menentukan jalannya pencocokan. Claim tanpa bidang tersebut dicocokkan dengan PV yang tidak membawa class, sedangkan claim dengan class hanya menunggu PV dari class yang sama, dan jalur kedua inilah yang dibahas pada topik StorageClass. Selain itu, resources.requests.storage menyatakan kapasitas minimum, sehingga PV dengan kapasitas lebih besar tetap sah sebagai pasangannya.
Alur binding dari claim ke volume#
Pencocokan dilakukan oleh controller PVC pada control plane. Setiap claim yang menunggu diperiksa terhadap PV yang berstatus Available, dan aturan pencocokannya menuntut kapasitas PV yang memenuhi permintaan, accessModes yang beririsan, serta label yang memenuhi selector. Satu PV hanya dapat terikat pada satu PVC pada satu waktu, sehingga claim yang lebih dulu cocok memenangkan volume tersebut. Diagram berikut merangkum alurnya:
Simulasi berikut menerapkan aturan pencocokan tersebut pada ketiga claim dan ketiga PV di atas. Kapasitas dibandingkan dengan mengonversi satuan Gi dan Mi, accessModes dibandingkan sebagai himpunan, dan selector dibandingkan terhadap label PV:
import yaml
def ukuran_gi(nilai):
# ubah "2Gi" atau "512Mi" menjadi angka GiB
angka = float(nilai[:-2])
return angka / 1024 if nilai.endswith("Mi") else angka
def cocok(pvc, pv):
permintaan = ukuran_gi(pvc["spec"]["resources"]["requests"]["storage"])
kapasitas = ukuran_gi(pv["spec"]["capacity"]["storage"])
if permintaan > kapasitas:
return f"kapasitas {pv['spec']['capacity']['storage']} kurang dari permintaan"
if not set(pvc["spec"]["accessModes"]) & set(pv["spec"]["accessModes"]):
return "accessModes tidak bertemu"
selektor = pvc["spec"].get("selector", {}).get("matchLabels", {})
label = pv["metadata"].get("labels", {})
for kunci, nilai in selektor.items():
if label.get(kunci) != nilai:
return f"label {kunci}={nilai} tidak ada pada PV"
return "cocok"
with open("pv.yaml") as f:
pv_semua = list(yaml.safe_load_all(f))
with open("pvc.yaml") as f:
pvc_semua = list(yaml.safe_load_all(f))
terikat = set()
for pvc in pvc_semua:
nama = pvc["metadata"]["name"]
dipilih = None
alasan = "tidak ada PV yang cocok"
for pv in pv_semua:
if pv["metadata"]["name"] in terikat:
continue
alasan = cocok(pvc, pv)
if alasan == "cocok":
dipilih = pv["metadata"]["name"]
break
if dipilih:
terikat.add(dipilih)
print(f"{nama} -> BOUND ke {dipilih}")
else:
print(f"{nama} -> PENDING ({alasan})")arsip-catatan -> BOUND ke pv-arsip-1
arsip-besar -> BOUND ke pv-arsip-2
laporan-bersama -> PENDING (label jenis=laporan tidak ada pada PV)Dua claim pertama berhasil terikat karena semua syaratnya terpenuhi, sedangkan laporan-bersama tetap Pending karena tidak ada PV berlabel jenis=laporan. Kluster yang sesungguhnya menampilkan keadaan yang sama pada kolom STATUS ketika kubectl get pvc dijalankan, dan claim yang Pending terus-menerus hampir selalu berarti pencocokan yang tidak menemukan pasangannya.
AccessModes dan artinya#
AccessModes menjelaskan cara penyimpanan dapat diakses dari sisi Node, bukan sisi Pod:
| Mode | Singkatan | Makna |
|---|---|---|
ReadWriteOnce | RWO | volume dapat di-mount untuk baca dan tulis oleh satu Node |
ReadOnlyMany | ROX | volume dapat di-mount hanya baca oleh banyak Node |
ReadWriteMany | RWX | volume dapat di-mount untuk baca dan tulis oleh banyak Node |
Singkatan RWO, ROX, dan RWX muncul pada kolom ACCESS MODES keluaran kubectl, sehingga ketiganya perlu dikenali. Satu nuansa yang sering terlewat adalah satuan ReadWriteOnce berupa Node dan bukan Pod, sehingga beberapa Pod yang dijadwalkan pada Node yang sama tetap dapat berbagi volume RWO. Mode tambahan ReadWriteOncePod mempersempit batasnya hingga satu Pod, dan ketersediaannya bergantung pada versi kluster.
Mode yang tertulis pada PV sifatnya deklaratif, yaitu penyedia penyimpanan yang menjamin kebenarannya, dan Kubernetes tidak menguji bahwa backend sungguh mendukung mode yang diiklankan. Manifest hostPath pada lab, misalnya, dapat memuat mode apa pun tanpa penolakan, sehingga kepercayaan pada mode menuntut kepercayaan pada penyedianya.
Siklus hidup dan kebijakan reclaim#
Umur hidup sebuah PV melewati empat fase, yaitu provisioning saat kapasitas dibuat, binding saat claim terikat, using selama Pod membaca dan menulisnya, serta reclaim setelah claim dilepas. Setelah pengguna menghapus PVC, volume tidak langsung hilang, dan nasibnya ditentukan persistentVolumeReclaimPolicy pada PV:
| Kebijakan | Perlakuan setelah claim dihapus |
|---|---|
Retain | PV tetap ada dengan status Released, datanya dipertahankan, dan pembersihannya dilakukan manual |
Delete | PV beserta penyimpanan di belakangnya dihapus |
Kebijakan Retain menjadi default pada PV statis, sehingga kehilangan data akibat salah hapus claim dapat dihindari dengan biaya pembersihan manual. Kebijakan Delete lebih praktis untuk penyimpanan sementara, tetapi perlu dipertimbangkan dengan sengaja karena penghapusan berjalan tanpa konfirmasi.
Ringkasan#
- PersistentVolume adalah kapasitas penyimpanan tingkat kluster, sedangkan PersistentVolumeClaim adalah permintaan kapasitas dari sisi namespace yang dirujuk Pod melalui
persistentVolumeClaim.claimName. - Binding terjadi ketika kapasitas, accessModes, dan label PV memenuhi permintaan claim, dan satu PV hanya terikat pada satu claim.
- AccessModes berupa RWO, ROX, dan RWX yang menyatakan akses dari sisi Node, sehingga satu volume RWO tetap dapat dibagikan antara beberapa Pod pada Node yang sama.
- Kebijakan reclaim menentukan nasib volume setelah claim dihapus, dengan
Retainmempertahankan data untuk pembersihan manual danDeletemenghapusnya.
Referensi#
- Persistent Volumes — Kubernetes — Dokumentasi konsep PV dan PVC, mencakup siklus hidup, accessModes, dan kebijakan reclaim.
- Configure a Pod to Use a PersistentVolume for Storage — Kubernetes — Panduan langkah demi langkah menghubungkan Pod ke penyimpanan persisten.