iT邦幫忙

2023 iThome 鐵人賽

DAY 22
0
DevOps

第一次參賽就學 Kubernetes系列 第 22

[Day 22] Persistent Volumes 與 Persistent Volume Claims

  • 分享至 

  • xImage
  •  

Volume 是在 Docker 中用來儲存資料的元件。在容器的世界中,應用程式中的資料會隨著容器的刪除而跟著消失,故需要透過 Volume 的方式保存這些資料。

除了讓資料不會跟著容器刪除消失外,Volume 可以很輕易地去做到在不同容器上共享資料。

同樣的在 k8s 中,pods 中的資料於刪除時也會跟著消失。這時就需要談到 Persistent Volume 以及 PersistentVolumeClaim 這兩個角色。


Volume

在 k8s 中有很多不同類型的 Volume,這邊介紹 hostPath(實務盡量避免不使用)、Persistent Volume Claim。

hostPath

因 hostPath 是將資料儲存在 worker node 上,但此做法存在許多安全性問題,因此「官方不建議使用」。

來看以下 pod 範例。

apiVersion: v1 
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: test-container
    image: registry.k8s.io/test-webserver
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      path: /data
      type: DirectoryOrCreate

以上是在容器中使用 log-volume,將 /log 資料儲存在 node 上的 /var/log/webapp 位址。

  • volumeMountsmountPath 為需要掛載的路徑,name 為 volume 名稱
  • volumes:該 pod 使用哪些 volumes,hostPath 為使用的類型
    • path:掛載到哪個路徑
    • typeDirectoryOrCreate 若目錄不存在會自動建立,其他類型可以參考

Persistent Volume Claim

Persistent Volume(簡稱為PV)是在叢集中使用的 volume,由管理者建立讓使用者(應用程式)們在叢集上部署程式時使用。應用程式可以請求一個 volume,稱之為 Persistent Volume Claim(簡稱PVC)。

在 k8s 中:

  • 管理者建立 Persistent Volume
  • 使用者建立 Persistent Volume Claim 來使用 Persistent Volume

如何使用 PVC

以下是一個 PVC 範例。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 500Mi # 需求為 500MB
  volumeMode: Filesystem

以下說明:

  • accessModes:存取該 volume 的模式,在此為 ReadWriteOnce 即資料只能被一個 node 讀取及寫入的動作
  • resources:描述資源需求,storage: 500Mi 即需要 500MB 的空間

以下是一個 PV 範例。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv
spec:
  capacity:
    storage: 2Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /tmp/data # 儲存在 node 上的位址

以下說明:

  • capacitystorage 定義要存 2G 資料

當 PVC 建立後,k8s 會根據以上設定檔中的請求,與當前存在叢集中的 persistent volume 設定參數來比對,將PV 跟 PVC 做綁定,意即一個 PVC 會配對到一個 PV。

也就是說:

  1. k8s 會尋找 PV 的容量是否符合 PVC 的要求,例如:空間的容量
  2. 再針對 PVC 上的 accessModesvolumeMode 尋找合適的 PV。

若當下有兩個 PV 符合 PVC 的請求時,可以另外使用 label selector (matchLabels) 去篩選 PVC 要配到哪個 PV。

一但 PVC 建立後沒有相符的選擇,例如因容量不合(需求 500MB、PV 定義 2GB),但因沒有其他更好的選擇,k8s 會進行 binding。但如果當下沒有 PV 可以提供給 PVC,則 PVC 會處於 pending state 等待管理者建立 PV。

範例

這邊使用 k8s 官網的範例。

  1. 建立一個 index.html,查看後並離開 ssh。
minikube ssh

docker@minikube:~$ sudo mkdir /mnt/data
docker@minikube:~$ sudo sh -c "echo 'Hello from Kubernetes storage' > /mnt/data/index.html"
docker@minikube:~$ cat /mnt/data/index.html
Hello from Kubernetes storage
  1. 建立 PersistentVolume,在這個練習是使用 hostPath,但在實務上不建議使用。
vi po-volume.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: task-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"

建立 persistent volume。

kubectl apply -f po-volume.yaml
persistentvolume/task-pv-volume created

STATUS 仍為 Available 意思是還沒指定到 PVC 上。

kubectl get pv task-pv-volume
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
task-pv-volume   10Gi       RWO            Retain           Available           manual   manual         54s
  1. 建立 PVC。
vi pv-claim.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: task-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi

建立 PVC。

kubectl apply -f pv-claim.yaml

persistentvolumeclaim/task-pv-claim created

若 k8s 找到符合的 PV,會將該 PVC 綁定到 PV 上。STATUSBound 代表已綁定 PV。

kubectl get pvc task-pv-claim
NAME            STATUS   VOLUME           CAPACITY   ACCESS MODES   STORAGECLASS   AGE
task-pv-claim   Bound    task-pv-volume   10Gi       RWO            manual         2m19s

另外在 PV 上 CLAIM 可以看到綁定的 PVC 為 default/task-pv-claim

kubectl get pv task-pv-volume
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                   STORAGECLASS   REASON   AGE
task-pv-volume   10Gi       RWO            Retain           Bound    default/task-pv-claim                           5m13s
  1. 建立一個 pod 使用該 PVC。
vi pv-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: task-pv-pod
spec:
  volumes:
    - name: task-pv-storage
      persistentVolumeClaim:
        claimName: task-pv-claim
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage
  • persistentVolumeClaim:指定 pod 使用的 PVC 類別的 volume。

建立 pod。

kubectl apply -f pv-pod.yaml

pod/task-pv-pod created
kubectl get pod task-pv-pod

NAME          READY   STATUS    RESTARTS   AGE
task-pv-pod   1/1     Running   0          25s
  1. 進去該容器中查看 pod 使用的 PVC 中 index.html,是否為我剛一開始建立的 /mnt/data/index.html
apt update
apt install curl
curl http://localhost/

# 會更新與安裝一些套件的 log 就不列出來了
Hello from Kubernetes storage

看到 Hello from Kubernetes storage 就代表該 pod 成功使用 PVC,最後記得刪除 pod、pvc 與 pv。

kubectl delete pod task-pv-pod
kubectl delete pvc task-pv-claim
kubectl delete pv task-pv-volume

pod "task-pv-pod" deleted
persistentvolumeclaim "task-pv-claim" deleted
persistentvolume "task-pv-volume" deleted

刪除 PVC

當 PVC 刪掉後,PV 上沒有對應到 PVC,其預設是 Retain,PV 會留下直至管理者手動去刪除它前,並不會再給其他 PVC 使用。

以下範例。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp
    server: 172.17.0.2
  • persistentVolumeReclaimPolicy:當 PVC 刪除後,PV 有三種情況可以設定:
    1. Retain(預設)
    2. Delete(PV 連同一起刪除)
    3. Recycle(PV 的資料會被清洗掉,再給其他 PVC 使用)

以下為 2023-11-30 補充

PVC、PV、StorageClass

一般我們透過 PV 與 PVC,再透過 pod 中 volume 去指定 persistentVolumeClaimclaimName 使用 PVC,稱之為 Static Provisioning。

每次 pod 要使用 PV、PVC,管理者就需要事先建立好 PV 讓 pod 可以 mount,這樣的方式會造成管理上的困擾。為了讓應用程式(pod)在需要時可以「自動建立 PV」,可以使用 StorageClass。這樣的方式稱為 Dynamic Volume Provisioning。

例如:

mypvc-def.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  storageClassName: my-storage-class
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

storageClassName 指定 StorageClass,在 pod 建立並指定該 PVC 時,StorageClass 會自動建立所需的 PV (AWS EBS gp2 磁碟類型,儲存容量為 1Gi)。

mysc-def.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: my-storage-class
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2

參考來源

1.Kubernetes - 配置 Pod 以使用 PersistentVolume 作为存储
2.Certified Kubernetes Administrator (CKA) with Practice Tests


上一篇
[Day 21] 在 AWS 部署 Kubernetes 叢集 (四) - 部署 AWS EKS
下一篇
[Day 23] DaemonSet 與 StatefulSet
系列文
第一次參賽就學 Kubernetes30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言