天天看點

Kubernetes 存儲卷管理 PV&PVC(十)一、emptyDir二、hostPath三、PV & PVC

為了持久化儲存容器的資料,可以使用 kubernetes volume。

volume 的生命周期獨立于容器,pod 中的容器可能被銷毀和重建,但 volume 會被保留。

本質上,kubernetes volume 是一個目錄,這一點與 docker volume 類似。當 volume 被 mount 到 pod,pod 中的所有容器都可以通路這個 volume。kubernetes volume 也支援多種 backend 類型,包括 emptydir、hostpath、gce persistent disk、aws elastic block store、nfs、ceph 等,完整清單可參考 https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes

emptydir 是最基礎的 volume 類型。正如其名字所示,一個 emptydir volume 是 host 上的一個空目錄。

emptydir volume 對于容器來說是持久的,對于 pod 則不是。當 pod 從節點删除時,volume 的内容也會被删除。但如果隻是容器被銷毀而 pod 還在,則 volume 不受影響。

也就是說:emptydir volume 的生命周期與 pod 一緻。

pod 中的所有容器都可以共享 volume,它們可以指定各自的 mount 路徑。下面通過例子來實踐 emptydir,配置檔案如下:

這裡我們模拟了一個 producer-consumer 場景。pod 有兩個容器 producer和 consumer,它們共享一個 volume。producer 負責往 volume 中寫資料,consumer 則是從 volume 讀取資料。

檔案最底部 volumes 定義了一個 emptydir 類型的 volume shared-volume。

producer 容器将 shared-volume mount 到 /producer_dir 目錄。

producer 通過 echo 将資料寫到檔案 hello 裡。

consumer 容器将 shared-volume mount 到 /consumer_dir 目錄。

consumer 通過 cat 從檔案 hello 讀資料。

執行如下指令建立 pod:

<code>kubectl logs</code> 顯示容器 consumer 成功讀到了 producer 寫入的資料,驗證了兩個容器共享 emptydir volume。

emptydir 是 host 上建立的臨時目錄,其優點是能夠友善地為 pod 中的容器提供共享存儲,不需要額外的配置。但它不具備持久性,如果 pod 不存在了,emptydir 也就沒有了。根據這個特性,emptydir 特别适合 pod 中的容器需要臨時共享存儲空間的場景,比如前面的生産者消費者用例。

hostpath volume 的作用是将 docker host 檔案系統中已經存在的目錄 mount 給 pod 的容器。大部分應用都不會使用 hostpath volume,因為這實際上增加了 pod 與節點的耦合,限制了 pod 的使用。不過那些需要通路 kubernetes 或 docker 内部資料(配置檔案和二進制庫)的應用則需要使用 hostpath。

下面的例子,我們把主機上的目錄<code>/data/pod/v1</code>挂載到 pod 上容器的<code>/usr/share/nginx/html/</code>。

如果 pod 被銷毀了,hostpath 對應的目錄也還會被保留,從這點看,hostpath 的持久性比 emptydir 強。不過一旦 host 崩潰,hostpath 也就沒法通路了。

volume 提供了非常好的資料持久化方案,不過在可管理性上還有不足。

拿前面 aws ebs 的例子來說,要使用 volume,pod 必須事先知道如下資訊:

目前 volume 來自 aws ebs。

ebs volume 已經提前建立,并且知道确切的 volume-id。

pod 通常是由應用的開發人員維護,而 volume 則通常是由存儲系統的管理者維護。開發人員要獲得上面的資訊:

要麼詢問管理者。

要麼自己就是管理者。

這樣就帶來一個管理上的問題:應用開發人員和系統管理者的職責耦合在一起了。如果系統規模較小或者對于開發環境這樣的情況還可以接受。但當叢集規模變大,特别是對于生成環境,考慮到效率和安全性,這就成了必須要解決的問題。

kubernetes 給出的解決方案是 <code>persistentvolume</code> 和 <code>persistentvolumeclaim</code>。

<code>persistentvolume (pv)</code> 是外部存儲系統中的一塊存儲空間,由管理者建立和維護。與 volume 一樣,pv 具有持久性,生命周期獨立于 pod。

<code>persistentvolumeclaim (pvc)</code> 是對 pv 的申請 (claim)。pvc 通常由普通使用者建立和維護。需要為 pod 配置設定存儲資源時,使用者可以建立一個 pvc,指明存儲資源的容量大小和通路模式(比如隻讀)等資訊,kubernetes 會查找并提供滿足條件的 pv。

有了 <code>persistentvolumeclaim</code>,使用者隻需要告訴 kubernetes 需要什麼樣的存儲資源,而不必關心真正的空間從哪裡配置設定,如何通路等底層細節資訊。這些 storage provider 的底層資訊交給管理者來處理,隻有管理者才應該關心建立 persistentvolume 的細節資訊。

kubernetes 支援多種類型的 persistentvolume,比如 aws ebs、ceph、nfs 等,完整清單請參考 https://kubernetes.io/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes

下節我們用 nfs 來體會 persistentvolume 的使用方法。

作為準備工作,我們已經在 node3 節點上搭建了一個 nfs 伺服器,輸出三個目錄:

下面建立<code>pv</code>,配置檔案 <code>nfs-pv.yaml</code> 如下:

<code>accessmodes</code> 指定通路模式為 readwriteonce,支援的通路模式有:

<code>readwriteonce</code> – pv 能以 read-write 模式 mount 到單個節點。

<code>readonlymany</code> – pv 能以 read-only 模式 mount 到多個節點。

<code>readwritemany</code> – pv 能以 read-write 模式 mount 到多個節點。

<code>persistentvolumereclaimpolicy</code> 指定當 pv 的回收政策為 recycle,支援的政策有:

<code>retain</code> – 需要管理者手工回收。

<code>recycle</code> – 清除 pv 中的資料,效果相當于執行 <code>rm -rf /thevolume/*</code>。

<code>delete</code> – 删除 storage provider 上的對應存儲資源,例如 aws ebs、gce pd、azure disk、openstack cinder volume 等。

建立我們剛剛做好的pv。

建立配置檔案<code>nfs-pvc.yaml</code>,修改内容如下:

建立 pvc。

建立 pod 配置檔案<code>nfs-pvc-pod.yaml</code>,内容如下:

建立pod。

驗證 pv 是否可用:

然後在node3伺服器上面檢視。

可見,在 pod 中建立的檔案 <code>/mydata/hello</code> 确實已經儲存到了 nfs 伺服器目錄 <code>/data/volumes/pv001</code> 中。