ข้ามไปยังเนื้อหา

PersistentVolume, Claim และ StorageClass

PersistentVolumeClaim คือ request ขอ storage ที่ Pod เอาไป mount ใช้ และจะ bind กับ PersistentVolume ที่เป็น storage ระดับ cluster ที่อยู่รอดข้าม Pod และตาม Pod ไปได้ข้าม node

emptyDir ตายไปพร้อม Pod ส่วน hostPath ผูกข้อมูลไว้กับ node เฉพาะตัว ทั้งสองแบบอยู่ไม่รอดถ้า Pod ถูก scheduler ย้ายไปรันบน hardware คนละตัว ซึ่ง scheduler มีสิทธิ์ทำแบบนั้นได้ตลอดเวลา workload แบบ stateful จริง ๆ (database, message queue หรืออะไรก็ตามที่ข้อมูลสำคัญ) ต้องการ storage ที่อยู่แยกอิสระจาก Pod หรือ node ตัวใดตัวหนึ่ง และให้ Pod ที่ถูกย้ายไปที่ใหม่ต่อกลับเข้าไปใช้ได้อีก

PersistentVolume (PV) คือ storage resource ระดับ cluster แนวคิดคล้าย Node ที่แทน compute capacity แต่ PV แทน storage capacity แทน admin ของ cluster provision PV แบบ static ล่วงหน้าได้ หรือจะให้ถูกสร้างแบบ dynamic ก็ได้ (อธิบายด้านล่าง)

PersistentVolumeClaim (PVC) คือ request ที่ user หรือ application ยื่นขอ “ขอ storage ขนาดเท่านี้ ด้วย access mode แบบนี้” Kubernetes จะ bind PVC เข้ากับ PV ที่ตรงกับ request นั้น ที่สำคัญคือ Pod reference แค่ PVC ไม่เคย reference PV ตรง ๆ Pod ไม่ต้องรู้หรือสนใจว่าไป bind กับ PV ตัวไหนจริง ๆ

apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-manual-10gi
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: manual
hostPath:
path: /mnt/data
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: manual
apiVersion: v1
kind: Pod
metadata:
name: db
spec:
containers:
- name: postgres
image: postgres:16
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumes:
- name: data
persistentVolumeClaim:
claimName: data-claim

PV ประกาศว่ารองรับ access mode ไหนบ้าง ส่วน PVC ก็ขอ mode ที่ต้องการ

  • ReadWriteOnce (RWO) — mount แบบ read-write ได้ แต่แค่ Pod บน node เดียวในเวลาเดียวกันเท่านั้น
  • ReadOnlyMany (ROX) — mount แบบ read-only ได้จากหลาย node พร้อมกัน
  • ReadWriteMany (RWX) — mount แบบ read-write ได้จากหลาย node พร้อมกัน (มีแค่บาง storage backend ที่รองรับ)
  • ReadWriteOncePod (RWOP) — mode ใหม่กว่าและเข้มกว่า volume ถูกจำกัดให้ใช้ได้แค่ Pod เดียว ทั้ง cluster ไม่ใช่แค่จำกัดที่ node เดียว ส่วน ReadWriteOnce ธรรมดายังเปิดให้หลาย Pod share volume กันได้ถ้าอยู่ node เดียวกัน ReadWriteOncePod มาปิดช่องว่างนี้เวลาต้องการ single-writer guarantee จริง ๆ

การ provision PV มือทีละตัวไม่ scale StorageClass อธิบาย storage class หนึ่งประเภท พร้อม provisioner ที่สร้าง storage นั้นได้ตามต้องการ พอ PVC reference StorageClass แทนที่จะ reference PV ที่มีอยู่แล้ว driver แบบ CSI (Container Storage Interface) จะ provision PV ที่ตรงกันให้อัตโนมัติ admin ไม่ต้องมานั่งสร้างล่วงหน้าเลย

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: ebs.csi.aws.com
parameters:
type: gp3
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: dynamic-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: fast-ssd
resources:
requests:
storage: 20Gi
Terminal window
# Watch a PVC bind to a dynamically provisioned PV
kubectl get pvc dynamic-claim -w

reclaim policy กำหนดว่า storage เบื้องหลังจะเป็นยังไงหลัง PVC ของตัวเองถูกลบ

  • Delete — PV และ storage เบื้องหลัง (disk จริง) ถูกลบไปพร้อม PVC เป็นค่า default ของ StorageClass แบบ dynamic provisioning ส่วนใหญ่
  • Retain — PV และข้อมูลยังอยู่ต่อหลัง PVC ถูกลบ admin เลยกู้คืนหรือเคลียร์ข้อมูลเองได้ก่อนที่ storage เบื้องหลังจะถูกปล่อยจริง ๆ
flowchart LR
  pod["Pod"] -->|mounts| pvc["PVC: dynamic-claim"]
  pvc -->|references| sc["StorageClass: fast-ssd"]
  sc -->|CSI driver provisions| pv["New PersistentVolume"]
  pv --> disk[("Underlying disk, e.g. an EBS volume")]
Dynamic provisioning: PVC สั่งให้ StorageClass กับ CSI driver สร้าง PV ใหม่
ตอน Pod ต้องการ persistent storage ต้อง reference อะไรใน spec.volumes
StorageClass ช่วยให้คุณไม่ต้องทำอะไร
ReadWriteOncePod จำกัดอะไรที่ ReadWriteOnce ธรรมดาไม่จำกัด
ความต่างเชิงปฏิบัติระหว่าง reclaim policy แบบ Delete กับ Retain คืออะไร