ว่าด้วยเรื่อง Access Modes ใน PersistentVolume
ข้อมูลใน Container ภายใน Pod จะถูกลบไปพร้อมกับ Pod ดังนั้น Volume จึงเข้ามามีบทบาทเพื่อแก้ปัญหานี้ เราอาจจะระบุข้อมูลของ Stroage ที่เราจะใช้งานเข้าไปใน Pod เลยก็ได้ หรือว่า จะระบุเป็น PersistentVolumeClaim แล้ว ให้ PersistentVolumeClaim ระบุ Storage ที่ใช้งานผ่าน PersistentVolume
ใน Kubernetes ก่อน v1.29 คุณสมบัติของ PersistentVolume ที่เราระบุได้ ให้สอดคล้องกับคุณสมบัติทางเทคนิคของ Storage ก็คือ Access Mode ระบุได้ 3 ประเภท
- ReadWriteOnce เป็น volume ที่สามารถใช้งานที่อ่านเขียนได้จาก 1 node เท่านั้น การเข้าถึงแบบ ReadWriteOnce ก็ยังสามารถเข้าถึงได้จาก pod หลาย pod ที่ทำงานบน node เดียวกัน
- ReadOnlyMany เป็น volume ที่สามารถอ่านได้อย่างเดียวจากหลาย node
- ReadWriteMany เป็น volume ที่สามารถอ่านเขียนได้จากหลาย node
ระบบที่ใช้ในการทดสอบ
- Platform: Kubernetes v1.29
- Storage: Longhorn
ทดลอง ReadWriteOnce
- สร้าง PersistentVolumeClaim ชื่อว่า pvc-lh-rwo โดยไปขอ provision จาก Longhorn
- แสดงรายการ node ใน K8s Cluster เพื่อเตรียมไว้กำหนด nodeName ในการสร้าง pod
- สร้าง Pod ชื่อว่า pod1 ระบุให้สร้างที่ node ชื่อว่า node4-0 ระบุให้ใช้ PersistentVolumeClaim ชื่อว่า pvc-lh-rwo
- สร้าง Pod ชื่อว่า pod2 ระบุให้สร้างที่ node ชื่อว่า node4-0 ระบุให้ใช้ PersistentVolumeClaim ชื่อว่า pvc-lh-rwo เหมือนกับ pod1
- ทดสอบว่า pod1 และ pod2 ใช้ Storage ที่เดียวกัน โดยทดสอบให้ pod1 เขียนคำว่า Hello Pod ไปที่ไฟล์ /data/app.log และให้ pod2 อ่านข้อมูลจากไฟล์ /data/app.log
- สร้าง pod99 แต่ระบุให้สร้างที่ node ชื่อว่า node4-1 ระบุให้ใช้ PersistentVolumeClaim ชื่อว่า pvc-lh-rwo
> cat > pvc-rwo.yaml <<EOF apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-lh-rwo spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: 2G EOF > kubectl apply -f pvc-rwo.yaml persistentvolumeclaim/pvc-lh-rwo created > kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE pvc-lh-rwo Bound pvc-2c4eb15a-1659-474c-9c29-8900ff4418f8 1908Mi RWO longhorn <unset> 8s
> kubectl get nodes NAME STATUS ROLES AGE VERSION cp4-0 Ready control-plane 81m v1.29.0 node4-0 Ready <none> 80m v1.29.0 node4-1 Ready <none> 80m v1.29.0 node4-2 Ready <none> 80m v1.29.0
> cat > pod1.yaml <<EOF apiVersion: v1 kind: Pod metadata: name: pod1 namespace: default spec: nodeName: node4-0 restartPolicy: Always containers: - name: c1 image: nginx:bookworm volumeMounts: - name: data-vol mountPath: /data volumes: - name: data-vol persistentVolumeClaim: claimName: pvc-lh-rwo EOF > kubectl apply -f pod1.yaml pod/pod1 created > kubectl get pods NAME READY STATUS RESTARTS AGE pod1 1/1 Running 0 103s
พบว่า pod1 สามารถทำงานได้ปกติ
> cat > pod2.yaml <<EOF apiVersion: v1 kind: Pod metadata: name: pod2 namespace: default spec: nodeName: node4-0 restartPolicy: Always containers: - name: c1 image: nginx:bookworm volumeMounts: - name: data-vol mountPath: /data volumes: - name: data-vol persistentVolumeClaim: claimName: pvc-lh-rwo EOF > kubectl apply -f pod2.yaml pod/pod2 created > kubectl get pods NAME READY STATUS RESTARTS AGE pod1 1/1 Running 0 4m58s pod2 1/1 Running 0 8s
พบว่า pod1 และ pod2 สามารถทำงานได้ปกติ
> kubectl exec pod1 -- sh -c 'echo "Hello Pod" > /data/app.log' > kubectl exec pod2 -- sh -c 'cat /data/app.log' Hello Pod
> cat > pod99.yaml <<EOF apiVersion: v1 kind: Pod metadata: name: pod99 namespace: default spec: nodeName: node4-1 restartPolicy: Always containers: - name: c1 image: nginx:bookworm volumeMounts: - name: data-vol mountPath: /data volumes: - name: data-vol persistentVolumeClaim: claimName: pvc-lh-rwo EOF > kubectl apply -f pod99.yaml pod/pod99 created > kubectl get pods NAME READY STATUS RESTARTS AGE pod1 1/1 Running 0 19m pod2 1/1 Running 0 14m pod99 0/1 ContainerCreating 0 15s > kubectl describe pod pod99 Name: pod99 Namespace: default Priority: 0 Service Account: default Node: node4-1/192.168.254.47 [... truncated output ...] Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedAttachVolume 39s attachdetach-controller Multi-Attach error for volume "pvc-2c4eb15a-1659-474c-9c29-8900ff4418f8" Volume is already used by pod(s) pod1, pod2
Kubernetes v1.29 เพิ่ม Access Modes แบบ ReadWriteOncePod
ใน Kubernetes v1.22 มีการเพิ่ม Access Mode ของ PersistentVolume อีก 1 ประเภท ก็คือ ReadWriteOncePod สำหรับ Storage ที่รองรับ CSI - Container Storage Interface ให้อยู่ในสถานะ Alpha เพื่อให้ PersistentVolumeClaim ที่ต้องการ access mode นี้ คือต้องการจำกัดการเข้าถึง storage ได้จาก pod ด้วยเท่านั้น มั่นใจได้ว่า จะไม่มี pod อื่น ๆ สามารถเข้าถึง storage จาก PersistentVolume ตัวนี้ได้อีกเลย และใน Kubernetes v1.29 ได้ประกาศให้ คุณสมบัติ ReadWriteOncePod อยู่ในสถานะ Stable พร้อมใช้งานใน production แล้ว (สถานะ Alpha,Beta และ Stable คืออะไร)
ทดลอง ReadWriteOncePod
- สร้าง PersistentVolumeClaim ชื่อว่า pvc-lh-rwop โดยไปขอ provision จาก Longhorn
- สร้าง Pod ชื่อว่า pod1p ระบุให้สร้างที่ node ชื่อว่า node4-0 ระบุให้ใช้ PersistentVolumeClaim ชื่อว่า pvc-lh-rwop
- สร้าง Pod ชื่อว่า pod2p ระบุให้สร้างที่ node ชื่อว่า node4-0 ระบุให้ใช้ PersistentVolumeClaim ชื่อว่า pvc-lh-rwop เหมือนกับ pod1p
> cat > pvc-rwop.yaml <<EOF apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-lh-rwop spec: accessModes: - ReadWriteOncePod storageClassName: longhorn resources: requests: storage: 2G EOF > kubectl apply -f pvc-rwop.yaml persistentvolumeclaim/pvc-lh-rwop created > kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE pvc-lh-rwop Bound pvc-b8410a74-39f8-4617-ad96-36c6799ed2ef 1908Mi RWOP longhorn <unset> 10s
> cat > pod1p.yaml <<EOF apiVersion: v1 kind: Pod metadata: name: pod1p namespace: default spec: nodeName: node4-0 restartPolicy: Always containers: - name: c1 image: nginx:bookworm volumeMounts: - name: data-vol mountPath: /data volumes: - name: data-vol persistentVolumeClaim: claimName: pvc-lh-rwop EOF > kubectl apply -f pod1p.yaml pod/pod1p created > kubectl get pods NAME READY STATUS RESTARTS AGE pod1p 1/1 Running 0 21s
พบว่า pod1p สามารถทำงานได้ปกติ
> cat > pod2p.yaml <<EOF apiVersion: v1 kind: Pod metadata: name: pod2p namespace: default spec: nodeName: node4-0 restartPolicy: Always containers: - name: c1 image: nginx:bookworm volumeMounts: - name: data-vol mountPath: /data volumes: - name: data-vol persistentVolumeClaim: claimName: pvc-lh-rwop EOF > kubectl apply -f pod2p.yaml pod/pod2p created > kubectl get pods NAME READY STATUS RESTARTS AGE pod1p 1/1 Running 0 5m48s pod2p 0/1 ContainerCreating 0 113s > kubectl describe pod pod2 Name: pod2p Namespace: default Priority: 0 Service Account: default Node: node4-0/192.168.254.46 Start Time: Wed, 20 Dec 2023 23:49:11 +0700 [... truncated output ...] Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedMount 12s (x9 over 2m20s) kubelet MountVolume.SetUp failed for volume "pvc-b8410a74-39f8-4617-ad96-36c6799ed2ef" : volume uses the ReadWriteOncePod access mode and is already in use by another pod
พบว่า ไม่สามารถสร้าง pod2p ได้ และตรวจสอบในรายละเอียด พบข้อความที่ว่า ไม่สามารถใช้งาน pvc ได้เพราะมีการกำหนด access mode ให้เป็น ReadWriteOncePod และมี pod อื่นใช้งาน volume นี้อยู่แล้ว
Reference:
- Kubernetes v1.29: Mandala
- Kubernetes 1.27: Single Pod Access Mode for PersistentVolumes Graduates to Beta
- Introducing Single Pod Access Mode for PersistentVolumes