PersistentVolume, Claim และ StorageClass
ไอเดียในหนึ่งประโยค
หัวข้อที่มีชื่อว่า “ไอเดียในหนึ่งประโยค”PersistentVolumeClaim คือ request ขอ storage ที่ Pod เอาไป mount ใช้ และจะ bind กับ PersistentVolume ที่เป็น storage ระดับ cluster ที่อยู่รอดข้าม Pod และตาม Pod ไปได้ข้าม node
ช่องว่างที่ emptyDir กับ hostPath ปิดไม่ได้
หัวข้อที่มีชื่อว่า “ช่องว่างที่ emptyDir กับ hostPath ปิดไม่ได้”emptyDir ตายไปพร้อม Pod ส่วน hostPath ผูกข้อมูลไว้กับ node เฉพาะตัว ทั้งสองแบบอยู่ไม่รอดถ้า Pod ถูก scheduler ย้ายไปรันบน hardware คนละตัว ซึ่ง scheduler มีสิทธิ์ทำแบบนั้นได้ตลอดเวลา workload แบบ stateful จริง ๆ (database, message queue หรืออะไรก็ตามที่ข้อมูลสำคัญ) ต้องการ storage ที่อยู่แยกอิสระจาก Pod หรือ node ตัวใดตัวหนึ่ง และให้ Pod ที่ถูกย้ายไปที่ใหม่ต่อกลับเข้าไปใช้ได้อีก
PersistentVolume กับ PersistentVolumeClaim
หัวข้อที่มีชื่อว่า “PersistentVolume กับ PersistentVolumeClaim”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: v1kind: PersistentVolumemetadata: name: pv-manual-10gispec: capacity: storage: 10Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: manual hostPath: path: /mnt/dataapiVersion: v1kind: PersistentVolumeClaimmetadata: name: data-claimspec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: manualapiVersion: v1kind: Podmetadata: name: dbspec: containers: - name: postgres image: postgres:18 volumeMounts: - name: data mountPath: /var/lib/postgresql/data volumes: - name: data persistentVolumeClaim: claimName: data-claimAccess mode
หัวข้อที่มีชื่อว่า “Access mode”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 จริง ๆ
Dynamic provisioning ด้วย StorageClass
หัวข้อที่มีชื่อว่า “Dynamic provisioning ด้วย StorageClass”การ 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/v1kind: StorageClassmetadata: name: fast-ssdprovisioner: ebs.csi.aws.comparameters: type: gp3reclaimPolicy: DeletevolumeBindingMode: WaitForFirstConsumerapiVersion: v1kind: PersistentVolumeClaimmetadata: name: dynamic-claimspec: accessModes: - ReadWriteOnce storageClassName: fast-ssd resources: requests: storage: 20Gi# Watch a PVC bind to a dynamically provisioned PVkubectl get pvc dynamic-claim -wReclaim policy ตัดสินชะตากรรมหลัง PVC หายไป
หัวข้อที่มีชื่อว่า “Reclaim policy ตัดสินชะตากรรมหลัง PVC หายไป”reclaim policy กำหนดว่า storage เบื้องหลังจะเป็นยังไงหลัง PVC ของตัวเองถูกลบ
Delete— PV และ storage เบื้องหลัง (disk จริง) ถูกลบไปพร้อม PVC เป็นค่า default ของ StorageClass แบบ dynamic provisioning ส่วนใหญ่Retain— PV และข้อมูลยังอยู่ต่อหลัง PVC ถูกลบ admin เลยกู้คืนหรือเคลียร์ข้อมูลเองได้ก่อนที่ storage เบื้องหลังจะถูกปล่อยจริง ๆ
volumeBindingMode: WaitForFirstConsumer ปล่อยให้ PVC ค้าง Pending ตั้งใจ
หัวข้อที่มีชื่อว่า “volumeBindingMode: WaitForFirstConsumer ปล่อยให้ PVC ค้าง Pending ตั้งใจ”volumeBindingMode ของ StorageClass คุมว่า PVC จะ bind เข้ากับ PV ตอนไหน Immediate (ค่า default แบบเดิม) จะ bind — และสำหรับ StorageClass แบบ dynamic ก็ provision ด้วย — ทันทีที่ PVC ถูกสร้าง ก่อนที่ Kubernetes จะรู้ด้วยซ้ำว่า Pod ไหนจะใช้หรือจะไปลงที่ node ไหน ส่วน WaitForFirstConsumer จะรอจนกว่า Pod ที่ reference PVC นี้มีอยู่จริงและกำลังถูก schedule ก่อน provisioner ถึงจะสร้าง volume ที่ตรงกับ node ที่ scheduler เลือกจริง ๆ ได้ (storage ที่ผูกกับ topology เช่น local disk หรือ zone เฉพาะ ต้องพึ่งพฤติกรรมนี้ ไม่งั้น PVC อาจ bind กับ storage ใน zone ที่ Pod ไปไม่ถึงเลย)
StorageClass standard ของ kind เองก็มากับ WaitForFirstConsumer อยู่แล้ว — พิสูจน์จริงบน cluster จริง (kind create cluster, Kubernetes 1.37.0, kind 0.33):
$ kubectl get storageclass -o wideNAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGEstandard (default) rancher.io/local-path Delete WaitForFirstConsumer false 22mสร้าง PVC เข้ากับ class นี้โดยยังไม่มี Pod ปล่อยให้ PVC ค้าง Pending จริง ๆ และ event จริงก็บอกเหตุผลตรง ๆ:
apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: wffc-demoprovisioner: rancher.io/local-pathvolumeBindingMode: WaitForFirstConsumerreclaimPolicy: Delete---apiVersion: v1kind: PersistentVolumeClaimmetadata: name: wffc-pvcspec: accessModes: ['ReadWriteOnce'] storageClassName: wffc-demo resources: requests: storage: 64Mi$ kubectl apply -f wffc-demo.yamlstorageclass.storage.k8s.io/wffc-demo createdpersistentvolumeclaim/wffc-pvc created
$ kubectl get pvc wffc-pvcNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGEwffc-pvc Pending wffc-demo 0s
$ kubectl describe pvc wffc-pvc | tail -4Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal WaitForFirstConsumer 8s (x2 over 8s) persistentvolume-controller waiting for first consumer to be created before bindingพอมี Pod ที่ mount wffc-pvc ถูกสร้างขึ้น การ bind (และสำหรับ dynamic class ก็ provision ด้วย) จะเกิดขึ้นทันที:
$ kubectl apply -f wffc-pod.yamlpod/wffc-consumer created
$ kubectl get pvc wffc-pvcNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGEwffc-pvc Bound pvc-1cd1cd2c-02c9-464b-a42a-33e01ef819c9 64Mi RWO wffc-demo 17sPVC ที่ Pending อยู่บน StorageClass แบบ WaitForFirstConsumer ไม่ได้แปลว่าค้าง — มันทำงานตามที่ออกแบบไว้เป๊ะ ๆ และจะ Pending ต่อไปเรื่อย ๆ จนกว่าจะมี Pod มา reference จริง
allowVolumeExpansion: ขยาย PVC ทีหลังได้
หัวข้อที่มีชื่อว่า “allowVolumeExpansion: ขยาย PVC ทีหลังได้”allowVolumeExpansion: true บน StorageClass ทำให้ PVC ที่ bind แล้ว resize เพิ่มขนาดได้ทีหลังโดยแก้ spec.resources.requests.storage — โดยไม่ต้องลบสร้าง PVC ใหม่ (ลดขนาดไม่รองรับ ทำได้แค่ขยายขึ้นอย่างเดียว) ค่า default คือ false ตามที่ output ของ standard ด้านบนแสดงให้เห็นแล้วบน kind cluster นี้
apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: expand-demoprovisioner: rancher.io/local-pathvolumeBindingMode: WaitForFirstConsumerallowVolumeExpansion: truereclaimPolicy: Delete---apiVersion: v1kind: PersistentVolumeClaimmetadata: name: expand-pvcspec: accessModes: ['ReadWriteOnce'] storageClassName: expand-demo resources: requests: storage: 64Mi$ kubectl apply -f expand-demo.yamlstorageclass.storage.k8s.io/expand-demo createdpersistentvolumeclaim/expand-pvc created
$ kubectl patch pvc expand-pvc -p '{"spec":{"resources":{"requests":{"storage":"128Mi"}}}}'persistentvolumeclaim/expand-pvc patched
$ kubectl get pvc expand-pvcNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGEexpand-pvc Bound pvc-1f3fa7ee-25c9-4262-9091-ab17913f3f83 64Mi RWO expand-demo 39m
$ kubectl describe pvc expand-pvc | tail -3Events: ... Normal ExternalExpanding 5s volume_expand waiting for an external controller to expand this PVCspec.requests.storage ยอมรับค่า 128Mi (API server ยอม edit เพราะ allowVolumeExpansion: true) แต่ status.capacity ยังคงอยู่ที่ 64Mi และไม่เคยมี condition FileSystemResizePending โผล่มาเลย — เหตุผลจริงที่พิสูจน์แล้วอยู่ใน event ตรงนั้นเลย: rancher.io/local-path (provisioner default ของ kind เอง) ไม่มี external-resizer controller ลงทะเบียนไว้ คำขอ resize เลยรอ controller ภายนอกที่ไม่มีอยู่จริงบน cluster นี้ นี่คือ finding จริงที่มีประโยชน์ ไม่ใช่สมมติฐาน: allowVolumeExpansion: true จำเป็นแต่ไม่พอ — provisioner ต้องมี resize sidecar/controller ที่ตรงกันติดตั้งอยู่จริงด้วย ตรงตาม เอกสาร Kubernetes เรื่อง CSI volume expansion และ CSI driver ของ cloud (ที่มี resizer controller ของตัวเองมาด้วย) จะพฤติกรรมต่างจากนี้
Reclaim policy พิสูจน์จริง: Retain เก็บ disk ไว้ Delete ไม่เก็บ
หัวข้อที่มีชื่อว่า “Reclaim policy พิสูจน์จริง: Retain เก็บ disk ไว้ Delete ไม่เก็บ”apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: retain-demoprovisioner: rancher.io/local-pathvolumeBindingMode: WaitForFirstConsumerreclaimPolicy: Retain---apiVersion: v1kind: PersistentVolumeClaimmetadata: name: retain-pvcspec: accessModes: ['ReadWriteOnce'] storageClassName: retain-demo resources: requests: storage: 32Mi$ kubectl apply -f reclaim-demo.yamlstorageclass.storage.k8s.io/retain-demo createdpersistentvolumeclaim/retain-pvc createdpod/retain-consumer created
$ kubectl get pvc retain-pvc -o wideNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGEretain-pvc Bound pvc-1eea386b-988f-4a79-a99f-d07812b445c1 32Mi RWO retain-demo 8s
$ kubectl delete pod retain-consumer --wait=truepod "retain-consumer" deleted
$ kubectl delete pvc retain-pvcpersistentvolumeclaim "retain-pvc" deleted
$ kubectl get pv pvc-1eea386b-988f-4a79-a99f-d07812b445c1NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS AGEpvc-1eea386b-988f-4a79-a99f-d07812b445c1 32Mi RWO Retain Released default/retain-pvc retain-demo 41sหลัง Pod กับ PVC หายไปทั้งคู่ PV ยังอยู่ — STATUS: Released ไม่ถูกลบ — ตรงตามพฤติกรรม reclaim policy “Retain” เป๊ะ: disk อยู่รอด แต่ก็ใช้ต่อทันทีไม่ได้อัตโนมัติเหมือนกัน (PVC ใหม่จะไม่ bind กับ PV ที่ Released จนกว่า admin จะเคลียร์ claimRef หรือลบสร้างใหม่) sequence เดียวกันกับ reclaimPolicy: Delete (default ของ class standard เองตามที่แสดงก่อนหน้า) จะลบทั้ง PV และ directory เบื้องหลังให้อัตโนมัติทันทีที่ PVC หายไป — ไม่มีสถานะ Released เลย object หายไปตรง ๆ
VolumeSnapshot กับ VolumeSnapshotClass
หัวข้อที่มีชื่อว่า “VolumeSnapshot กับ VolumeSnapshotClass”VolumeSnapshot คือการขอให้ CSI driver capture ข้อมูลของ PVC ณ ช่วงเวลาหนึ่ง ส่วน VolumeSnapshotClass ก็เหมือน StorageClass เวอร์ชัน snapshot — ระบุ CSI driver ที่รองรับ snapshot (driver:) กับ deletion policy การ restore คือสร้าง PVC ใหม่ ที่ spec.dataSource ชี้ไปที่ VolumeSnapshot แทนที่จะขอ storage เปล่า ๆ:
# k8s/persistent-volumes-claims-and-storage-classes/snapshot-demo.yaml — @expect-error no snapshot-capable CSI driver was installed on this cluster before the host became unresponsive; verified with --dry-run=server against verify-k8s insteadapiVersion: snapshot.storage.k8s.io/v1kind: VolumeSnapshotClassmetadata: name: csi-hostpath-snapclassdriver: hostpath.csi.k8s.iodeletionPolicy: Delete---apiVersion: snapshot.storage.k8s.io/v1kind: VolumeSnapshotmetadata: name: data-snapshotspec: volumeSnapshotClassName: csi-hostpath-snapclass source: persistentVolumeClaimName: expand-pvc---apiVersion: v1kind: PersistentVolumeClaimmetadata: name: restored-pvcspec: accessModes: ['ReadWriteOnce'] storageClassName: expand-demo dataSource: name: data-snapshot kind: VolumeSnapshot apiGroup: snapshot.storage.k8s.io resources: requests: storage: 64Miสิ่งที่รันจริง: CRD client ของ external-snapshotter (VolumeSnapshotClass/VolumeSnapshotContent/VolumeSnapshot, v8.6.0 — เวอร์ชันเดียวกับที่ harness คอร์สติดตั้งไว้บน verify-k8s) กับ Deployment snapshot-controller ติดตั้งสำเร็จบน cluster storage-net ของโมดูลนี้เอง (kubectl apply -k external-snapshotter/client/config/crd กับ .../deploy/kubernetes/snapshot-controller ทั้งคู่จาก release ต้นทาง kubernetes-csi/external-snapshotter v8.6.0) ส่วนการติดตั้ง CSI hostpath driver เอง (kubernetes-csi/csi-driver-host-path v1.18.0) — ตัวที่ implement snapshot จริง ๆ — คือจุดที่มีปัญหา: เครื่องที่ใช้ร่วมกันซึ่งรัน kind cluster ของหลาย agent พร้อมกันในคอร์สนี้ ตกอยู่ในสภาพ CPU ขาดแคลนอย่างหนักนานพอสมควรในเซสชันนี้ (uptime แสดง load average ค้างที่ 20–30, docker stats แสดง CPU 50–95% ต่อ container ของแต่ละ node ยืนยันแล้วว่าเป็นปัญหาระดับเครื่องทั้งเครื่องเพราะ cluster verify-k8s ที่ใช้ร่วมกันแยกต่างหาก ก็ fail กับ kubectl get ns แบบพื้นฐานเดียวกันในช่วงเวลาเดียวกัน) driver เลยไม่เคยขึ้นมา running ก่อนที่หน้าต่างเวลาจะปิดลง จนพิสูจน์ snapshot-and-restore จริงแบบ end to end ไม่ได้ รูปแบบ object ด้านบนตรวจแล้วว่าถูกต้องด้วย kubectl apply --dry-run=server (ตรวจ OpenAPI + admission เต็มรูปแบบ) กับ verify-k8s ส่วนพฤติกรรม end-to-end เรื่องการรักษาข้อมูลอ้างอิงตาม เอกสาร Kubernetes CSI volume snapshots ไม่ได้พิสูจน์ซ้ำเองในบทนี้
อ่านโค้ดที่ AI เขียน
หัวข้อที่มีชื่อว่า “อ่านโค้ดที่ AI เขียน”ตอนรีวิว manifest ของ PV/PVC/StorageClass ที่ AI สร้าง ให้เช็ค
- PVC ที่ไม่มี
storageClassNameบน cluster ที่ไม่มี default StorageClass — จะค้างPendingตลอดไป มี event จริงที่พลาดดูง่ายมาก (no persistent volumes available for this claim and no storage class is set) ไม่มี error โผล่ในkubectl getเลย - PVC ที่
Pendingแล้วเข้าใจว่าพัง ทั้งที่ StorageClass เป็นWaitForFirstConsumer— พิสูจน์ด้านบนแล้วว่านี่คือพฤติกรรมที่คาดไว้จนกว่าจะมี Pod allowVolumeExpansionไม่ได้ตั้ง (default เป็นfalse) บน StorageClass ที่ผู้เขียนคาดว่าจะ resize ได้ทีหลัง- comment ที่บอกว่า
reclaimPolicy: Delete“ปลอดภัย” เพราะ “Kubernetes จะเคลียร์ให้เอง” — พิสูจน์ด้านบนด้วยการเทียบกับRetainแล้วว่าDeleteแปลว่า disk เบื้องหลังหายไปทันทีที่ PVC หายไป ซึ่งตรงข้ามกับ “ปลอดภัย” เลยสำหรับอะไรก็ตามที่ผู้เขียนตั้งใจจะเก็บไว้
🐛 หา bug ในโค้ดนี้
apiVersion: v1kind: PersistentVolumeClaimmetadata:name: db-dataspec:accessModes: - ReadWriteOnceresources: requests: storage: 20Gi---apiVersion: v1kind: Podmetadata:name: dbspec:containers: - name: postgres image: postgres:18 volumeMounts: - name: data mountPath: /var/lib/postgresql/datavolumes: - name: data persistentVolumeClaim: claimName: db-dataเฉลย
PVC นี้ไม่ได้ตั้ง storageClassName เลย บน cluster ที่มี default StorageClass ก็เป็นทางลัดที่ใช้ได้ปกติ — แต่บน cluster ที่ไม่มี default (พิสูจน์ด้านบนแล้วว่า class standard ของ kind มีเพราะ kind ติดตั้งให้เอง cluster ที่สร้างเองหรือตัดทอนมาอาจไม่มีเลย) PVC นี้ไม่มีทาง provision แบบ dynamic ได้ และไม่มี PV แบบ static ตัวไหนตรงกันพอดี เลยค้าง Pending ตลอดไป Pod ที่ reference มันก็ Pending ตามไปด้วย (FailedScheduling, unbound PVC) โดยไม่มีอะไรใน status ของสองตัวนี้ชี้ตรง ๆ ว่า “ไม่มี default StorageClass” คือ root cause — ต้องรู้เองว่าต้องไปรัน kubectl get storageclass แล้วเช็คหา (default) ต่อท้ายชื่อ class ทางแก้คือ ตั้ง storageClassName เองตรง ๆ หรือไม่ก็ยืนยันก่อนว่า cluster ปลายทางมี default StorageClass จริงก่อนจะปล่อย manifest ที่ไม่ได้ตั้งค่านี้ออกไป
Mental Model
หัวข้อที่มีชื่อว่า “Mental Model”PV/PVC/StorageClass คือสัญญาที่แยกจากกันเป็นชิ้น ๆ ไม่ใช่ object เดียวที่มีสามชื่อ StorageClass สัญญาว่าจะให้ storage หนึ่งประเภทพร้อมวิธี provision PVC สัญญาว่า “ขอ storage เท่านี้ access mode แบบนี้ bind ในจังหวะที่ถูกต้อง” และ PV คือผลลัพธ์รูปธรรมที่ได้ volumeBindingMode, allowVolumeExpansion, reclaimPolicy ล้วนเป็นปุ่มปรับว่า เมื่อไหร่ และ เข้มงวดแค่ไหน สัญญานั้นถูกทำตาม — ไม่ได้เปลี่ยนว่า PV หรือ PVC คืออะไรโดยพื้นฐาน
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ทางเลือก | ข้อดี | ต้นทุน |
|---|---|---|
volumeBindingMode: WaitForFirstConsumer | provisioner เลือก storage ที่ตรงกับที่ Pod ไปลงจริงได้ (พิสูจน์ด้านบน) | PVC ดูเหมือนค้าง Pending จนกว่าจะมี Pod — คนที่ไม่รู้จะคิดว่าพัง |
volumeBindingMode: Immediate | PVC bind ทันที ไม่ต้องรอ Pod | อาจ bind กับ PV/zone ที่ constraint การ schedule ของ Pod ที่จะมาทีหลังไปไม่ถึง |
reclaimPolicy: Delete | ไม่มี storage เหลือค้างหลัง cleanup | ลบ PVC พลาดครั้งเดียว disk เบื้องหลังหายตาม พิสูจน์ด้านบนด้วยการเทียบกับ Retain |
reclaimPolicy: Retain | กู้ข้อมูลคืนได้หลัง PVC ถูกลบ | ต้อง cleanup มือโดย admin หรือ storage จะค้างสะสมเงียบ ๆ |
| restore จาก VolumeSnapshot | กู้คืนแบบ point-in-time โดยไม่ต้องมี backup tool แยก | ขึ้นอยู่กับว่า CSI driver รองรับ snapshot จริงหรือเปล่าทั้งหมด ไม่มีอะไรใน API ห้ามไม่ให้ประกาศ snapshot กับ driver ที่ไม่รองรับ |
ความเข้าใจผิดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ความเข้าใจผิดที่พบบ่อย”- “PVC ที่
Pendingแปลว่าพังเสมอ” พิสูจน์ด้านบนแล้ว — บน StorageClass แบบWaitForFirstConsumerการPendingตอนยังไม่มี Pod คือสถานะที่ถูกต้องตามที่ออกแบบไว้ - “
allowVolumeExpansionเปิดเป็น default” พิสูจน์ด้านบนแล้วว่า classstandardของ kind เองมากับค่าfalseต้องตั้งเปิดเองชัด ๆ - “ลบ PVC แล้วข้อมูลเบื้องหลังหายเสมอ” จริงแค่กรณี
reclaimPolicy: Deleteเท่านั้น —Retain(เทียบด้านบน) เก็บ PV กับ disk ไว้ตั้งใจ - “มี object VolumeSnapshot แปลว่า snapshot ถูกสร้างจริงแล้ว” API ยอมรับ
VolumeSnapshotที่ reference StorageClass/driver คู่ไหนก็ได้ ส่วนจะมีอะไรเกิดขึ้นจริงหรือเปล่าขึ้นอยู่กับว่ามี CSI driver ที่รองรับ snapshot ติดตั้งอยู่จริงไหม ทั้งหมด ซึ่ง object เองบอกไม่ได้เลย
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")]