Kubernetes 提供多種持久儲存機制,以滿足不同應用程式需求。對於簡單的組態資料,ConfigMap 可將設定檔掛載至容器內,方便管理和更新。而 Volume 則提供更通用的儲存方案,支援 emptyDir、hostPath 等本地儲存,以及 FC、NFS 等外部儲存。然而,這些方案在節點繫結和管理複雜度方面存在限制。PersistentVolume 則提供更抽象和靈活的儲存層,允許動態組態和管理儲存資源,提升應用程式可移植性和可靠性。實務上,選擇合適的持久儲存方案需考量應用程式特性、資料存取模式和儲存後端支援等因素。

Kubernetes 中的持久儲存:技術深度解析

在 Kubernetes 環境中,佈署具狀態的應用程式需要持久儲存的支援。本文將探討 Kubernetes 中的持久儲存機制,包括 ConfigMap、不同型別的 Volume,以及如何使用這些資源來支援應用程式的資料儲存需求。

ConfigMap 與 Volume 的基本使用

首先,我們使用 ConfigMap 來儲存資料並將其掛載到 NGINX 容器的特定目錄下。以下是一個簡單的範例,展示如何建立 ConfigMap 並將其掛載到容器中:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-hello
data:
  hello1.html: |
    <html>hello world 1</html>
  hello2.html: |
    <html>hello world 2</html>

內容解密:

  1. apiVersionkind 定義了 Kubernetes 資源的版本和型別。
  2. metadata 包含了資源的中繼資料,如名稱。
  3. data 部分定義了 ConfigMap 中的資料,在本例中是兩個 HTML 檔案。

建立 Pod 時,我們將 ConfigMap 掛載到容器的 /usr/share/nginx/html/hello 目錄:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-hello
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-hello
      mountPath: /usr/share/nginx/html/hello
  volumes:
  - name: nginx-hello
    configMap:
      name: nginx-hello

內容解密:

  1. volumeMounts 將名為 nginx-hello 的 Volume 掛載到容器的指定路徑。
  2. volumes 部分定義了 Volume 的來源,在本例中使用了 ConfigMap nginx-hello

驗證 ConfigMap 的掛載與資料存取

執行以下命令驗證檔案是否正確掛載:

$ kubectl exec -t pod/nginx-hello -- ls -al /usr/share/nginx/html/hello/

透過 port-forward,我們可以存取 NGINX 服務並驗證資料是否正確提供:

$ kubectl port-forward nginx-hello 8080:80 &
$ curl 127.0.0.1:8080/hello/hello1.html
<html>hello world 1</html>
$ curl 127.0.0.1:8080/hello/hello2.html
<html>hello world 2</html>

內容解密:

  1. 使用 kubectl port-forward 將 Pod 的 80 連線埠轉發到本地的 8080 連線埠。
  2. 使用 curl 命令存取指定的 URL 以驗證 NGINX 是否正確提供檔案。

Kubernetes 中的不同 Volume 型別

Kubernetes 支援多種 Volume 型別,包括:

  • emptyDir
  • hostPath
  • local
  • FC (Fiber Channel) block disk
  • NFS (Network File System)

前三種 Volume 受限於節點的磁碟空間,且與節點繫結,可能導致服務品質下降或資料遺失。後兩種 Volume 由於是外部儲存,能夠解決上述問題,但需要與儲存管理員協調組態。

使用 FC 和 NFS Volume

對於 FC 和 NFS Volume,需要在 Pod 定義中進行相應的組態。例如,使用 FC Volume 時,需要指定目標 WWPN 和 LUN:

volumes:
- name: fc-vol
  fc:
    targetWWNs:
    - "500a0982991b8dc5"
    - "500a0982891b8dc5"
    lun: 2
    fsType: ext4
    readOnly: true

對於 NFS Volume,則需要指定 NFS 伺服器和匯出路徑:

volumes:
- name: nfs-volume
  nfs:
    server: nfs.corp.mycompany.org
    path: /k8s-nginx-hello
    readOnly: true

內容解密:

  1. FC 和 NFS Volume 需要儲存管理員預先組態 LUN 或匯出路徑。
  2. 在 Pod 定義中,需正確設定對應的引數以掛載這些 Volume。

PersistentVolume:更靈活的儲存解決方案

雖然上述 Volume 型別能夠滿足基本的儲存需求,但在大規模佈署微服務時,其限制和複雜性成為了一大挑戰。Kubernetes 的 PersistentVolume(PV)提供了一個更抽象、更靈活的儲存解決方案,使應用程式能夠動態地使用儲存資源。

介紹 PersistentVolumes

就像 Pod 或 ConfigMap 一樣,PersistentVolume 是透過 kube-apiserver 公開的資源型別。你可以使用 YAML 和 kubectl 像其他 Kubernetes 物件一樣建立、更新和刪除持久性儲存區(PVs)。

以下命令將演示如何列出目前在你的 Kubernetes 叢集中組態的 PersistentVolume 資源型別:

$ kubectl get persistentvolume
No resource found

persistentvolume 物件也可以使用 persistentvolumes 的複數形式以及 pv 的別名來存取。以下三個命令本質上是相同的:

$ kubectl get persistentvolume
No resource found
$ kubectl get persistentvolumes
No resource found
$ kubectl get pv
No resource found

你會發現,pv 別名在 Kubernetes 社群中非常常用,很多人直接稱 PV 為 pv,所以要注意這一點。目前為止,我們的 Kubernetes 叢集中尚未建立任何 PersistentVolume 物件,這就是為什麼在上述命令的輸出中看不到任何資源列出的原因。

PersistentVolume 是物件,從本質上代表你可以附加到 Pod 的儲存空間。這種儲存空間被稱為持久的,因為它不應該與 Pod 的生命週期繫結。

事實上,如第 5 章《使用多容器 Pod 和設計模式》中提到的,Kubernetes Pod 使用了卷的概念。此外,我們還瞭解了 emptyDir 卷,它初始化了一個空目錄,供 Pod 分享。它還定義了工作節點檔案系統中的一個路徑,該路徑將暴露給 Pod。這兩種卷都應該附加到 Pod 的生命週期中。這意味著,一旦 Pod 被銷毀,儲存在卷中的資料也將被銷毀。

然而,有時你不希望卷被銷毀。你只是希望它有自己的生命週期,以便在 Pod 失敗時保持卷和其資料的存活。這就是 PersistentVolumes 發揮作用的地方:它們本質上是不與 Pod 生命週期繫結的卷。由於它們是一種資源型別,就像 Pod 本身一樣,它們可以獨立存在!從本質上講,PVs 確保你的儲存在 Pod 存在之後仍然可用,這對於維護有狀態應用程式的資料完整性至關重要。現在,讓我們分解 PersistentVolumes 物件:它們由兩個關鍵元素組成 – 後端技術(PersistentVolume 型別)和存取模式(如 ReadWriteOnce(RWO))。瞭解這些概念對於在 Kubernetes 環境中有效地使用 PVs 至關重要。

Kubernetes 中的持久儲存

在下一節中,我們將首先解釋什麼是 PersistentVolume 型別。

介紹 PersistentVolume 型別

正如你已經知道的,最簡單的 Kubernetes 安裝由一個簡單的 minikube 安裝組成,而最複雜的 Kubernetes 安裝可以由數十台伺服器組成,執行在大規模可擴充套件的基礎設施上。所有這些不同的設定都將不可避免地具有不同的管理持久儲存的方式。例如,三個知名的公有雲提供商有很多不同的解決方案。讓我們來命名幾個,如下所示:

  • Amazon EBS 卷
  • Amazon Elastic File System(EFS)檔案系統
  • Google GCE 持久磁碟(PD)
  • Microsoft Azure 磁碟

這些解決方案有自己的設計和原理,以及自己的邏輯和機制。Kubernetes 的構建原則是,所有這些設定都應該使用一個物件進行抽象,以抽象所有不同的技術;那個單一物件就是 PersistentVolume 資源型別。PersistentVolume 資源型別是將附加到執行中的 Pod 的物件。

事實上,Pod 是 Kubernetes 資源,不知道什麼是 EBS 或 PD;Kubernetes Pod 只與 PersistentVolumes(也是一種 Kubernetes 資源)配合良好。無論你的 Kubernetes 叢集執行在 Google GKE 還是 Amazon EKS 上,或者它是在本地機器上的單個 minikube 叢集,都沒有關係。當你希望管理持久儲存時,你將建立、使用和佈署 PersistentVolumes 物件,然後將它們繫結到你的 Pod!

以下是 Kubernetes 開箱即用的一些後端技術:

  • csi:容器儲存介面(CSI)
  • fc:FC 儲存
  • iscsi:透過 IP 的 SCSI
  • local:使用本地儲存
  • hostPath:HostPath 卷
  • nfs:常規網路檔案儲存

上述列表並不詳盡:Kubernetes 極其靈活,可以與許多儲存解決方案一起使用,這些解決方案可以在叢集中抽象為 PersistentVolume 物件。

請記住,PersistentVolumes 物件只是 etcd 資料函式庫中的條目,它們本身並不是實際的磁碟。PersistentVolume 只是在 Kubernetes 中指向一塊儲存空間的一種指標,例如 NFS、磁碟、Amazon Elastic Block Store(EBS)卷等。這樣,你就可以以 Kubernetes 的方式從 Kubernetes 中存取這些技術。

內容解密:

此段落主要闡述了Kubernetes中的PersistentVolume(PV)概念及其相關技術。首先,介紹了PV的基本操作和其與Pod生命週期的獨立性,接著探討了PV型別的多樣性及其在不同雲端環境和本地環境中的應用,最後強調了PV在本質上是Kubernetes對不同儲存技術的抽象表示。透過這些內容,可以瞭解到PV在Kubernetes中實作持久化儲存的重要性和靈活性。

程式碼解析

以下是一個簡單的YAML檔案範例,用於建立一個PersistentVolume:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  local:
    path: /mnt/data
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - minikube

內容解密:

  1. apiVersionkind 定義了該YAML檔案所建立的Kubernetes資源型別,在此為PersistentVolume
  2. metadata.name 指定了PV的名字。
  3. spec.capacity.storage 定義了PV的儲存容量。
  4. spec.accessModes 指定了PV的存取模式,如ReadWriteOnce表示該卷可以被單個節點以讀寫模式掛載。
  5. spec.persistentVolumeReclaimPolicy 定義了當PV不再被使用時的回收策略,此處設定為Retain表示保留資料。
  6. spec.local.path 指定了本地節點上的儲存路徑。
  7. spec.nodeAffinity 定義了節點親和性規則,用於指定哪些節點可以存取該PV。

此YAML檔案展示瞭如何定義一個使用本地儲存的PersistentVolume,並指定其屬性和回收策略。透過這種方式,可以根據實際需求建立和管理持久化儲存資源,以支援Kubernetes叢集中的應用程式。

探討 Kubernetes 中的 PersistentVolume

在 Kubernetes 環境中,儲存管理是一項至關重要的任務。隨著 Kubernetes 的不斷演進,許多 PersistentVolume(PV)型別已被棄用或移除,這標誌著 Kubernetes 儲存管理方式的轉變。本文將探討 PersistentVolume 的概念、其帶來的好處、存取模式以及如何在 Kubernetes 中建立第一個 PersistentVolume 物件。

PersistentVolume 的好處

PersistentVolumes 是 Kubernetes 中管理有狀態應用程式的關鍵元件。與臨時儲存不同,PV 能夠確保資料在個別 Pod 的生命週期之外持續存在,使其成為需要資料保留和一致性的應用程式的理想選擇。這些儲存資源為 Kubernetes 生態系統帶來了靈活性和可靠性,增強了效能和還原能力。

PersistentVolume 的三大主要好處如下:

  • PV 在 Kubernetes 中獨立於使用它的 Pod 存在。這意味著,如果您刪除或重新建立連線到 PersistentVolume 的 Pod,儲存在該磁碟區上的資料將保持完整。資料的永續性取決於 PersistentVolume 的回收原則:使用保留原則,資料將保持可用以供未來使用,而刪除原則則會在 Pod 被刪除時移除磁碟區及其資料。因此,您可以在管理 Pod 的同時無需擔心儲存在 PersistentVolumes 上的資料遺失。
  • 當 Pod 當機時,PersistentVolume 物件將倖存下來,不會從叢集中被移除。
  • PersistentVolume 是叢集範圍的;這意味著它可以連線到在任何節點上執行的任何 Pod。

然而,這些陳述並非總是 100% 有效。事實上,有時 PersistentVolume 物件會受到其底層技術的影響。

存取模式的限制

例如,如果 PersistentVolume 物件指向計算節點上的 hostPath 儲存,則該 PersistentVolume 將無法被其他節點存取。然而,如果使用 NFS 設定,則情況會有所不同。您可以從多台機器同時存取 NFS。因此,由 NFS 支援的 PersistentVolume 物件可以從執行在不同節點上的多個 Pod 存取,而不會出現太多問題。

介紹 PersistentVolume 存取模式

存取模式是在建立 PersistentVolume 型別時設定的選項,它告訴 Kubernetes 如何掛載該磁碟區。PersistentVolumes 支援四種存取模式,如下所示:

  • ReadWriteOnce(RWO):此磁碟區允許一個節點同時進行讀寫操作。
  • ReadOnlyMany(ROX):此磁碟區允許多個節點同時進行唯讀操作。
  • ReadWriteMany(RWX):此磁碟區允許多個節點同時進行讀寫操作。
  • ReadWriteOncePod:這是一種最近引入的新模式,在 Kubernetes 1.29 版本中已經穩定。在此存取模式下,該磁碟區可被單個 Pod 以讀寫方式掛載。當您希望整個叢集中只有一個 Pod 能夠對 Persistent Volume Claim(PVC)進行讀寫操作時,請使用 ReadWriteOncePod 存取模式。

並非所有 PersistentVolume 型別都支援所有存取模式,如下表所示。

不同 PersistentVolume 型別的存取模式支援

| PV 型別 | RWO | ROX | RWX | ReadWriteOncePod | |





– | — | — | — |




– | | hostPath | ✓ | - | - | - | | NFS | ✓ | ✓ | ✓ | ✓ | | iSCSI | ✓ | ✓ | - | - | | CephFS | ✓ | ✓ | ✓ | ✓ |

在 Kubernetes 中,PersistentVolume 型別的存取模式與底層儲存技術及其處理資料的方式密切相關。檔案儲存(如 NFS 或 CIFS)允許多個客戶端同時存取相同的檔案,因此它們可以支援多種存取模式,如 RWO、ROX 和 RWX。另一方面,區塊儲存(如本機儲存或 hostPath)則設計為一次只能被一個客戶端存取,因為它處理的是原始磁碟扇區而非檔案。因此,區塊儲存僅支援 RWO 模式,即單個節點可以對該磁碟區進行讀寫操作。

建立第一個 PersistentVolume 物件

讓我們使用宣告式方法在 Kubernetes 叢集中建立一個 PersistentVolume。由於 PersistentVolumes 是更複雜的資源,因此強烈建議避免使用命令式方法。宣告式方法允許您以 YAML 檔案定義和管理資源,使其更容易追蹤變更、對組態進行版本控制,並確保在不同環境中的可重複性。

以下是一個建立 PersistentVolume 物件的 YAML 定義範例:

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-hostpath
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /data/pv-hostpath

程式碼解析:

  1. apiVersionkind: 指定 Kubernetes 資源的 API 版本和型別。在此例中,我們使用的是 v1 版本的 PersistentVolume
  2. metadata: 提供有關 PersistentVolume 的元資料,如名稱和標籤。
  3. spec: 定義 PersistentVolume 的規格,包括儲存類別名稱、容量、存取模式和回收原則。
  4. storageClassName: 指定儲存類別名稱。在此例中,我們使用的是 manual
  5. capacity: 定義 PersistentVolume 的儲存容量。在此例中,我們分配了 1Gi 的儲存空間。
  6. accessModes: 指定 PersistentVolume 的存取模式。在此例中,我們使用的是 ReadWriteOnce,表示該磁碟區可以被單個節點以讀寫方式掛載。
  7. persistentVolumeReclaimPolicy: 定義當 PersistentVolume 被釋放時的回收原則。在此例中,我們使用的是 Retain 原則,表示當 PVC 被刪除時,PV 將被保留。
  8. hostPath: 指定本機節點上的路徑,用於儲存 PersistentVolume 的資料。在此例中,我們使用的是 /data/pv-hostpath 路徑。