一篇文章讀懂K8S的PV和PVC以及實踐攻略
1 概念
1.1 什么是存儲卷?
在容器化環(huán)境中,因為容器的生命周期是臨時的,所以伴隨產(chǎn)生的數(shù)據(jù)默認(rèn)也是臨時的。當(dāng)容器重啟或崩潰后,其內(nèi)部數(shù)據(jù)將丟失。因此,Kubernetes 引入了存儲卷(Volume),為應(yīng)用提實現(xiàn)數(shù)據(jù)持久化的能力。
1.2 存儲卷的類型與使用場景
存儲類型 | 描述 | 適用場景 |
---|---|---|
emptyDir | Pod 生命周期內(nèi)的臨時存儲 | 適合臨時數(shù)據(jù)存儲,如緩存、臨時文件等。 |
hostPath | 將宿主機(jī)上的文件系統(tǒng)目錄掛載到Pod中。 | 適用于需要訪問宿主機(jī)文件系統(tǒng)的場景,但可能會帶來宿主機(jī)與Pod間的緊耦合問題,影響Pod的調(diào)度靈活性。 |
NFS | 使用網(wǎng)絡(luò)文件系統(tǒng)協(xié)議進(jìn)行數(shù)據(jù)共享,適合多Pod之間共享數(shù)據(jù)。 | 多個 Pod 共享訪問同一文件,適合數(shù)據(jù)共享、日志收集等。 |
塊存儲 | 直接使用云服務(wù)提供的塊存儲,支持動態(tài)創(chuàng)建和掛載。 | 適合在云上部署的生產(chǎn)環(huán)境,支持持久性和自動擴(kuò)展。 |
分布式文件系統(tǒng) | 這些分布式文件系統(tǒng)適合在高可用性和大規(guī)模集群中使用,提供更好的性能和冗余支持。 | 企業(yè)級應(yīng)用、大數(shù)據(jù)處理等場景。 |
1.3 存儲類(Storage Class)
在 Kubernetes 中,存儲類是一個抽象,讓用戶無需提前準(zhǔn)備 PV,而是根據(jù)需要由集群自動分配存儲。StorageClass 決定了如何創(chuàng)建、配置和管理存儲卷(如云盤、本地盤、NFS 等),實現(xiàn)按需動態(tài)分配。
簡單來說,StorageClass就是一個存儲策略模板,用戶通過它告訴 Kubernetes:“我需要的存儲資源符合這些規(guī)則,請幫我動態(tài)生成合適的存儲卷。”
1.4 PV(Persistent Volume)
PV 是集群中的一個存儲資源,可以由管理員創(chuàng)建或使用存儲類動態(tài)創(chuàng)建,并定義了存儲容量、訪問模式、后端存儲等規(guī)則。
以下是PV的特性:
- 生命周期獨立于 Pod,不會因為 Pod 刪除而消失。
- PV 是集群級的資源,管理員負(fù)責(zé)創(chuàng)建。
- 支持多種存儲類型,如本地磁盤、NFS、Cephfs等。
- 支持不同的訪問模式,如
ReadWriteOnce
(一次只能一個 Pod 寫入)和ReadWriteMany
(多個 Pod 可同時寫入)。
1.5 PVC (Persistent Volume Claim)
PVC 是用戶對持久存儲的請求聲明,它規(guī)定了存儲容量和訪問權(quán)限等需求,并以一種抽象方法通知Kubernetes 集群,再由Kubernetes 自動匹配合適的 PV,并進(jìn)行綁定。這樣對用戶屏蔽了后端存儲,實現(xiàn)存儲統(tǒng)一管理。
以下是PVC的特性:
- PVC 解耦了應(yīng)用與存儲資源,使開發(fā)人員不需要直接處理具體的存儲細(xì)節(jié)。
- 如果沒有符合條件的 PV,PVC 會處于“待綁定”狀態(tài),直到管理員創(chuàng)建滿足條件的 PV。
- PVC類似于 Pod, Pod 消耗節(jié)點資源(CPU和內(nèi)存),PVC 消耗 PV 資源,通常與PV是1對1的關(guān)系。
1.6 動態(tài)卷(Dynamic Volume Provisioning)
PV由管理員提前創(chuàng)建提供給用戶使用,稱為靜態(tài)卷。
當(dāng)用戶在提交 PVC 時,K8S 根據(jù) StorageClass 自動創(chuàng)建 PV,而不需要管理員提前準(zhǔn)備好存儲卷,稱為動態(tài)卷。
當(dāng)然,如果要實現(xiàn)動態(tài)卷, 必須設(shè)置存儲類,否則Kubernetes無法創(chuàng)建PV,如果PVC設(shè)置storageClassName
字段為“”,也不會自動創(chuàng)建動態(tài)卷。
1.7 PV、PVC 與后端存儲的關(guān)系
以“租房場景”來說明StorageClass、PV、PVC 與后端存儲之間的關(guān)系。
- 后端存儲: 物業(yè)公司(如 NFS、AWS EBS 等)是所有房源的真正提供者。它們負(fù)責(zé)實際存儲資源的供應(yīng),例如:云存儲、NFS、本地磁盤。
- StorageClass: 類似租房平臺上的房型模板。它定義了不同租房規(guī)則,比如:標(biāo)準(zhǔn)單間(普通低成本存儲)、豪華公寓(高性能大容量存儲)、短租房(臨時存儲)。用戶在提交租房申請(PVC)時,可以指定采用哪種房型模板(StorageClass)。根據(jù)這個模板,平臺會自動生成實際的房源(PV)。
- PV: 類似已經(jīng)發(fā)布到平臺上的“具體房子”。每個 PV 是由后端存儲提供的資源,例如:某間20平方的單人房(塊存儲),或某間共享公寓(文件存儲)。
- PVC :租客提交的租房申請。它描述了租客希望租到的房屋類型和條件,例如:面積(容量)、入住規(guī)則(只允許一人入住,或帶寵物共?。⒎啃鸵螅ü?、小區(qū)、城中村)。Kubernetes 會根據(jù) PVC 提交的條件,自動匹配合適的 PV。如果沒有符合條件的 PV,系統(tǒng)會根據(jù) StorageClass 動態(tài)生成一個 PV,并綁定給 PVC。
2 實戰(zhàn):PV 和 PVC 的部署攻略
? 說明:以NFS作為后端存儲,驗證PV和PVC相關(guān)策略。
2.1 實驗準(zhǔn)備
- nfs server系統(tǒng): Ubuntu22.04
- Kubernetes環(huán)境: v1.29.7
2.2 部署NFS Server
安裝nfs-server
apt install -y nfs-kernel-server nfs-common
配置nfs, 把數(shù)據(jù)目錄掛著到ssd磁盤
sudo mkdir -p /ssd/data sudo chown nobody:nogroup /ssd/data sudo chmod 777 /ssd/data
編輯/etc/exports文件
/ssd/data *(rw,sync)
? 參數(shù)說明:
/ssd/data
:指定服務(wù)器上的共享目錄路徑。*
:表示允許所有的客戶端訪問該共享。如果是業(yè)務(wù)環(huán)境要求訪問限制,可以替換為特定的IP地址或子網(wǎng),例如 Kubernetes集群的網(wǎng)段。rw
:read-write,表示客戶端具有讀寫該共享目錄的權(quán)限。如果設(shè)置為ro
(read-only),則客戶端只能讀取數(shù)據(jù),無法寫入。sync
(同步寫入):表示所有對該共享目錄的寫入操作都將同步地寫入到磁盤上。客戶端發(fā)起的寫操作必須等到數(shù)據(jù)寫入磁盤后才會被確認(rèn)。如果配置為async
,則寫入操作會在數(shù)據(jù)實際寫入磁盤之前就返回,這樣會提高性能,但在系統(tǒng)崩潰時可能導(dǎo)致數(shù)據(jù)丟失。
重啟nfs服務(wù)
systemctl enable nfs-server systemctl restart nfs-server
查看nfs配置
exportfs -rv
輸出如下:
exportfs: /etc/exports [1]: Neither 'subtree_check' or 'no_subtree_check' specified for export "*:/ssd/data". Assuming default behaviour ('no_subtree_check'). NOTE: this default has changed since nfs-utils version 1.0.x exporting *:/ssd/data
- 證明配置成功
2.3 Master節(jié)點掛載測試
查看共享目錄
showmount -e 192.168.3.20
輸出如下:
Export list for 192.168.3.20: /ssd/data *
創(chuàng)建共享目錄 /mnt/share
mkdir /mnt/share
掛載nfs目錄
mount -t nfs 192.168.3.200:/ssd/data /mnt/share
創(chuàng)建測試文件
echo “test” > /mnt/share/test.txt
- 創(chuàng)建成功,證明寫入成功
卸載nfs共享目錄
umount /mnt/share
2.4 創(chuàng)建 PV和PVC
接下來我們基于 NFS存儲創(chuàng)建PV和PVC,驗證不同的策略 :
第一個PV和PVC:
apiVersion: v1 kind: PersistentVolume metadata: name: pv-rwo spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain nfs: path: /ssd/data server: 192.168.3.20 --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-rwo spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi
第二個PV和PVC:
apiVersion: v1 kind: PersistentVolume metadata: name: pv-rwx spec: capacity: storage: 1Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain nfs: path: /ssd/data server: 192.168.3.20 --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-rwx spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi
第三個PV和PVC:
apiVersion: v1 kind: PersistentVolume metadata: name: pv-rox spec: capacity: storage: 1Gi accessModes: - ReadOnlyMany persistentVolumeReclaimPolicy: Retain nfs: path: /ssd/data server: 192.168.3.20 --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-rox spec: accessModes: - ReadOnlyMany resources: requests: storage: 1Gi
? 參數(shù)說明:
- PV和PVC的volumeMode保持一致:Filesystem 模式:
- 當(dāng)
volumeMode
設(shè)置為Filesystem
(默認(rèn)值)
時,存儲卷會被掛載到Pod的一個目錄中。如果存儲卷是基于塊設(shè)備且設(shè)備為空,Kubernetes 會在第一次掛載前自動在設(shè)備上創(chuàng)建一個文件系統(tǒng)。 - 這種模式適合大多數(shù)應(yīng)用場景,用戶可以像使用普通文件系統(tǒng)一樣訪問存儲卷。
- 當(dāng)
volumeMode
設(shè)置為Block
時,存儲卷會作為一個原始塊設(shè)備提供給Pod,而不經(jīng)過文件系統(tǒng)層。這意味著該卷在Pod中被暴露為一個塊設(shè)備。 - 這種模式適合需要直接訪問塊存儲的應(yīng)用,如數(shù)據(jù)庫或需要最高I/O性能的應(yīng)用,但應(yīng)用程序必須能夠處理原始塊設(shè)備的數(shù)據(jù)管理。
- 當(dāng)
- PV和PVC的accessModes保持一致:
訪問模式 | 縮寫 | 描述 | 典型使用場景 |
---|---|---|---|
ReadWriteOnce | RWO | 該存儲卷可以被一個節(jié)點上的Pod以讀寫方式掛載。當(dāng) Pod 在同一節(jié)點上運行時,ReadWriteOnce 訪問模式仍然可以允許多個 Pod 訪問該卷。 | 適用于單實例應(yīng)用,如數(shù)據(jù)庫(MySQL、PostgreSQL)。 |
ReadOnlyMany | ROX | 該存儲卷可以被多個節(jié)點上的多個Pod以只讀方式掛載。 | 適用于需要共享靜態(tài)內(nèi)容的場景,如配置文件或日志查看。 |
ReadWriteMany | RWX | 該存儲卷可以被多個節(jié)點上的多個Pod以讀寫方式掛載。 | 適用于需要多節(jié)點并發(fā)讀寫的場景,如共享文件存儲。 |
ReadWriteOncePod | RWOP | 該存儲卷只能被一個Pod以讀寫方式掛載,即使在同一節(jié)點上也不能被其他Pod掛載。 1.22+ 版本后支持。 | 用于增強(qiáng)Pod間的獨占資源訪問,防止多個Pod競爭使用。 |
- PV的ReclaimPolicy
回收策略 | 描述 | 適用場景 |
---|---|---|
Retain | 保留數(shù)據(jù),即使PVC被刪除,PV中的數(shù)據(jù)仍會被保留,需要手動清理或重新綁定PVC。 | 適用于需要數(shù)據(jù)持久保留的場景,如數(shù)據(jù)庫或備份存儲。 |
Delete | 刪除PV和存儲資源。當(dāng)PVC被刪除時,Kubernetes會自動刪除PV及其對應(yīng)的存儲資源。 | 適用于臨時數(shù)據(jù)或不需要保留的數(shù)據(jù),如測試環(huán)境。 |
Recycle (已廢棄) | 清空數(shù)據(jù)并將PV重置為Available狀態(tài),以便被新的PVC綁定。此功能在Kubernetes 1.11之后已廢棄。 | 已不推薦使用,Kubernetes 1.11版本之前的舊集群可能仍支持。 |
創(chuàng)建三個PV和PVC
kubectl apply -f pv-rwo.yaml kubectl apply -f pv-rwm.yaml kubectl apply -f pv-rom.yaml
2.5 觀察PV和PVC的狀態(tài)
查看PV狀態(tài)
kubectl get pv
輸出如下:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE pv-rox 1Gi ROX Retain Available <unset> 11s pv-rwo 1Gi RWO Delete Available <unset> 106s pv-rwx 1Gi RWX Retain Available <unset> 42s
查看PVC狀態(tài)
kubectl get pvc
輸出如下:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE pvc-rox Bound pvc-e32cf856-b00b-4012-a25a-74c82ba8f092 1Gi ROX nfs-class <unset> 2m9s pvc-rwo Bound pvc-c864776b-5811-452f-9e98-f50466922be2 1Gi RWO nfs-class <unset> 3m44s pvc-rwx Bound pvc-7bebb579-5f8a-4994-a7a8-02bde0d651c2 1Gi RWX nfs-class <unset> 2m41s
? 說明:PV和PVC的生命周期
- PV的 生命周期狀態(tài)表:
生命周期階段 | 狀態(tài)描述 |
---|---|
Available | PV已創(chuàng)建且未綁定到任何PVC,表示可供PVC使用。 |
Bound | PV已綁定到一個PVC,表示正在被使用。 |
Released | PVC被刪除后,PV進(jìn)入Released狀態(tài),表示PV已經(jīng)釋放,但資源尚未被重新使用,數(shù)據(jù)仍可能存在。 |
Failed | PV無法綁定到PVC,或回收過程中出現(xiàn)錯誤。通常需要管理員手動干預(yù)修復(fù)。 |
Reclaim | 根據(jù)persistentVolumeReclaimPolicy 配置,PV的回收策略可以是Retain、Recycle或Delete。 |
- PVC的生命周期:
生命周期階段 | 狀態(tài)描述 |
---|---|
Pending | PVC已創(chuàng)建,但尚未找到合適的PV進(jìn)行綁定。 |
Bound | PVC已成功綁定到一個PV,存儲資源可以被Pod使用。 |
Lost | PV被刪除或失效,PVC進(jìn)入Lost狀態(tài),表示無法繼續(xù)訪問存儲資源。通常需要管理員處理。 |
2.6 Pod掛載不同PVC測試
2.6.1 創(chuàng)建Pod并掛載ReadWriteOnce的PV
將PVC pvc-rwo
掛載到nginx1:
apiVersion: v1 kind: Pod metadata: name: nginx1 spec: containers: - name: nginx1 image: harbor.zx/hcie/nginx:1.27.1 imagePullPolicy: IfNotPresent volumeMounts: - mountPath: "/usr/share/nginx/html" name: my-config volumes: - name: my-configvim persistentVolumeClaim: claimName: pvc-rwo
創(chuàng)建pod
kubectl apply -f nginx1.yaml
嘗試再創(chuàng)建一個Pod nginx2
,使用同一個PVC,觀察PVC掛載情況。
apiVersion: v1 kind: Pod metadata: name: nginx2 spec: containers: - name: nginx2 image: harbor.zx/hcie/nginx:1.27.1 imagePullPolicy: IfNotPresent volumeMounts: - mountPath: "/usr/share/nginx/html" name: my-config volumes: - name: my-config persistentVolumeClaim: claimName: pvc-rwo
查看pod的狀態(tài)
kubectl get pod -owide
輸出如下:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx1 1/1 Running 0 66m 172.16.135.207 k8s-master3 <none> <none> nginx2 1/1 Running 0 61m 172.16.126.55 k8s-worker2 <none> <none>
? 思考: 測試發(fā)現(xiàn),無論nginx1與nginx2運行在同一工作節(jié)點或不同工作節(jié)點上都能正常讀寫。
- 這里推測,雖然Kubernetes的
ReadWriteOnce
模式限制了跨節(jié)點的讀寫訪問,但某些存儲系統(tǒng)(如NFS)本身是支持多節(jié)點并發(fā)訪問的。因此即使Kubernetes中的訪問模式配置為ReadWriteOnce
,NFS協(xié)議也不強(qiáng)制執(zhí)行這種訪問限制。
2.6.2 創(chuàng)建Pod并掛載ReadWriteOncePod的PV
現(xiàn)在將nginx1、nginx2刪除:
kubectl delete -f nginx1.yaml kubectl delete -f nginx2.yaml kubectl delete -f pv-rwo.yaml
將第一個PV和PVC的策略改為ReadWriteOncePod
apiVersion: v1 kind: PersistentVolume metadata: name: pv-rwo spec: capacity: storage: 1Gi accessModes: - ReadWriteOncePod persistentVolumeReclaimPolicy: Retain nfs: path: /ssd/data server: 192.168.3.20 --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-rwo spec: accessModes: - ReadWriteOncePod resources: requests: storage: 1Gi
創(chuàng)建pv和pvc
kubectl apply -f pv-rwo.yaml
創(chuàng)建nginx1和nginx2
kubectl apply -f nginx1.yaml kubectl apply -f nginx2.yaml
查看pod
kubectl get pod
輸出如下:
NAME READY STATUS RESTARTS AGE nginx1 1/1 Running 0 67s nginx2 0/1 Pending 0 66s
- 這時nginx2狀態(tài)是
“Pending”
出現(xiàn)無法掛載的情況。
nginx2詳細(xì)信息如下:
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 12s default-scheduler 0/5 nodes are available: 1 node has pod using PersistentVolumeClaim with the same name and ReadWriteOncePod access mode, 4 node(s) didn't match Pod's node affinity/selector. preemption: 0/5 nodes are available: 1 No preemption victims found for incoming pod, 4 Preemption is not helpful for scheduling.
- 可以看到nginx2無法掛載是因為
ReadWriteOncePod
只允許一個Pod掛載。 - 為了做好存儲訪問控制,可以考慮使用其他存儲插件或者存儲系統(tǒng)。
- 另外,可以使用
ReadWriteOncePod
(RWOP)訪問模式來替代ReadWriteOnce
,該模式在Kubernetes 1.22及更高版本中可用,能夠限制PV只能被一個Pod掛載,即使在同一節(jié)點上也不允許其他Pod使用。
2.6.3 創(chuàng)建Pod并掛載ReadWriteMany的PV
現(xiàn)在將nginx1、nginx2刪除:
kubectl delete -f nginx1.yaml kubectl delete -f nginx2.yaml
修改成pv-rwx的pvc
volumes: - name: my-config persistentVolumeClaim: claimName: pvc-rwx
重新創(chuàng)建nginx1、nginx2
kubectl apply -f nginx1.yaml kubectl apply -f nginx2.yaml
nginx1測試讀寫
[root@k8s-master1 ~]# kubectl exec -it nginx1 -- bash root@nginx1:/# echo "nginx1" >>/usr/share/nginx/html/nginx1 root@nginx1:/# cat /usr/share/nginx/html/nginx1 nginx1
nginx2測試讀寫
[root@k8s-master1 ~]# kubectl exec -it nginx2 -- bash root@nginx2:/# echo "nginx2" >>/usr/share/nginx/html/nginx2 root@nginx2:/# cat /usr/share/nginx/html/nginx2 nginx2
- 證明一個pv可以共享掛載給多個Pod。
2.6.4 創(chuàng)建Pod并掛載ReadOnlyMany的PV
現(xiàn)在將nginx1、nginx2刪除:
kubectl delete -f nginx1.yaml kubectl delete -f nginx2.yaml
Pod修改成pv-rox的pvc
containers: - name: nginx1 image: harbor.zx/hcie/nginx:1.27.1 imagePullPolicy: IfNotPresent volumeMounts: - mountPath: "/usr/share/nginx/html" name: my-config readOnly: true volumes: - name: my-config persistentVolumeClaim: claimName: pvc-rox
重新創(chuàng)建nginx1、nginx2
kubectl apply -f nginx1.yaml kubectl apply -f nginx2.yaml
查看nginx1詳細(xì)信息,執(zhí)行以下命令:
kubectl describe pod nginx1
輸出如下:
Containers: nginx1: Container ID: containerd://28659839ee65b3be6579dd5d519ebcd89fefbf05e9908feb21b504728c19527a Image: harbor.zx/hcie/nginx:1.27.1 Image ID: harbor.zx/hcie/nginx@sha256:127262f8c4c716652d0e7863bba3b8c45bc9214a57d13786c854272102f7c945 Port: <none> Host Port: <none> State: Running Started: Thu, 17 Oct 2024 10:16:53 +0800 Ready: True Restart Count: 0 Environment: <none> Mounts: /usr/share/nginx/html from my-config (ro) /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-vcmlw (ro)
- 存儲卷是以只讀訪問方式掛載。
nginx1測試寫
[root@k8s-master1 ~]# kubectl exec -it nginx1 -- bash root@nginx1:/# echo "nginx1" >>/usr/share/nginx/html/nginx1
輸出如下:
bash: /usr/share/nginx/html/nginx1: Read-only file system
- 證明該存儲卷是只讀。
nginx2測試讀
[root@k8s-master1 ~]# kubectl exec -it nginx2 -- bash root@nginx2:/# cat /usr/share/nginx/html/nginx2 nginx2 root@nginx2:/# cat /usr/share/nginx/html/nginx1 nginx1
- 證明一個pv可以“只讀”方式共享給多個Pod
2.7 PV的回收策略測試
? 說明: 因為
Recycle
策略已經(jīng)被丟棄了, 所以只驗證Retain
和Delete
兩種策略類型。
登錄nfs-server,創(chuàng)建卷目錄
mkdir /ssd/data/{retain,delete}
編寫Retain卷文件
apiVersion: v1 kind: PersistentVolume metadata: name: pv-retain spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain nfs: path: /ssd/data/retain server: 192.168.3.20 --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-retain spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: ""
編寫Delete卷文件
apiVersion: v1 kind: PersistentVolume metadata: name: pv-delete spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Delete nfs: path: /ssd/data/delete server: 192.168.3.20 --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-delete spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: ""
創(chuàng)建存儲卷
kubectl apply -f pv-retain.yaml kubectl apply -f pv-delete.yaml
創(chuàng)建pod測試
apiVersion: v1 kind: Pod metadata: name: pod-retain spec: containers: - name: busybox image: harbor.zx/library/busybox:1.29-2 command: ["sh", "-c", "echo 'Hello from Retain' > /mnt/data/test.txt; sleep 3600"] volumeMounts: - mountPath: /mnt/data name: volume volumes: - name: volume persistentVolumeClaim: claimName: pvc-retain --- apiVersion: v1 kind: Pod metadata: name: pod-delete spec: containers: - name: busybox image: harbor.zx/library/busybox:1.29-2 command: ["sh", "-c", "echo 'Hello from Delete' > /mnt/data/test.txt; sleep 3600"] volumeMounts: - mountPath: /mnt/data name: volume volumes: - name: volume persistentVolumeClaim: claimName: pvc-delete
執(zhí)行以下命令創(chuàng)建兩個Pod:
kubectl apply -f pv-test.yaml
刪除pod
、pvc-retain
和pvc-delete
,觀察PV的狀態(tài)變化。
kubectl delete pod pod-retain kubectl delete pod pod-delete kubectl delete pvc pvc-retain kubectl delete pvc pvc-delete
觀察pv的回收狀態(tài),執(zhí)行以下命令:
kubectl get pv -w
輸出如下:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE 3m33s pv-retain 1Gi RWO Retain Bound default/pvc-reta in <unset> 3m34s ... pv-retain 1Gi RWO Retain Released default/pvc-reta in <unset> --- pv-delete 1Gi RWO Delete Bound default/pvc-dele te <unset> 4m42s ... pv-delete 1Gi RWO Delete Released default/pvc-dele te <unset> 4m41s pv-delete 1Gi RWO Delete Failed default/pvc-dele te <unset> 4m41s
- pv狀態(tài)從Bound到Released, 但是Delete策略回收nfs的存儲卷失敗。
查看nfs底層數(shù)據(jù)
root@ub22:/ssd/data# ls -l delete/ total 4 -rw-r--r-- 1 nobody nogroup 18 10月 17 11:27 test.txt root@ub22:/ssd/data# ls -l retain/ total 4 -rw-r--r-- 1 nobody nogroup 18 10月 17 11:27 test.txt
- 底層的數(shù)據(jù)沒有被刪除。
2.7.1 手動刪除并回收卷
查看pv-delete詳細(xì)信息
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning VolumeFailedDelete 6m2s persistentvolume-controller error getting deleter volume plugin for volume "pv-delete": no deletable volume plugin matched
- 因為我并沒有使用nfs的provider進(jìn)行管理導(dǎo)致,所以不支持nfs存儲卷刪除操作。
登錄NFS服務(wù)器,手動刪除PV對應(yīng)的目錄。例如:
# 登錄到NFS服務(wù)器,手動刪除目錄 rm -rf /ssd/data/delete
然后刪除PV資源:
kubectl delete pv pv-delete
或者,使用Finalizer強(qiáng)制刪除PV
- 如果PV已經(jīng)標(biāo)記為
Failed
,可以嘗試移除PV的finalizer
以強(qiáng)制刪除:kubectl patch pv pv-delete -p '{"metadata":{"finalizers":null}}'
3 總結(jié)
Kubernetes 通過PV和PVC的方式提供了后端存儲統(tǒng)一管理和靈活存儲的解決方案,在實際生產(chǎn)環(huán)境中,您可以根據(jù)業(yè)務(wù)需求選擇合適的存儲類型,并制定完善的數(shù)據(jù)備份方案,是確保系統(tǒng)穩(wěn)定運行的關(guān)鍵。
4 參考文獻(xiàn)
到此這篇關(guān)于K8S的PV和PVC以及實踐攻略的文章就介紹到這了,更多相關(guān)K8S的PV和PVC詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
K8s中Pod處于Pending狀態(tài)的八種原因分析
文章詳細(xì)介紹了Pod處于Pending狀態(tài)的八種常見原因,并提供了相應(yīng)的排查和解決方法,這些原因包括資源不足、調(diào)度約束、存儲依賴、鏡像問題、配額限制、網(wǎng)絡(luò)暗礁、系統(tǒng)級異常以及冷門陷阱,每種原因都附帶了具體的診斷方法和解決建議,感興趣的朋友一起看看吧2025-02-02關(guān)于Rancher部署并導(dǎo)入K8S集群的問題
這篇文章主要介紹了關(guān)于Rancher部署并導(dǎo)入K8S集群的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-12-12如何在 K8S 中使用 Values 文件定制不同環(huán)境下的應(yīng)用配置
Kubernetes是一個開源的容器編排平臺,它可以自動化容器的部署、擴(kuò)展和管理,在 K8s 中,應(yīng)用程序通常以容器的形式運行,這些容器被組織在不同的資源對象中,這篇文章主要介紹了如何在 K8S 中使用 Values 文件定制不同環(huán)境下的應(yīng)用配置,需要的朋友可以參考下2025-03-03K8s學(xué)習(xí)之Pod的定義及詳細(xì)資源調(diào)用案例
Kubernetes將所有內(nèi)容抽象為資源,通過操作資源管理集群,核心單元是Pod,通過控制器管理Pod,資源管理分為命令式對象管理、命令式對象配置和聲明式對象配置,各有適用場景,需要的朋友可以參考下2024-09-09Linux安裝Kubernetes(k8s)超詳細(xì)教程
Kubernetes是一個輕便的和可擴(kuò)展的開源平臺,用于管理容器化應(yīng)用和服務(wù),通過Kubernetes能夠進(jìn)行應(yīng)用的自動化部署和擴(kuò)縮容,這篇文章主要給大家介紹了關(guān)于Linux安裝Kubernetes(k8s)的相關(guān)資料,需要的朋友可以參考下2024-07-07詳解k8s ConfigMap 中 subPath 字段和 items
volumeMounts.subPath 屬性可用于指定所引用的卷內(nèi)的子路徑,而不是其根路徑,這篇文章主要介紹了詳解k8s ConfigMap 中 subPath 字段和 items 字段,需要的朋友可以參考下2023-03-03