iT邦幫忙

2024 iThome 鐵人賽

DAY 30
0

寫不完根本寫不完 ( ;´Д`)


在 Kubernetes 中的 Pod & Container 本質上是無狀態(Stateless)且臨時的,一旦被回收就會失去所有暫存在其中的資訊。雖然 Stateless 可以保證系統的高擴展性,但實務上難免會遇到需要儲存狀態或是讓 Pod 之間共享資訊的需求。

這就是 Kubernetes Volumes 發揮作用的地方。


Volumes

解決 PodContainer 中暫存的資訊會隨其生命週期消失的問題。
本質上,Volumes 是個目錄(dictionary),目錄中儲存著資訊,並提供 Pod 中的 Container 可以讀取。
Volumes 的種類超級多,列出比較常用的幾種:

  • persistentVolumeClaim (PVC)
    • 最常用的持久化儲存解決方案
    • 提供了儲存的抽象,易於使用
  • configMap (對,ConfigMap也是)
    • 廣泛用於管理應用程序的配置
    • 可以動態更新,無需 rebuild image
  • emptyDir
    • 用於臨時儲存和 Container 間共用資訊
    • 簡單易用,適合多種場景
  • nfs
    需要多個 Pod 共享讀寫時使用

完整資訊可以參考官方文件:Types of volumes

因安全性會產生許多風險,官方不建議使用 hostPath,可改為使用 local Persistent Volume

使用方式
https://ithelp.ithome.com.tw/upload/images/20241001/201684370frUSSFKwx.png
yaml 設定:

apiVersion: v1
kind: Pod
metadata:
  name: <pod-name>
spec:
  containers:
  - image: <image>
    name: <container-name>
    # VOLUME
    volumeMounts:
    - mountPath: /opt # 實際指向 data-volume 設定的 host 位置 /data
      name:  data-volume # volume name set in "volumes"
  volumes:
  - name: data-volume
    hostPath:
      path: /data # host 內的 /data 位置
      type: Directory
  • volumeMounts:將路徑掛載進 container 的設定值
  • volumes:掛載進 Pod 的 volume 設定

不過,這種方式有些限制:

  • 每個 Pod 都去做一次設定(或至少每個部署都要做一次)
  • 只適用於單一個 Node

有沒有更彈性、更泛用的儲存方式呢?

有的有的!可以透過 Persistent Volume 設定。

Persistent Volume(PV)

k8s 的討論中很常看到的 PV,就是指 Persistent Volume。
它是將 k8s 的持久化儲存機制抽象,讓使用者可以不用擔心底層實踐,只需調用即可。
https://ithelp.ithome.com.tw/upload/images/20241001/20168437uaestZNdyM.png
設定方式:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  capacity:
    storage: 5Gi  # 指定存儲空間
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany  # 允許多個 Pod 同時讀寫
  persistentVolumeReclaimPolicy: Retain  # 當 PVC 被刪除時保留資料
  storageClassName: nfs  # 可用於將 PVC 對應
  nfs:  # NFS 配置
    server: <NFS server>
    path: "/exported/path"  # NFS 導出的路徑
  mountOptions:  # NFS 掛載設定
    - hard
    - nfsvers=4.1

  • accessModes:有哪些設定取決於 PV resource provider 支援度 (非 k8s 支援)
    • ReadOnlyMany:僅有一個 Node 可寫入,多個 Node 可讀
    • ReadWriteOnce:僅有一個 Node 可讀寫
    • ReadWriteMany:允許多個 Node 讀寫

蛤?為什麼不把 Pod 接上去?

因為這個設定只是將外部儲存空間掛進 Cluster 內,Pod 要使用這個儲存空間還需要另一層介接:

PersistentVolumeClaim (PVC)

https://ithelp.ithome.com.tw/upload/images/20241001/20168437r9bSP78GoO.png

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  accessModes:
    - ReadWriteMany
  volumeMode: Filesystem
  resources:
    requests:
      storage: 5Gi
  storageClassName: nfs

PersistentVolumeClaim & PersistentVolume 是以 storageClassName 做對應,PVC 只能使用相同名稱的 PV。

如果 PVC 沒有指定 storageClassName,那它也只能使用同樣沒有設定 storageClassName 的 PV,並不會因此變得所有 PV 皆可使用。

啊怎麼 PV 跟 PVC 都有指定資源跟 accessMode?不會衝突嗎?

會唷!當 PersistentVolumeClaim (PVC)PersistentVolume (PV) 的設置之間出現衝突時,可能會導致 PVC 無法綁定到 PV。
具體的結果取決於衝突的類型:

  • 儲存空間不相同

    • PVC 請求的空間 > PV
      Kubernetes 不會將這個 PVC 綁定到該 PV,並且會保持 PVC 處於 Pending 狀態。
    • PVC 請求的空間 < PV
      Kubernetes 允許 PVC 請求小於 PV 提供的大小,但是未使用的部分就會浪費掉。

    PV 空間的"浪費":

    PV 一次只能綁定一個 PVC,但 PVC 可以提供多個 Pod 使用。
    ReadWriteOnce 只能被綁到單一個 Pod; ReadOnlyManyReadWriteMany 則可以被多個 Pod 共同使用。

  • 讀寫模式不一致
    PVC 和 PV 需要使用相同的設定。
    如果 PVC 的設定與 PV 不一致,PVC 會保持在 Pending 狀態,無法綁定。

    status:pending

    當 PVC 找不到可用的 PV 時,會維持在 pending 狀態直到有可用的 PV 出現。

透過 PV + PVC,就不用擔心部署到其他 Node 上就讀不到資訊啦 (⁎⁍̴̛ᴗ⁍̴̛⁎)

將 PVC 抽象還有其他好處:

  • 解耦
    Pod 不直接與 PV 交互,將 Pod 的配置與具體的儲存實現細節解耦,提升了 Pod 的可移植性
  • 彈性配置
    如果需要更改底層儲存(換掉 PV),只需要修改 PVC 的配置,而不需要修改 Pod 的配置。
  • 安全性
    通過使用 PVC,更能控制對儲存空間的訪問權限。

小結

Volume 主要解決兩個問題:

  1. Container 或 Pod 異常或終止時,其狀態資料會消失
  2. Container 或 Pod 需要讀取同一份資料的情境
    解決方式:長久儲存機制
    優化:將 Pod 掛載儲存的方式抽象化

差點忘了,PV 有支援 nodeAffinity

不認識 nodeAffinity 的話可以看這邊:nodeAffinity
透過在 PV 上設置 nodeAffinity,可以間接控制 PVC 只能在某些 Node 上使用該 PV
視情況還可以搭配 Pod 的 nodeAffinity 設定,以確保 Pod 部署到與 PV 相對應的 Node 上。


沒想到 30 天只能寫到 volume... 這30天的內容包含了 Kubernetes 的基本運作、運作生命週期、基本儲存方式,雖說還沒寫到網路,但 Kubernetes 的網路應該自己就可以寫滿 30 天了吧 (。・ω・。)

有了對 Kubernetes 的基本認識,往後學習的路上應該也可以輕鬆一些... (希望啦)。


上一篇
Day-29 變數管理
系列文
Kubernetes圖解筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言