ว่าด้วยเรื่อง 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

