入門Kubernetes-數據存儲
- 2021 年 8 月 1 日
- 筆記
- k8s, Kubernetes
一、Volume介紹:
在k8s中Pod的生命周期可能很短,會被頻繁地銷毀和創建。容器銷毀時,保存在容器內部文件系統中的數據都會被清除。
為了持久化保存容器數據,k8s 提供了卷(Volume)的抽象概念來解決上述問題。
卷(Volume)的核心是一個目錄,其中可能存有數據,Pod 中的容器可以訪問該目錄中的數據。 所採用的特定的卷類型將決定該目錄如何形成的、使用何種介質保存數據以及目錄中存放的內容。
Kubernetes Volume 支援多種卷類型,包括 emptyDir、hostPath、nfs、local、configMap、AWSElasticBlockStore、Cinder、CSI等。
按照存儲可大概劃分為:
臨時存儲:emptydir
半持久化存儲:hostpath
持久化存儲:nfs、ceph、Cinder等
接下來分別介紹幾種常用類型:emptyDir、hostPath、nfs(PV、PVC)
二、Volume:emptyDir
emptyDir 是最基礎的 Volume 類型。正如其名字所示,一個 emptyDir Volume 是 Host 上的一個空目錄。
emptyDir Volume 對於容器來說是持久的,對於 Pod 則不是。當 Pod 從節點刪除時,Volume 的內容也會被刪除。但如果只是容器被銷毀而 Pod 還在,則 Volume 不受影響。(emptyDir Volume 的生命周期與 Pod 一致)
Pod 中的所有容器都可以共享 Volume,它們可以指定各自的掛載路徑。
驗證示例:
apiVersion: v1 kind: Pod metadata: name: producer-consumer spec: containers: - image: busybox name: producer volumeMounts: - mountPath: /producer_dir #掛載到容器中的路徑 name: shared-volume args: - /bin/sh - -c - echo "hello world" > /producer_dir/hello; sleep 3000 - image: busybox name: consumer volumeMounts: - mountPath: /consumer_dir #掛載到容器中的路徑 name: shared-volume args: - /bin/sh - -c - cat /consumer_dir/hello; sleep 3000 volumes: - name: shared-volume emptyDir: {} #指定存儲方式為emptydir
- 創建一個名為[shared-volume]的emptyDir的卷
- 容器producer 將 shared-volume掛載到 producer_dir 目錄
- 容器producer 通過echo 命令向hello 文件中寫入文本-hello world
- 容器consumer 將 shared-volume掛載到 consumer_dir目錄
- 容器consumer 通過cat命令讀取consumer_dir中hello文件內容
通過命令:kubectl logs 查看讀取內容。
# 輸出producer-consumer Pod中容器 consumer 的日誌: kubectl logs producer-consumer -c consumer hello world
顯示容器 consumer
成功讀取到 producer
寫入的數據,驗證了兩個容器共享 emptyDir Volume。
三、Volume:hostPath
hostPath
卷能將主機節點文件系統上的文件或目錄掛載到你的 Pod 中。 雖然這不是大多數 Pod 需要的,但是它為一些應用程式提供了強大應急方式。
hostPath
的一些用法有:
- 運行一個需要訪問 Docker 內部機制的容器;可使用
hostPath
掛載/var/lib/docker
路徑。 - 在容器中運行 cAdvisor 時,以
hostPath
方式掛載/sys
。 - 允許 Pod 指定給定的
hostPath
在運行 Pod 之前是否應該存在,是否應該創建以及應該以什么方式存在。
除了必需的 path
屬性之外,用戶可以選擇性地為 hostPath
卷指定 type,下表為type取值
取值 | 行為 |
---|---|
空字元串(默認)用於向後兼容,這意味著在安裝 hostPath 卷之前不會執行任何檢查。 | |
DirectoryOrCreate |
如果在給定路徑上什麼都不存在,那麼將根據需要創建空目錄,許可權設置為 0755,具有與 kubelet 相同的組和屬主資訊。 |
Directory |
在給定路徑上必須存在的目錄。 |
FileOrCreate |
如果在給定路徑上什麼都不存在,那麼將在那裡根據需要創建空文件,許可權設置為 0644,具有與 kubelet 相同的組和所有權。 |
File |
在給定路徑上必須存在的文件。 |
Socket |
在給定路徑上必須存在的 UNIX 套接字。 |
CharDevice |
在給定路徑上必須存在的字元設備。 |
BlockDevice |
在給定路徑上必須存在的塊設備。 |
hostPath示例:
apiVersion: v1 kind: Pod metadata: name: localpod spec: containers: - image: busybox name: local volumeMounts: - mountPath: /localdir #掛載到容器中的路徑 name: mydir - mountPath: loacl.txt name: myfile args: - /bin/sh - -c - echo "local dir test" > /localdir/test.txt; - -c - cat loacl.txt; volumes: - name: mydir hostPath: # 確保文件所在目錄成功創建。 path: /var/local type: DirectoryOrCreate - name: myfile hostPath: # 確保文件創建成功 path: /var/local/test.txt type: FileOrCreate
步驟:
1、創建兩個hostPath類型的Volume
2、將這兩個卷都掛載到local容器中
3、容器啟動時,寫入文件內容「local dir test」,並讀取出來。
四、Volume:持久化存儲-nfs
說到持久化存儲:就需要提k8s中提供的重要的幾種資源類型:
- PersistentVolume (PV): 外部存儲系統中的一塊存儲空間,由管理員創建和維護。與 Volume 一樣,PV 具有持久性,生命周期獨立於 Pod。
- StorageClass:另外一種提供存儲資源的方式, 提供更多的層級選型, 如iops等參數。 但是具體的參數與提供方是綁定的。 如aws和gce它們提供的storageclass的參數可選項是有不同的。
- PersistentVolumeClaim (PVC):是對 PV 的申請 (Claim)。PVC 通常由普通用戶創建和維護。需要為 Pod 分配存儲資源時,用戶可以創建一個 PVC,指明存儲資源的容量大小和訪問模式(比如只讀)等資訊,Kubernetes 會查找並提供滿足條件的 PV。
PersistentVolume :
生命周期:
- Provisioning- 配置階段, 分為static, dynamic兩種方式。靜態的方式是創建一系列的pv,然後pvc從pv中請求。 動態的方式是基於storageclass的。
- Binding - 綁定階段, pvc根據請求的條件篩選並綁定對應的pv。 一定pvc綁定pv後, 就會排斥其它綁定,即其它pvc無法再綁定同一個pv,即使這個pv設定的access mode允許多個node讀寫。 此外 ,pvc 如何匹配不到相應條件的pv, 那麼就會顯示unbound狀態, 直到匹配為止。 需要注意的是,pvc請求100Gi大小的存儲,即使用戶創建了很多50Gi大小的存儲, 也是無法被匹配的。
- Using- 使用階段, pods 掛載存儲, 即在pod的template文件中定義volumn使用某個pvc。
- Releasing - 釋放階段, 當pvc對象被刪除後, 就處於釋放階段。 在這個階段, 使用的pv還不能被其它的pvc請求。 之前數據可能還會留存下來, 取決於用戶在pv中設定的policy, 見persistentVolumeReclaimPolicy。
- Reclaiming - 重聲明階段。 到這個階段, 會告訴cluster如何處理釋放的pv。 數據可能被保留(需要手工清除), 回收和刪除。動態分配的存儲總是會被刪除掉的。
- Recycling - 回收階段。回收階段會執行基本的遞歸刪除(取決於volumn plugins的支援),把pv上的數據刪除掉, 以使pv可以被新的pvc請求。 用戶也可以自定義一個 recycler pod , 對數據進行刪除。
卷模式:
PV支援兩種卷模式:
Filesystem
:卷會被 Pod 掛載(Mount) 到某個目錄。 如果卷的存儲來自某塊設備而該設備目前為空,Kuberneretes 會在第一次掛載卷之前 在設備上創建文件系統。- Block:將卷作為原始塊設備來使用。 這類卷以塊設備的方式交給 Pod 使用,其上沒有任何文件系統。 這種模式對於為 Pod 提供一種使用最快可能方式來訪問卷而言很有幫助,Pod 和 卷之間不存在文件系統層。另外,Pod 中運行的應用必須知道如何處理原始塊設備。
訪問模式:
PersistentVolume 卷可以用資源提供者所支援的任何方式掛載到宿主系統上。 如下表所示,提供者(驅動)的能力不同,每個 PV 卷的訪問模式都會設置為 對應卷所支援的模式值。 例如,NFS 可以支援多個讀寫客戶,但是某個特定的 NFS PV 卷可能在伺服器 上以只讀的方式導出。每個 PV 卷都會獲得自身的訪問模式集合,描述的是 特定 PV 卷的能力。
訪問模式有:
-
- ReadWriteOnce (RWO) — 卷可以被一個節點以讀寫方式掛載;
- ReadOnlyMany (ROX) — 卷可以被多個節點以只讀方式掛載;
- ReadWriteMany (RWX) – 卷可以被多個節點以讀寫方式掛載
卷插件 | ReadWriteOnce | ReadOnlyMany | ReadWriteMany |
---|---|---|---|
AWSElasticBlockStore | ✓ | – | – |
AzureFile | ✓ | ✓ | ✓ |
AzureDisk | ✓ | – | – |
CephFS | ✓ | ✓ | ✓ |
Cinder | ✓ | – | – |
CSI | 取決於驅動 | 取決於驅動 | 取決於驅動 |
FC | ✓ | ✓ | – |
FlexVolume | ✓ | ✓ | 取決於驅動 |
Flocker | ✓ | – | – |
GCEPersistentDisk | ✓ | ✓ | – |
Glusterfs | ✓ | ✓ | ✓ |
HostPath | ✓ | – | – |
iSCSI | ✓ | ✓ | – |
Quobyte | ✓ | ✓ | ✓ |
NFS | ✓ | ✓ | ✓ |
RBD | ✓ | ✓ | – |
VsphereVolume | ✓ | – | – (Pod 運行於同一節點上時可行) |
PortworxVolume | ✓ | – | ✓ |
ScaleIO | ✓ | ✓ | – |
StorageOS | ✓ | – | – |
回收策略:
目前的回收策略有:
- Retain — 手動回收
- Recycle — 基本擦除 (
rm -rf /thevolume/*
) - Delete — 諸如 AWS EBS、GCE PD、Azure Disk 或 OpenStack Cinder 卷這類關聯存儲資產也被刪除
目前,僅 NFS 和 HostPath 支援回收(Recycle)。 AWS EBS、GCE PD、Azure Disk 和 Cinder 卷都支援刪除(Delete)
持久化存儲驗證:
1、nfs服務搭建:
所有節點安裝nfs
yum install -y nfs-common nfs-utils
在master節點創建共享目錄
[root@k8s-master k8s]# mkdir /nfsdata
授權共享目錄
[root@k8s-master k8s]# chmod 666 /nfsdata
編輯exports文件
[root@k8s-master k8s]# cat /etc/exports /nfsdata *(rw,no_root_squash,no_all_squash,sync)
配置生效
[root@k8s-master k8s]# export -r
啟動rpc和nfs(注意順序)
[root@k8s-master k8s]# systemctl start rpcbind [root@k8s-master k8s]# systemctl start nfs
2、創建PV:
#創建Pv:name-pv01 apiVersion: v1 kind: PersistentVolume metadata: name: pv01 labels: name: pv01 spec: # 所有節點可共享訪問 accessModes: ["ReadWriteMany"]
# 回收策略:清除PV數據
persistentVolumeReclaimPolicy:Recycle
# 指定PV的Class為 nfs
storageClassName:nfs capacity: # Pv大小1G storage: 1Gi #nfs 服務設置,以及目錄設置 nfs: server: 192.168.115.6 path: /home
3、創建PVC:
#創建名為mypvc的PVC apiVersion: v1 kind: PersisitentVolumeClaim metadata: name: mypvc namespace: default spec: accessmodes: ["ReadWriteMany"] #所有節點可讀寫 resources: #指定資源說明 requests: #指定請求 storage: 4Gi #指定請求存儲空間的大小
4、創建POD使用PVC
#創建Pod並使用PVC apiVersion: v1 kind: Pod metadata: name: pvnginx labels: app: pvnginx spec: containers: - name: my-pvnginx image: nginx ports: - name: http containerPort: 80 - name: https containerPort: 443 volumeMounts: - name: html mountPath: /data/html volumes: - name: html persistentVolumeClaim: #指明使用pvc模式 claimname: mypvc #指明使用的pvc名稱
總結:
1、對於不需要持久化的數據可採用emptyDir類型捲來存儲相關數據,其生命周期同Pod相同
2、當需要訪問當前主機文件時,可以採用hostPath類型的捲來實現
3、PV、PVC在實際場景中應用較多,需要了解透徹:包括PV的動/靜態創建、PVC、生命周期等基本概念
參考:
//kubernetes.io/zh/docs/concepts/storage/
//kubernetes.io/zh/docs/concepts/storage/