Kubernetes之存儲原理和應用——資源對象與Node本地存儲卷
容器內部存儲的生命周期是短暫的,會隨著容器環境的銷毀而銷毀,具有不穩定性。如果多個容器希望共享同一份存儲,則僅僅依賴容器本身是很難實現的。Kubernetes 系統中,將對容器應用所需的存儲資源抽象為存儲卷(Volume)概念來解決這些問題。
Volume 是與 Pod 綁定的(獨立于容器)與 Pod 具有相同生命周期的資源對象。我們可以將 Volume 的內容理解為目錄或文件,容器如需使用某個 Volume, 則僅需設置 volumeMounts 將一個或多個 Volume 掛載為容器中的目錄或文件,即可訪問 Volume 中的數據。Volume 具體是什么類型,以及由哪個系統提供,對容器應用來說是透明的。
一、將資源對象映射為存儲卷
在 Kubernetes 中有一些資源對象可以以存儲卷的形式掛載為容器內的目錄或文件,目前有以下幾種類型:
(1)ConfigMap:一般用于存儲容器應用需要的一些配置信息。
(2)Downward API:用于將 Pod 和容器的某些元數據信息注入容器環境內,供容器應用方便地使用。
(3)Secret:主要用于存儲一些敏感認證信息。
(4)ServiceAccountToken:用于 Pod 與 API Server 之間的認證。
(5)Projected Volume:用于將一個或多個上述資源對象一次性掛載到容器內的同一個目錄下。
這些資源對象以存儲卷的形式掛載到 Pod 以后,在 Pod 上看到的目錄或文件都是只讀的。
1. ConfigMap
ConfigMap 以一個或多個 key:value 的形式保存在 Kubernetes 系統中供應用使用,既可以用于表示一個變量的值(例如 apploglevel=info) ,也可以用于表示一個完整配置文件的內容(例如 server.xml=... )。
(1)ConfigMap 資源對象的創建
<1>通過 YAML 文件方式創建
YAML 文件:
創建:
<2>通過 kubectl 命令行方式創建
通過 --from-file 參數從文件中創建,可以指定 key 的名稱,也可以在一個命令行中創建包含多個 key 的 ConfigMap,value 則是指定的文件中的內容:
通過 --from-file 參數在目錄下進行創建,該目錄下每個文件的名稱都將被設置為 key,文件的內容則被設置為 value:
(注意:子目錄下的文件不會被設置為 configmap 中的配置項)
使用 --from-literal 時會從文本中進行創建,直接將指定的 key=value 創建為 ConfigMap 的內容:
(2)ConfigMap 資源對象在 Pod 中的使用
<1>通過環境變量方式使用 ConfigMap

或者直接使用字段 envFrom,在 Pod 環境中自動將 ConfigMap 中所有定義的 key=value 自動生成為環境變量:

<2>通過 volumeMount 使用 ConfigMap
首先在字段 volumes 中聲明要使用的 ConfigMap,ConfigMap 中一個 key=value 將成為 volume 中的一個文件:
文件名稱:使用 items 字段時,可以在 path 字段設置每個 key 對應的文件名稱,還可以設置子目錄;不使用 items 字段時,將直接使用 key 作為文件名稱。
文件內容:ConfigMap 中 key 對應的 value 則成為文件的內容。
然后使用 volumeMounts 字段在容器中掛載卷,指定 volumes 中聲明的卷名稱和掛載的目錄。
(3)使用 ConfigMap 的限制條件
<1>ConfigMap 必須在 Pod 之間創建, Pod 才能引用它。
<2>如果 Pod 使用 envFrom 基于 ConfigMap 定義環境變量 ,則無效的環境變量名稱(例如名稱以數字開頭)將被忽略,在事件中被記錄為 InvalidVariableNames。
<3>ConfigMap 受命名空間限制, 只有處于相同命名空間中的 Pod 才可以引用它。
<4>ConfigMap 無法用于靜態 Pod。
2. Downward API
在某些應用場景中,容器內的應用需要獲取 Pod 的信息。為了在容器內獲取 Pod 信息, Kubernetes 提供了 Downward API 機制來將 Pod 和容器的某些元數據信息注入容器環境內,供容器應用方便地使用。
Downward API 可以通過以下兩種方式將 Pod 和容器的元數據信息注人容器內部:
(1)環境變量方式:將 Pod 或 Container 信息設置為容器內的環境變量。
(2)Volume 掛載方式:將 Pod 或 Container 信息以文件的形式掛載到容器內部。
實踐示例如下:

3. Secret
Secret 是用來存儲敏感認證信息的一種重要資源,例如密碼、token、密鑰等。Secret 中的數據是以 base64 編碼的,Secret 作為 volume 掛載到 Pod 以后,可在 Pod 上看到 base64 解碼后的明文。
(1)創建 Secret

(2)在 Pod 中使用 Secret

4. Projected Volume
Projected Volume 是一種特殊的存儲卷類型,用于將一個或多個上述資源對象(ConfigMap、Secret、Downward API)一次性掛載到容器內的同一個目錄下。
如果 Pod 希望同時掛載 ConfigMap、Secret、Downward APT,則需要設置多個不同類型的 Volume,再將每個 Volume 都掛載為容器內的目錄或文件。如果應用程序希望將配置文件和密鑰文件放在容器內的同一個目錄下,則通過多個 Volume 就無法實現了。為了支待這種需求, Kubernetes 入了一種新的 Projected Volume 存儲卷類型,用于將多種配置類數據通過單個 Volume 掛載到容器內的單個目錄下。
實踐示例如下:

二、Node 本地存儲卷
Kubernetes 管理的 Node 地存儲卷(Volume)類型如下:
(1)EmptyDir:與 Pod 同生命周期的 Node 臨時存儲。
(2)HostPath:Node 目錄。
(3)Local:基于持久卷(PV)管理的 Node 目錄。
1. EmptyDir
這種類型的 Volume 將在 Pod 被調度到 Node 時進行創建,在初始狀態下目錄中是空的,所以命名為“空目錄 ”(Empty Directory),它與 Pod 具有相同的生命周期,當 Pod 銷毀時, Node 上相應的目錄也會被刪除。同一個 Pod 中的多個容器都可以掛載這種 Volume。
(1)應用場景
由于 EmptyDir 類型存儲卷的臨時性特點,它通常可以用于以下應用場景中:
<1>基于磁盤進行合并排序操作時需要的暫存空間。
<2>長時間計算任務的中間檢查點文件。
<3>為某個 Web 服務提供的臨時網站內容文件。
(2)存儲介質
在默認情況下, kubelet 會在 Node 的工作目錄下為 Pod 創建 EmptyDir 目錄,這個目錄的存儲介質可能是本地磁盤、 SSD 磁盤或者網絡存儲設備,取決于環境的配置。
另外, EmptyDir 可以通過 medium 字段設置存儲介質為“Memory",表示使用基于內存的文件系統(tmpfs RAM-backed filesystem)。雖然 tmpfs 的讀寫速度非常快,但與磁盤中的目錄不同,在主機重啟之后, tmpfs 的內容就會被清空。此外,寫入 tmpfs 的數據將被統計為容器的內存使用量,受到容器級別內存資源上限(Memory Resource Limit)的限制
(3)使用實踐
創建一個掛載 EmptyDir 的 Pod:

登錄 Pod,在 EmptyDir 掛載目錄下寫入一個文件:
在 Node 上查找這個文件,可以找到 EmptyDir 臨時存儲的文件位置:
刪除 Pod 后,Node 上對應的 EmptyDir 臨時存儲也被刪除:
2. HostPath
HostPath 類型的存儲卷用于將 Node 文件系統的目錄或文件掛載到容器內部使用。
(1)應用場景
對于大多數容器應用來說,都不需要使用宿主機的文件系統。適合使用 HostPath 存儲卷的一些應用場景如下:
<1>容器應用的關鍵數據需要被持久化到宿主機上。
<2>需要使用 Docker 的某些內部數據,可以將主機的 var/Iib/docker 目錄掛載到容器內。
<3>監控系統,例如 cAdvisor 需要采集宿主機 /sys 目錄下的內容。
<4>Pod 的啟動依賴于宿主機上的某個目錄或文件就緒的場景。
(2)宿主機路徑類型
HostPath 存儲卷的主要配置參數為 path,設置為宿主機的目錄或文件路徑;還可以設置一個可選的參數 type,表示宿主機路徑的類型。目前支待的 type 配置參數和校驗規則如下:
(3)使用實踐
創建一個掛載 HostPath 的 Pod:

登錄 Pod,在 HostPath 掛載目錄下寫入一個文件:
在 Node 上可以找到這個文件,且 Pod 刪除后,HostPath 對應的目錄和文件都還存在:
參考:
《Kubernetes 權威指南第 5 版》

浙公網安備 33010602011771號