09
10-Day Kubernetes Track • Week 2

วันที่ 9: Persistent Storage Primitives (PV, PVC, SC)

คู่มือปฏิบัติการ • 20–30 นาทีต่อวัน • สัปดาห์ที่ 2

ยินดีต้อนรับสู่ วันที่ 9: Persistent Storage Primitives (PVs, PVCs และ StorageClasses)!

วันนี้เราจะมาเรียนรู้เรื่องการจัดการเนื้อที่จัดเก็บข้อมูลแบบถาวร (Persistent Storage) ใน Kubernetes ซึ่งช่วยให้ข้อมูลของแอปพลิเคชันยังคงอยู่ไม่สูญหาย แม้ตัว Pod จะถูกลบ สร้างใหม่ หรือย้ายไปรันบน Node อื่นก็ตามครับ

5-10m

ช่วงที่ 1: สรุปแนวคิดสถาปัตยกรรม

เข้าใจปัญหา Ephemeral Storage, บทบาทของ 3 เสาหลัก SC, PV, PVC, กลไก Dynamic Provisioning และการส่องสถานะ Bound บน Headlamp

15-20m

ช่วงที่ 2: การลงมือปฏิบัติจริง (5 ขั้นตอน)

ตรวจ StorageClass ในคลัสเตอร์, ร้องขอ PVC ขนาด 1Gi, ดูการจับคู่ Bound บน UI, เมานต์ดิสก์เข้า Pod และทดสอบความคงอยู่ของไฟล์ (Data Persistence)

1

สรุปแนวคิดและสถาปัตยกรรม (5–10 นาที)

3 เสาหลักของ Storage

โดยปกติคอนเทนเนอร์เป็น Ephemeral (ดับแล้วข้อมูลหาย) Kubernetes จึงแยกความรับผิดชอบออกเป็น:

• StorageClass (SC): ตัวกำหนดวิธีและไดรฟ์เวอร์สร้างดิสก์

• PV: เนื้อที่ดิสก์จริงระดับคลัสเตอร์

• PVC: ใบคำร้องขอพื้นที่จากนักพัฒนา

• แยกการจัดการโครงสร้างพื้นฐานออกจากแอป

Dynamic Provisioning

เมื่อเรายื่นขอ PersistentVolumeClaim (เช่น ขอพื้นที่ 1Gi แบบ ReadWriteOnce) ตัว StorageClass จะเรียก Provisioner จัดสรรดิสก์สร้างเป็น PersistentVolume ให้แบบอัตโนมัติ และเปลี่ยนสถานะเป็น Bound โดยแอดมินไม่ต้องมานั่งสร้างดิสก์ล่วงหน้า

• PVC Request → SC Provisioner → PV Auto-bound

Storage บน Headlamp UI

Headlamp มีหมวด Storage แยกเฉพาะ ประกอบด้วย PersistentVolumeClaims, PersistentVolumes และ StorageClasses ทำให้ตรวจสอบสถานะการ Bound, ขนาดพื้นที่, Access Modes และ Reclaim Policy ได้อย่างชัดเจนโดยไม่ต้องจำคำสั่งยาวๆ

• ดูความสัมพันธ์ระหว่าง PVC และ PV ได้ในคลิกเดียว
2

ขั้นตอนลงมือปฏิบัติจริง (15–20 นาที)

ติ๊กถูกเมื่อทำแต่ละขั้นตอนเสร็จ
Step 1 of 5

เปิด Terminal แล้วตรวจสอบ StorageClass เริ่มต้นที่มีอยู่ใน Cluster ของคุณ (เช่น standard หรือ k8s.io/minikube-hostpath):

Terminal Bash • Check StorageClasses
kubectl get storageclass
✓ ผลลัพธ์ที่คาดหวัง: คุณควรเห็น StorageClass อย่างน้อย 1 รายการที่มีเครื่องหมาย (default) เช่น standard (default) หรือ local-path (default) แสดงว่าคลัสเตอร์พร้อมทำ Dynamic Provisioning
Step 2 of 5

สร้างคำร้องขอจองพื้นที่จัดเก็บข้อมูลขนาด 1Gi ในโหมด ReadWriteOnce โดยตั้งชื่อว่า data-pvc:

Terminal Bash • Apply PVC Manifest
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
EOF
✓ ผลลัพธ์ที่คาดหวัง: Terminal จะแสดงข้อความ persistentvolumeclaim/data-pvc created และระบบจะเริ่มประสานงานกับ StorageClass เพื่อสร้าง PV จริงขึ้นมารองรับ
Step 3 of 5

เปิด Headlamp UI เพื่อตรวจสอบการจับคู่ผูกมัด (Binding) ของทรัพยากรจัดเก็บข้อมูล:

  1. เปิด Headlamp UI ขึ้นมา (ผ่าน http://localhost:8080 หรือ Headlamp Desktop)
  2. ไปที่เมนูด้านซ้ายในส่วน Storage > PersistentVolumeClaims
  3. คลิกเลือก data-pvc เพื่อสังเกตสถานะ: จะต้องขึ้นเป็น Bound พร้อมระบุชื่อของ Volume (PV) ที่ระบบสร้างให้อัตโนมัติ (เช่น pvc-xxxxxxxx-xxxx...)
  4. คลิกสลับไปที่เมนูด้านซ้ายในส่วน Storage > PersistentVolumes เพื่อดูคุณสมบัติของดิสก์จริง เช่น ขนาดความจุ 1Gi, Access Mode RWO และ Reclaim Policy
บนหน้าจอ Headlamp คุณสามารถคลิกสลับดูระหว่าง PVC และ PV ได้โดยตรง ช่วยให้เห็นความสัมพันธ์ของ Storage ได้ชัดเจนกว่าการพิมพ์ CLI แยกคำสั่ง
Step 4 of 5

สร้าง Pod ชื่อ storage-pod ที่นำ data-pvc มาเมานต์ไว้ที่โฟลเดอร์แสดงผลเว็บของ Nginx (/usr/share/nginx/html):

Terminal Bash • Apply Pod with VolumeMount
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: storage-pod
spec:
  containers:
    - name: web
      image: nginx:alpine
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: my-storage
  volumes:
    - name: my-storage
      persistentVolumeClaim:
        claimName: data-pvc
EOF
✓ ผลลัพธ์ที่คาดหวัง: Terminal จะแสดงข้อความ pod/storage-pod created และในหน้ารายละเอียด Pod บน Headlamp UI จะแสดงแถบ Volumes ที่ผูกติดกับ data-pvc อย่างสมบูรณ์
Step 5 of 5

พิสูจน์ว่าไฟล์ที่เขียนลงดิสก์ถาวรจะไม่สูญหาย แม้สั่งลบ Pod ทิ้งแล้วสร้างใหม่:

1. เขียนข้อมูลทดสอบลงในไฟล์ index.html บน Volume:
Terminal Bash • Write File
kubectl exec storage-pod -- sh -c "echo 'Headlamp Storage Test' > /usr/share/nginx/html/index.html"
2. สั่งลบ Pod ทิ้ง แล้วสร้างขึ้นมาใหม่ด้วยสเปกเดิม:
Terminal Bash • Recreate Pod
kubectl delete pod storage-pod
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: storage-pod
spec:
  containers:
    - name: web
      image: nginx:alpine
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: my-storage
  volumes:
    - name: my-storage
      persistentVolumeClaim:
        claimName: data-pvc
EOF
3. ตรวจสอบว่าเนื้อหาในไฟล์เดิมยังคงอยู่ครบถ้วน:
Terminal Bash • Read Persisted File
kubectl exec storage-pod -- cat /usr/share/nginx/html/index.html
✓ ผลลัพธ์ที่คาดหวัง: Terminal จะแสดงข้อความ Headlamp Storage Test แสดงว่าข้อมูลถูกเขียนลงดิสก์ถาวรจริง ไม่ได้เก็บไว้ในชั้น Ephemeral ของ Container
ภารกิจสำหรับวันที่ 9 (Day 9 Mission)

ลองทำตามขั้นตอนการสร้าง PVC และทดสอบ Data Persistence ดูนะครับ หากตรวจสอบสถานะการ Bound บน Headlamp UI และยืนยันว่าข้อมูลไม่หายเรียบร้อยแล้ว แจ้งได้เลยครับ!

ขั้นตอนถัดไป: เมื่อพร้อมแล้ว บอกผมได้เลยนะครับเพื่อไปต่อในวันสุดท้ายของสัปดาห์นี้ วันที่ 10: Headlamp Authentication & ServiceAccount Tokens ซึ่งเป็นบทสรุปสำคัญของ Level 1!
ข้อความแจ้งเตือน