1. 程式人生 > 其它 >Kubernetes(k8s)儲存管理之資料卷volumes(四):持久卷Persistent Volume

Kubernetes(k8s)儲存管理之資料卷volumes(四):持久卷Persistent Volume

目錄

一.系統環境

伺服器版本 docker軟體版本 Kubernetes(k8s)叢集版本 CPU架構
CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 v1.21.9 x86_64

Kubernetes叢集架構:k8scloude1作為master節點,k8scloude2,k8scloude3作為worker節點

伺服器 作業系統版本 CPU架構 程序 功能描述
k8scloude1/192.168.110.130 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico k8s master節點
k8scloude2/192.168.110.129 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kubelet,kube-proxy,calico k8s worker節點
k8scloude3/192.168.110.128 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kubelet,kube-proxy,calico k8s worker節點

二.前言

Kubernetes(k8s)資料卷volumes型別眾多,本文介紹資料卷volumes之一持久卷Persistent Volume

使用資料卷volumes的前提是已經有一套可以正常執行的Kubernetes叢集,關於Kubernetes(k8s)叢集的安裝部署,可以檢視部落格《Centos7 安裝部署Kubernetes(k8s)叢集》https://www.cnblogs.com/renshengdezheli/p/16686769.html

三.持久卷(Persistent Volume)

3.1 持久卷(Persistent Volume)概覽

儲存的管理是一個與計算例項的管理完全不同的問題。 PersistentVolume 子系統為使用者和管理員提供了一組 API, 將儲存如何製備的細節從其如何被使用中抽象出來。 為了實現這點,我們引入了兩個新的 API 資源:PersistentVolume 和 PersistentVolumeClaim。

持久卷(PersistentVolume,PV) 是叢集中的一塊儲存,可以由管理員事先製備, 或者使用儲存類(Storage Class)來動態製備。 持久卷是叢集資源,就像節點也是叢集資源一樣。PV 持久卷和普通的 Volume 一樣, 也是使用卷外掛來實現的,只是它們擁有獨立於任何使用 PV 的 Pod 的生命週期。 此 API 物件中記述了儲存的實現細節,無論其背後是 NFS、iSCSI 還是特定於雲平臺的儲存系統。

持久卷申領(PersistentVolumeClaim,PVC) 表達的是使用者對儲存的請求。概念上與 Pod 類似。 Pod 會耗用節點資源,而 PVC 申領會耗用 PV 資源。Pod 可以請求特定數量的資源(CPU 和記憶體);同樣 PVC 申領也可以請求特定的大小和訪問模式 (例如,可以要求 PV 卷能夠以 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany 模式之一來掛載)。

儘管 PersistentVolumeClaim 允許使用者消耗抽象的儲存資源, 常見的情況是針對不同的問題使用者需要的是具有不同屬性(如,效能)的 PersistentVolume 卷。 叢集管理員需要能夠提供不同性質的 PersistentVolume, 並且這些 PV 卷之間的差別不僅限於卷大小和訪問模式,同時又不能將卷是如何實現的這些細節暴露給使用者。 為了滿足這類需求,就有了儲存類(StorageClass) 資源。

3.2 持久卷和持久卷申領的生命週期

PV 卷是叢集中的資源。PVC 申領是對這些資源的請求,也被用來執行對資源的申領檢查。 PV 卷和 PVC 申領之間的互動遵循如下生命週期:
PV 卷的建立有兩種方式:

  • 靜態製備:叢集管理員建立若干 PV 卷。這些卷物件帶有真實儲存的細節資訊, 並且對叢集使用者可用。PV 卷物件存在於 Kubernetes API 中,可供使用者消費(使用)。
  • 動態製備:如果管理員所建立的所有靜態 PV 卷都無法與使用者的 PersistentVolumeClaim 匹配, 叢集可以嘗試為該 PVC 申領動態製備一個儲存卷。 這一製備操作是基於 StorageClass 來實現的:PVC 申領必須請求某個 儲存類, 同時叢集管理員必須已經建立並配置了該類,這樣動態製備卷的動作才會發生。 如果 PVC 申領指定儲存類為 "",則相當於為自身禁止使用動態製備的卷。

為了基於儲存類完成動態的儲存製備,叢集管理員需要在 API 伺服器上啟用 DefaultStorageClass 准入控制器。 舉例而言,可以通過保證 DefaultStorageClass 出現在 API 伺服器元件的 --enable-admission-plugins 標誌值中實現這點;該標誌的值可以是逗號分隔的有序列表。
使用者建立一個帶有特定儲存容量和特定訪問模式需求的 PersistentVolumeClaim 物件; 在動態製備場景下,這個 PVC 物件可能已經建立完畢。 主控節點中的控制迴路監測新的 PVC 物件,尋找與之匹配的 PV 卷(如果可能的話), 並將二者繫結到一起。 如果為了新的 PVC 申領動態製備了 PV 卷,則控制迴路總是將該 PV 卷繫結到這一 PVC 申領。 否則,使用者總是能夠獲得他們所請求的資源,只是所獲得的 PV 卷可能會超出所請求的配置。 一旦繫結關係建立,則 PersistentVolumeClaim 繫結就是排他性的, 無論該 PVC 申領是如何與 PV 卷建立的繫結關係。 PVC 申領與 PV 卷之間的繫結是一種一對一的對映,實現上使用 ClaimRef 來記述 PV 卷與 PVC 申領間的雙向繫結關係。

如果找不到匹配的 PV 卷,PVC 申領會無限期地處於未繫結狀態。 當與之匹配的 PV 卷可用時,PVC 申領會被繫結。 例如,即使某叢集上製備了很多 50 Gi 大小的 PV 卷,也無法與請求 100 Gi 大小的儲存的 PVC 匹配。當新的 100 Gi PV 卷被加入到叢集時, 該 PVC 才有可能被繫結。
Pod 將 PVC 申領當做儲存捲來使用。叢集會檢視 PVC 申領,找到所繫結的卷, 併為 Pod 掛載該卷。對於支援多種訪問模式的卷, 使用者要在 Pod 中以卷的形式使用申領時指定期望的訪問模式。

一旦使用者有了申領物件並且該申領已經被繫結, 則所繫結的 PV 卷在使用者仍然需要它期間一直屬於該使用者。 使用者通過在 Pod 的 volumes 塊中包含 persistentVolumeClaim 節區來排程 Pod,訪問所申領的 PV 卷。
保護使用中的儲存物件(Storage Object in Use Protection) 這一功能特性的目的是確保仍被 Pod 使用的 PersistentVolumeClaim(PVC) 物件及其所繫結的 PersistentVolume(PV)物件在系統中不會被刪除,因為這樣做可能會引起資料丟失。

說明: 當使用某 PVC 的 Pod 物件仍然存在時,認為該 PVC 仍被此 Pod 使用。
如果使用者刪除被某 Pod 使用的 PVC 物件,該 PVC 申領不會被立即移除。 PVC 物件的移除會被推遲,直至其不再被任何 Pod 使用。 此外,如果管理員刪除已繫結到某 PVC 申領的 PV 卷,該 PV 卷也不會被立即移除。 PV 物件的移除也要推遲到該 PV 不再繫結到 PVC。

你可以看到當 PVC 的狀態為 Terminating 且其 Finalizers 列表中包含 kubernetes.io/pvc-protection 時,PVC 物件是處於被保護狀態的。

3.3 持久卷的型別

PV 持久卷是用外掛的形式來實現的。Kubernetes 目前支援以下外掛:

cephfs - CephFS volume
csi - 容器儲存介面 (CSI)
fc - Fibre Channel (FC) 儲存
hostPath - HostPath 卷 (僅供單節點測試使用;不適用於多節點叢集;請嘗試使用 local 卷作為替代)
iscsi - iSCSI (SCSI over IP) 儲存
local - 節點上掛載的本地儲存裝置
nfs - 網路檔案系統 (NFS) 儲存
rbd - Rados 塊裝置 (RBD) 卷

3.4 持久卷的回收策略persistentVolumeReclaimPolicy

當用戶不再使用其儲存卷時,他們可以從 API 中將 PVC 物件刪除, 從而允許該資源被回收再利用。PersistentVolume 物件的回收策略告訴叢集, 當其被從申領中釋放時如何處理該資料卷。 目前,資料卷可以被 Retained(保留)、Recycled(回收)或 Deleted(刪除)。

保留(Retain):回收策略 Retain 使得使用者可以手動回收資源。當 PersistentVolumeClaim 物件被刪除時,PersistentVolume 卷仍然存在,對應的資料卷被視為"已釋放(released)"。 由於捲上仍然存在這前一申領人的資料,該卷還不能用於其他申領。 管理員可以通過下面的步驟來手動回收該卷:

刪除 PersistentVolume 物件。與之相關的、位於外部基礎設施中的儲存資產 (例如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)在 PV 刪除之後仍然存在。根據情況,手動清除所關聯的儲存資產上的資料。手動刪除所關聯的儲存資產。如果你希望重用該儲存資產,可以基於儲存資產的定義建立新的 PersistentVolume 卷物件。

刪除(Delete):對於支援 Delete 回收策略的卷外掛,刪除動作會將 PersistentVolume 物件從 Kubernetes 中移除,同時也會從外部基礎設施(如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)中移除所關聯的儲存資產。 動態製備的卷會繼承其 StorageClass 中設定的回收策略, 該策略預設為 Delete。管理員需要根據使用者的期望來配置 StorageClass; 否則 PV 卷被建立之後必須要被編輯或者修補。 參閱更改 PV 卷的回收策略。

回收(Recycle):警告: 回收策略 Recycle 已被廢棄。取而代之的建議方案是使用動態製備。如果下層的卷外掛支援,回收策略 Recycle 會在捲上執行一些基本的擦除 (rm -rf /thevolume/*)操作,之後允許該卷用於新的 PVC 申領。

簡言之:

  • 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)。

3.5 卷模式volumeMode

針對 PV 持久卷,Kubernetes 支援兩種卷模式(volumeModes):Filesystem(檔案系統) 和 Block(塊)。 volumeMode 是一個可選的 API 引數。 如果該引數被省略,預設的卷模式是 Filesystem。

volumeMode 屬性設定為 Filesystem 的卷會被 Pod 掛載(Mount) 到某個目錄。 如果卷的儲存來自某塊裝置而該裝置目前為空,Kuberneretes 會在第一次掛載卷之前在裝置上建立檔案系統。

你可以將 volumeMode 設定為 Block,以便將卷作為原始塊裝置來使用。 這類卷以塊裝置的方式交給 Pod 使用,其上沒有任何檔案系統。 這種模式對於為 Pod 提供一種使用最快可能方式來訪問卷而言很有幫助, Pod 和卷之間不存在檔案系統層。另外,Pod 中執行的應用必須知道如何處理原始塊裝置。

3.6 訪問模式 accessModes

PersistentVolume 卷可以用資源提供者所支援的任何方式掛載到宿主系統上。 如下表所示,提供者(驅動)的能力不同,每個 PV 卷的訪問模式都會設定為對應卷所支援的模式值。 例如,NFS 可以支援多個讀寫客戶,但是某個特定的 NFS PV 卷可能在伺服器上以只讀的方式匯出。 每個 PV 卷都會獲得自身的訪問模式集合,描述的是特定 PV 卷的能力。

訪問模式accessModes有:

  • ReadWriteOnce:卷可以被一個節點以讀寫方式掛載。 ReadWriteOnce 訪問模式也允許執行在同一節點上的多個 Pod 訪問卷。
  • ReadOnlyMany:卷可以被多個節點以只讀方式掛載。
  • ReadWriteMany:卷可以被多個節點以讀寫方式掛載。
  • ReadWriteOncePod:卷可以被單個 Pod 以讀寫方式掛載。 如果你想確保整個叢集中只有一個 Pod 可以讀取或寫入該 PVC, 請使用 ReadWriteOncePod 訪問模式。這隻支援 CSI 卷以及需要 Kubernetes 1.22 以上版本。

說明:Kubernetes 使用卷訪問模式來匹配 PersistentVolumeClaim 和 PersistentVolume。 在某些場合下,卷訪問模式也會限制 PersistentVolume 可以掛載的位置。 卷訪問模式並不會在儲存已經被掛載的情況下為其實施防寫。 即使訪問模式設定為 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany,它們也不會對卷形成限制。 例如,即使某個卷建立時設定為 ReadOnlyMany,也無法保證該卷是隻讀的。 如果訪問模式設定為 ReadWriteOncePod,則卷會被限制起來並且只能掛載到一個 Pod 上。

重要提醒! 每個卷同一時刻只能以一種訪問模式掛載,即使該卷能夠支援多種訪問模式。 例如,一個 GCEPersistentDisk 卷可以被某節點以 ReadWriteOnce 模式掛載,或者被多個節點以 ReadOnlyMany 模式掛載,但不可以同時以兩種模式掛載。

在命令列介面(CLI)中,訪問模式也使用以下縮寫形式:

  • RWO - ReadWriteOnce
  • ROX - ReadOnlyMany
  • RWX - ReadWriteMany
  • RWOP - ReadWriteOncePod

3.7 儲存類storageClass

每個 PV 可以屬於某個類(Class),通過將其 storageClassName 屬性設定為某個 StorageClass 的名稱來指定。 特定類的 PV 卷只能繫結到請求該類儲存卷的 PVC 申領。 未設定 storageClassName 的 PV 卷沒有類設定,只能繫結到那些沒有指定特定儲存類的 PVC 申領。

早前,Kubernetes 使用註解 volume.beta.kubernetes.io/storage-class 而不是 storageClassName 屬性。這一註解目前仍然起作用,不過在將來的 Kubernetes 釋出版本中該註解會被徹底廢棄。

3.8 持久卷狀態PersistentVolume status

持久卷狀態PersistentVolume status如下:

[root@k8scloude1 volume]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM          STORAGECLASS   REASON   AGE
pv007   5Gi        RWO            Recycle          Released   volume/mypvc   secret                  75m

每個pv卷會處於以下狀態之一

  • Available(可用)-- 卷是一個空閒資源,尚未繫結到任何申領;
  • Bound(已繫結)-- 該卷已經繫結到某申領;
  • Released(已釋放)-- 所繫結的申領已被刪除,但是資源尚未被叢集回收;
  • Failed(失敗)-- 卷的自動回收操作失敗。

命令列介面能夠顯示繫結到某 PV 卷的 PVC 物件(CLAIM欄位)。

pv全域性有效,不限於某個namespace

四.持久卷申領PersistentVolumeClaim(PVC)

每個 PVC 物件都有 spec 和 status 部分,分別對應申領的規約和狀態。 PersistentVolumeClaim 物件的名稱必須是合法的 DNS 子域名。

訪問模式:申領在請求具有特定訪問模式的儲存時,使用與卷相同的訪問模式約定。

卷模式:申領使用與卷相同的約定來表明是將卷作為檔案系統還是塊裝置來使用。

資源:申領和 Pod 一樣,也可以請求特定數量的資源。在這個上下文中,請求的資源是儲存。 卷和申領都使用相同的 資源模型。

選擇算符:申領可以設定標籤選擇算符 來進一步過濾卷集合。只有標籤與選擇算符相匹配的卷能夠繫結到申領上。 選擇算符包含兩個欄位:

  • matchLabels - 卷必須包含帶有此值的標籤
  • matchExpressions - 通過設定鍵(key)、值列表和操作符(operator) 來構造的需求。合法的操作符有 In、NotIn、Exists 和 DoesNotExist。

來自 matchLabels 和 matchExpressions 的所有需求都按邏輯與的方式組合在一起。 這些需求都必須被滿足才被視為匹配。

儲存類storageClass:申領可以通過為 storageClassName 屬性設定 StorageClass 的名稱來請求特定的儲存類。 只有所請求的類的 PV 卷,即 storageClassName 值與 PVC 設定相同的 PV 卷, 才能繫結到 PVC 申領。

PVC 申領不必一定要請求某個類。如果 PVC 的 storageClassName 屬性值設定為 "", 則被視為要請求的是沒有設定儲存類的 PV 卷,因此這一 PVC 申領只能繫結到未設定儲存類的 PV 卷(未設定註解或者註解值為 "" 的 PersistentVolume(PV)物件在系統中不會被刪除, 因為這樣做可能會引起資料丟失。未設定 storageClassName 的 PVC 與此大不相同, 也會被叢集作不同處理。具體篩查方式取決於 DefaultStorageClass 准入控制器外掛 是否被啟用。

如果准入控制器外掛被啟用,則管理員可以設定一個預設的 StorageClass。 所有未設定 storageClassName 的 PVC 都只能繫結到隸屬於預設儲存類的 PV 卷。 設定預設 StorageClass 的工作是通過將對應 StorageClass 物件的註解 storageclass.kubernetes.io/is-default-class 賦值為 true 來完成的。 如果管理員未設定預設儲存類,叢集對 PVC 建立的處理方式與未啟用准入控制器外掛時相同。 如果設定的預設儲存類不止一個,准入控制外掛會禁止所有建立 PVC 操作。
如果准入控制器外掛被關閉,則不存在預設 StorageClass 的說法。 所有將 storageClassName 設為 "" 的 PVC 只能被繫結到也將 storageClassName 設為 "" 的 PV。 不過,只要預設的 StorageClass 可用,就可以稍後更新缺少 storageClassName 的 PVC。 如果這個 PVC 更新了,它將不再繫結到也將 storageClassName 設為 "" 的 PV。

取決於安裝方法,預設的 StorageClass 可能在叢集安裝期間由外掛管理器(Addon Manager)部署到叢集中。

當某 PVC 除了請求 StorageClass 之外還設定了 selector,則這兩種需求會按邏輯與關係處理: 只有隸屬於所請求類且帶有所請求標籤的 PV 才能繫結到 PVC。

說明: 目前,設定了非空 selector 的 PVC 物件無法讓叢集為其動態製備 PV 卷。
早前,Kubernetes 使用註解 volume.beta.kubernetes.io/storage-class 而不是 storageClassName 屬性。這一註解目前仍然起作用,不過在將來的 Kubernetes 釋出版本中該註解會被徹底廢棄。

PVC不是全域性生效的,只在一個namespace裡生效

五.建立NFS持久卷

5.1 配置NFS服務端以及共享目錄

在一臺機器上安裝NFS服務端,k8s的兩個worker安裝NFS客戶端。

etcd1機器作為NFS的服務端,安裝NFS。

[root@etcd1 ~]# yum -y install nfs-utils

[root@etcd1 ~]# rpm -qa | grep nfs
libnfsidmap-0.25-19.el7.x86_64
nfs-utils-1.3.0-0.68.el7.2.x86_64

啟動NFS

#使nfs開機自啟動並現在就啟動
[root@etcd1 ~]# systemctl enable nfs-server --now
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.

#檢視nfs狀態
[root@etcd1 ~]# systemctl status nfs-server 
● nfs-server.service - NFS server and services
   Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; enabled; vendor preset: disabled)
   Active: active (exited) since 二 2022-01-18 17:24:24 CST; 8s ago
  Process: 1469 ExecStartPost=/bin/sh -c if systemctl -q is-active gssproxy; then systemctl reload gssproxy ; fi (code=exited, status=0/SUCCESS)
  Process: 1453 ExecStart=/usr/sbin/rpc.nfsd $RPCNFSDARGS (code=exited, status=0/SUCCESS)
  Process: 1451 ExecStartPre=/usr/sbin/exportfs -r (code=exited, status=0/SUCCESS)
 Main PID: 1453 (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/nfs-server.service

1月 18 17:24:24 etcd1 systemd[1]: Starting NFS server and services...
1月 18 17:24:24 etcd1 systemd[1]: Started NFS server and services.

先在NFS服務端建立/persitdir,並把目錄/persitdir共享出去

#建立/persitdir作為共享目錄
[root@etcd1 ~]# mkdir /persitdir

[root@etcd1 ~]# vim /etc/exports

#把/persitdir目錄共享出去
[root@etcd1 ~]# cat /etc/exports
/persitdir *(rw,async,no_root_squash)

[root@etcd1 ~]# exportfs -arv
exporting *:/persitdir

建立檔案

[root@etcd1 ~]# touch /persitdir/{xx,yy,zz,ww}.txt

[root@etcd1 ~]# ls /persitdir/
ww.txt  xx.txt  yy.txt  zz.txt

5.2 配置NFS客戶端

在k8s叢集的worker節點安裝nfs的客戶端

[root@k8scloude3 ~]# yum -y install nfs-utils

 #安裝nfs的客戶端
[root@k8scloude2 ~]# yum -y install nfs-utils

檢視etcd1(192.168.110.133)機器共享出來的目錄是哪個?

[root@k8scloude2 ~]# showmount -e 192.168.110.133
Export list for 192.168.110.133:
/persitdir *

5.3 建立持久卷

PersistentVolume 和 docker 中的 Volume 概念類似,都是代表機器上的一塊儲存,而PersistentVolume 也被稱為叢集共享資源,PersistentVolumeClaim 則是使用者請對 pv 資源的請求。pv全域性有效,不限於某個namespace

檢視持久化儲存資料卷PV

[root@k8scloude1 volume]# kubectl get pv
No resources found

配置nfs型別的持久卷Persistent Volume,關於nfs資料卷請檢視部落格《Kubernetes(k8s)儲存管理之資料卷volumes(三):NFS資料卷》https://www.cnblogs.com/renshengdezheli/p/16971943.html

[root@k8scloude1 volume]# vim persistentv.yaml

[root@k8scloude1 volume]# cat persistentv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv007
spec:
  #pv的大小
  capacity:
    storage: 5Gi
  #PV的卷模式
  volumeMode: Filesystem
  #PV的訪問模式
  accessModes:
    - ReadWriteOnce
  #PV的回收策略
  persistentVolumeReclaimPolicy: Recycle
  #storageClassName: slow
  #PV的型別為nfs
  nfs:
    #nfs共享目錄
    path: /persitdir
    #nfs伺服器地址
    server: 192.168.110.133

建立持久卷Persistent Volume

[root@k8scloude1 volume]# kubectl apply -f persistentv.yaml 
persistentvolume/pv007 created

檢視持久卷Persistent Volume

[root@k8scloude1 volume]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv007   5Gi        RWO            Recycle          Available                                   10s

pv全域性有效,不限於某個namespace

[root@k8scloude1 volume]# kubectl get pv -n default
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv007   5Gi        RWO            Recycle          Available      
                             95s
[root@k8scloude1 volume]# kubectl get pv -n ns1
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv007   5Gi        RWO            Recycle          Available                                   101s

5.4 建立持久卷申領PersistentVolumeClaim

PersistentVolumeClaim(簡稱PVC)是使用者儲存的請求,PVC消耗PV的資源,可以請求特定的大小和訪問模式,需要指定歸屬於某個Namespace,在同一個Namespace的Pod才可以指定對應的PVC。當需要不同性質的PV來滿足儲存需求時,可以使用StorageClass來實現。

PVC不是全域性生效的,只在一個namespace裡生效。

檢視持久化儲存卷宣告pvc

[root@k8scloude1 volume]# kubectl get pvc
No resources found in volume namespace.

配置pvc

[root@k8scloude1 volume]# vim pvc1.yaml

[root@k8scloude1 volume]# cat pvc1.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc
spec:
  #訪問模式
  accessModes:
    - ReadWriteOnce
  #卷模式
  volumeMode: Filesystem
  #請求的儲存大小
  resources:
    requests:
      storage: 3Gi
  #storageClassName: slow

建立pvc

[root@k8scloude1 volume]# kubectl apply -f pvc1.yaml 
persistentvolumeclaim/mypvc created

注意:pvc和PV之間的關聯主要靠引數:CAPACITY ,ACCESS MODES

[root@k8scloude1 volume]# kubectl get pvc
NAME    STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc   Bound    pv007    5Gi        RWO                           11s

PVC不是全域性生效的,只在一個namespace裡生效。

[root@k8scloude1 volume]# kubectl get pvc -n default
No resources found in default namespace.

在default名稱空間建立pvc

[root@k8scloude1 volume]# kubectl apply -f pvc1.yaml -n default
persistentvolumeclaim/mypvc created

因為此時pvc已經被volume的名稱空間裡的pv關聯在一起,現在不能在default名稱空間關聯pv

[root@k8scloude1 volume]# kubectl get pvc -n default
NAME    STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc   Pending                                                     3s

[root@k8scloude1 volume]# kubectl get pvc -n default
NAME    STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc   Pending                                                     2m1s

[root@k8scloude1 volume]# kubectl delete -f pvc1.yaml -n default
persistentvolumeclaim "mypvc" deleted

[root@k8scloude1 volume]# kubectl get pvc -n default
No resources found in default namespace.

5.5 新增儲存類storageClass

注意:pvc和PV之間的關聯主要靠引數:1.CAPACITY:pvc裡的要求容量要小於等於pv裡的容量 ,2.ACCESS MODES:必須相同, 3.STORAGECLASS不一樣的話,pv和PVC也關聯不起來。

CLAIM:volume/mypvc 可以看到mypvc已經和pv007關聯在一起了。

[root@k8scloude1 volume]# kubectl get pvc 
NAME    STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc   Bound    pv007    5Gi        RWO                           5m31s

[root@k8scloude1 volume]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM          STORAGECLASS   REASON   AGE
pv007   5Gi        RWO            Recycle          Bound    volume/mypvc                           16m

配置PersistentVolume

[root@k8scloude1 volume]# vim persistentv.yaml 

#設定storageClassName: secret
[root@k8scloude1 volume]# cat persistentv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv007
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: secret
  nfs:
    path: /persitdir
    server: 192.168.110.133

配置PersistentVolumeClaim

[root@k8scloude1 volume]# vim pvc1.yaml 

#設定storageClassName: secret
[root@k8scloude1 volume]# cat pvc1.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 3Gi
  storageClassName: secret

建立PV和PVC,可以看到STORAGECLASS是一樣的

[root@k8scloude1 volume]# kubectl apply -f persistentv.yaml 
persistentvolume/pv007 configured

[root@k8scloude1 volume]# kubectl apply -f pvc1.yaml 
persistentvolumeclaim/mypvc created

[root@k8scloude1 volume]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM          STORAGECLASS   REASON   AGE
pv007   5Gi        RWO            Recycle          Released   volume/mypvc   secret                  75m

[root@k8scloude1 volume]# kubectl get pvc
NAME    STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc   Pending                                      secret         16s
[root@k8scloude1 volume]# kubectl get pvc
NAME    STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc   Bound    pv007    5Gi        RWO            secret         25s

可以檢視PV的詳細描述資訊,比如NFS伺服器地址和目錄

[root@k8scloude1 volume]# kubectl describe pv pv007 
Name:            pv007
Labels:          <none>
Annotations:     pv.kubernetes.io/bound-by-controller: yes
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    secret
Status:          Bound
Claim:           volume/mypvc
Reclaim Policy:  Recycle
Access Modes:    RWO
VolumeMode:      Filesystem
Capacity:        5Gi
Node Affinity:   <none>
Message:         
Source:
    Type:      NFS (an NFS mount that lasts the lifetime of a pod)
    Server:    192.168.110.133
    Path:      /persitdir
    ReadOnly:  false
Events:
  Type    Reason          Age   From                         Message
  ----    ------          ----  ----                         -------
  Normal  RecyclerPod     91s   persistentvolume-controller  Recycler pod: Successfully assigned default/recycler-for-pv007 to k8scloude2
  Normal  RecyclerPod     89s   persistentvolume-controller  Recycler pod: Pulling image "busybox:1.27"
  Normal  RecyclerPod     71s   persistentvolume-controller  Recycler pod: Successfully pulled image "busybox:1.27" in 18.377762222s
  Normal  RecyclerPod     71s   persistentvolume-controller  Recycler pod: Created container pv-recycler
  Normal  RecyclerPod     71s   persistentvolume-controller  Recycler pod: Started container pv-recycler
  Normal  VolumeRecycled  70s   persistentvolume-controller  Volume recycled

刪除pvc之後,pv的狀態由Bound變為Available

[root@k8scloude1 volume]# kubectl delete -f pvc1.yaml 
persistentvolumeclaim "mypvc" deleted

[root@k8scloude1 volume]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv007   5Gi        RWO            Recycle          Available           secret                  80m

刪除pvc之後,NFS服務端的 /persitdir/ 這個目錄下檔案沒了 ,persistentVolumeReclaimPolicy: Recycle pv的回收策略:Recycle表示只要pvc被刪除,對應的資料也會被刪除

[root@etcd1 ~]# ls /persitdir/

5.6 修改persistentVolume的回收策略

在NFS服務端建立檔案

[root@etcd1 ~]# touch /persitdir/{xx,yy,zz,ww}.txt

[root@etcd1 ~]# ls /persitdir/
ww.txt  xx.txt  yy.txt  zz.txt

配置PersistentVolume

[root@k8scloude1 volume]# vim persistentv.yaml 

#persistentVolumeReclaimPolicy: Retain  Retain表示pvc被刪除之後,也要保留對應的資料 
[root@k8scloude1 volume]# cat persistentv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv007
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: secret
  nfs:
    path: /persitdir
    server: 192.168.110.133

建立pv,PVC

[root@k8scloude1 volume]# kubectl apply -f persistentv.yaml 
persistentvolume/pv007 created

[root@k8scloude1 volume]# kubectl apply -f pvc1.yaml 
persistentvolumeclaim/mypvc created

[root@k8scloude1 volume]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM          STORAGECLASS   REASON   AGE
pv007   5Gi        RWO            Retain           Bound    volume/mypvc   secret                  44s

[root@k8scloude1 volume]# kubectl get pvc
NAME    STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc   Bound    pv007    5Gi        RWO            secret         8s

[root@k8scloude1 volume]# kubectl delete -f pvc1.yaml 
persistentvolumeclaim "mypvc" deleted

[root@k8scloude1 volume]# kubectl get pvc
No resources found in volume namespace.

RECLAIM POLICY:Retain ,STATUS:Released,STATUS:Released 表示pv仍然保留為被關聯狀態,即使重新建立一個相同的pvc也只會處於Pending狀態

[root@k8scloude1 volume]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM          STORAGECLASS   REASON   AGE
pv007   5Gi        RWO            Retain           Released   volume/mypvc   secret                  112s

在NFS服務端 /persitdir/ 資料依然存在

[root@etcd1 ~]# ls /persitdir/
ww.txt  xx.txt  yy.txt  zz.txt

建立PVC

[root@k8scloude1 volume]# kubectl apply -f pvc1.yaml 
persistentvolumeclaim/mypvc created

#PV的STATUS:Released  表示pv仍然保留為被關聯狀態,即使重新建立一個相同的pvc也只會處於Pending狀態
[root@k8scloude1 volume]# kubectl get pvc
NAME    STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc   Pending                                      secret         13s

[root@k8scloude1 volume]# kubectl delete -f pvc1.yaml 
persistentvolumeclaim "mypvc" deleted

[root@k8scloude1 volume]# kubectl get pvc
No resources found in volume namespace.

想正常使用PVC,只能刪除pv,然後重新建立PVC

[root@k8scloude1 volume]# kubectl delete -f persistentv.yaml 
persistentvolume "pv007" deleted

[root@k8scloude1 volume]# kubectl get pv
No resources found

pv被刪除了,NFS服務端/persitdir/ 資料依然存在沒有影響

[root@etcd1 ~]# ls /persitdir/
ww.txt  xx.txt  yy.txt  zz.txt

現在重新建立PV和PVC即可

[root@k8scloude1 volume]# kubectl apply -f persistentv.yaml 
persistentvolume/pv007 created

[root@k8scloude1 volume]# kubectl apply -f pvc1.yaml 
persistentvolumeclaim/mypvc created

[root@k8scloude1 volume]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM          STORAGECLASS   REASON   AGE
pv007   5Gi        RWO            Retain           Bound    volume/mypvc   secret                  10s

[root@k8scloude1 volume]# kubectl get pvc
NAME    STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc   Bound    pv007    5Gi        RWO            secret         7s

六.建立有NFS持久卷的pod

那我們的pod怎麼使用pvc呢?配置pod把PVC掛載到容器的/xx目錄

[root@k8scloude1 volume]# vim pvcpod.yaml 

[root@k8scloude1 volume]# cat pvcpod.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pvcshare
  name: pvcshare
spec:
  #nodeName指定pod執行在k8scloude3節點
  nodeName: k8scloude3
  terminationGracePeriodSeconds: 0
  volumes:
  - name: v1
    #卷型別為PVC
    persistentVolumeClaim:
      claimName: mypvc
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: h1
    resources: {}
    volumeMounts:
    - name: v1
      mountPath: /xx
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

建立pod

[root@k8scloude1 volume]# kubectl apply -f pvcpod.yaml 
pod/pvcshare created

[root@k8scloude1 volume]# kubectl get pod -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
pvcshare   1/1     Running   0          14s   10.244.251.255   k8scloude3   <none>           <none>

檢視pod的詳細描述資訊

[root@k8scloude1 volume]# kubectl describe pod pvcshare | grep -A10 Volumes
Volumes:
  v1:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  mypvc
    ReadOnly:   false
  kube-api-access-4kd64:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true

檢視PV的詳細描述資訊

[root@k8scloude1 volume]# kubectl describe pv pv007 
Name:            pv007
Labels:          <none>
Annotations:     pv.kubernetes.io/bound-by-controller: yes
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    secret
Status:          Bound
Claim:           volume/mypvc
Reclaim Policy:  Retain
Access Modes:    RWO
VolumeMode:      Filesystem
Capacity:        5Gi
Node Affinity:   <none>
Message:         
Source:
    Type:      NFS (an NFS mount that lasts the lifetime of a pod)
    Server:    192.168.110.133
    Path:      /persitdir
    ReadOnly:  false
Events:        <none>

進入pod

[root@k8scloude1 volume]# kubectl exec -it pvcshare -- bash
#pod裡也有對應的檔案
root@pvcshare:/# ls /xx/
ww.txt	xx.txt	yy.txt	zz.txt
root@pvcshare:/# exit
exit

刪除pod,pvc,pv

[root@k8scloude1 volume]# kubectl delete pod pvcshare --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "pvcshare" force deleted

[root@k8scloude1 volume]# kubectl delete pvc mypvc 
persistentvolumeclaim "mypvc" deleted

[root@k8scloude1 volume]# kubectl delete pv pv007 
persistentvolume "pv007" deleted

[root@k8scloude1 volume]# kubectl get pod
No resources found in volume namespace.

[root@k8scloude1 volume]# kubectl get pvc
No resources found in volume namespace.

[root@k8scloude1 volume]# kubectl get pv
No resources found

目前建立持久卷Persistent Volume使用的是靜態製備(叢集管理員建立若干 PV 卷。這些卷物件帶有真實儲存的細節資訊, 並且對叢集使用者可用。PV 卷物件存在於 Kubernetes API 中,可供使用者消費使用),簡言之就是需要先建立pv,然後才能建立PVC,我們可以使用儲存類StorageClass實現動態製備,關於動態製備詳細內容請檢視部落格《動態製備-儲存類StorageClass》。