ReadWriteOncePod กำหนด accessMode ใหม่ใน K8s v1.29

ถ้าจะกำหนดให้ PersistenceVolumeClaim ถูกอ่านเขียนได้จาก Pod เดียวเท่านั้น ... ReadWriteOncePod ทำได้

author image
drs

Technology evangelistic advocacy

Posted on 2023-12-19 00:01:47 +0700

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

ระบบที่ใช้ในการทดสอบ



ทดลอง ReadWriteOnce

  1. สร้าง PersistentVolumeClaim ชื่อว่า pvc-lh-rwo โดยไปขอ provision จาก Longhorn
  2. > 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
    
    
  3. แสดงรายการ node ใน K8s Cluster เพื่อเตรียมไว้กำหนด nodeName ในการสร้าง pod
  4. > 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
    
  5. สร้าง Pod ชื่อว่า pod1 ระบุให้สร้างที่ node ชื่อว่า node4-0 ระบุให้ใช้ PersistentVolumeClaim ชื่อว่า pvc-lh-rwo
  6. > 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 สามารถทำงานได้ปกติ

  7. สร้าง Pod ชื่อว่า pod2 ระบุให้สร้างที่ node ชื่อว่า node4-0 ระบุให้ใช้ PersistentVolumeClaim ชื่อว่า pvc-lh-rwo เหมือนกับ pod1
  8. > 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 สามารถทำงานได้ปกติ

  9. ทดสอบว่า pod1 และ pod2 ใช้ Storage ที่เดียวกัน โดยทดสอบให้ pod1 เขียนคำว่า Hello Pod ไปที่ไฟล์ /data/app.log และให้ pod2 อ่านข้อมูลจากไฟล์ /data/app.log
  10. > kubectl exec pod1 -- sh -c 'echo "Hello Pod" > /data/app.log'
    
    > kubectl exec pod2 -- sh -c 'cat /data/app.log'
    Hello Pod
    
  11. สร้าง pod99 แต่ระบุให้สร้างที่ node ชื่อว่า node4-1 ระบุให้ใช้ PersistentVolumeClaim ชื่อว่า pvc-lh-rwo
  12. > 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

  1. สร้าง PersistentVolumeClaim ชื่อว่า pvc-lh-rwop โดยไปขอ provision จาก Longhorn
  2. > 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
    
  3. สร้าง Pod ชื่อว่า pod1p ระบุให้สร้างที่ node ชื่อว่า node4-0 ระบุให้ใช้ PersistentVolumeClaim ชื่อว่า pvc-lh-rwop
  4. > 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 สามารถทำงานได้ปกติ

  5. สร้าง Pod ชื่อว่า pod2p ระบุให้สร้างที่ node ชื่อว่า node4-0 ระบุให้ใช้ PersistentVolumeClaim ชื่อว่า pvc-lh-rwop เหมือนกับ pod1p
  6. > 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:



cover

Share on

Tags

Human knowledge belongs to the world

a line from the movie "Antitrust"