07-持久化儲存和StorageClass
在k8s中部署的應用都是以pod容器的形式執行的,假如我們部署MySQL、Redis等資料庫,需要對這些資料庫產生的資料做備份。因為Pod是有生命週期的,如果pod不掛載資料卷,那pod被刪除或重啟後這些資料會隨之消失,如果想要長久的保留這些資料就要用到pod資料持久化儲存。
1、持久化儲存
我們可以通過下面的命令查詢Kubernetes的Pod支援哪些持久化儲存方案:
kubectl explain pods.spec.volumes
-
awsElasticBlockStore
:AWSElasticBlockStore 表示一個 AWS 磁碟資源,它附加到 kubelet 的主機,然後暴露給 pod。 -
azureDisk
:AzureDisk 表示主機上的 Azure 資料磁碟掛載,並將掛載繫結到 pod。 -
azureFile
:AzureFile 表示主機上的 Azure 檔案服務掛載,並將掛載繫結到 pod。 -
cephfs
:CephFS 表示主機上的 Ceph FS 掛載,共享 pod 的生命週期。 -
cinder
:Cinder 表示附加並安裝在 kubelets 主機上的 cinder 卷。 -
configMap
:ConfigMap 表示應該填充此卷的 configMap。 -
csi
:CSI(容器儲存介面)表示由某些外部 CSI 驅動程式(Beta 功能)處理的臨時儲存。 -
downwardAPI
-
emptyDir
:EmptyDir 表示共享 pod 生命週期的臨時目錄。 -
ephemeral
:Ephemeral 表示由叢集儲存驅動程式(Alpha 功能)處理的卷。 卷的生命週期與定義它的 pod 相關聯——它將在 pod 啟動之前建立,並在 pod 被刪除時刪除。 -
fc
:FC 表示連線到 kubelet 主機然後暴露給 pod 的光纖通道資源。 -
flexVolume
:FlexVolume 表示使用基於 exec 的外掛配置/附加的通用卷資源。 -
flocker
:Flocker 表示附加到 kubelet 主機的 Flocker 卷。 這取決於正在執行的 Flocker 控制服務。 -
gcePersistentDisk
:GCEPersistentDisk 表示一個 GCE 磁碟資源,它附加到 kubelet 的主機上,然後暴露給 pod。 -
gitRepo
:GitRepo 代表特定版本的 git 儲存庫。GitRepo 已棄用
。 要使用 git repo 配置容器,請將 EmptyDir 掛載到使用 git 克隆 repo 的 InitContainer 中,然後將 EmptyDir 掛載到 Pod 的容器中。 -
glusterfs
:Glusterfs 表示主機上的 Glusterfs 掛載,共享一個 pod 的生命週期。 -
hostPath
:HostPath 表示主機上直接暴露給容器的預先存在的檔案或目錄。 這通常用於系統代理或其他允許檢視主機的特權事物。 大多數容器不需要這個。 -
iscsi
:ISCSI 代表一個 ISCSI 磁碟資源,它連線到 kubelet 的主機,然後暴露給 pod。 -
name
:卷的名稱。 必須是 DNS_LABEL 並且在 pod 中是唯一的。 -
nfs
:NFS 表示共享 pod 生命週期的主機上的 NFS 掛載。 -
persistentVolumeClaim
:PersistentVolumeClaimVolumeSource 表示對同一名稱空間中的 PersistentVolumeClaim 的引用。 -
photonPersistentDisk
:PhotonPersistentDisk 表示附加並掛載在 kubelets 主機上的 PhotonController 永久磁碟。 -
portworxVolume
:PortworxVolume 表示連線並掛載在 kubelets 主機上的 portworx 卷。 -
projected
:一站式資源祕密、配置對映和向下 API 的專案。 -
quobyte
:Quobyte 表示共享 pod 生命週期的主機上的 Quobyte 掛載。 -
rbd
:RBD 表示在共享 pod 生命週期的主機上掛載的 Rados 塊裝置。 -
scaleIO
:ScaleIO 表示附加並安裝在 Kubernetes 節點上的 ScaleIO 持久卷。 -
secret
:Secret 表示應填充此卷的金鑰。 -
storageos
:StorageOS 表示附加並安裝在 Kubernetes 節點上的 StorageOS 卷。 -
vsphereVolume
:VsphereVolume 表示附加並安裝在 kubelets 主機上的 vSphere 卷。
其中比較常用的掛在卷型別有:
- emptyDir
- hostPath
- nfs
- persistentVolumeClaim
- glusterfs
- cephfs
- configMap
- secret
想要使用儲存卷,需要經歷下面兩個步驟:
- 定義pod的volume,這個volume指明它要關聯到哪個儲存上的
- 在容器中要使用volumemounts掛載對應的儲存
1.1 emptyDir
emptyDir型別的Volume是在Pod分配到Node上時被建立,Kubernetes會在Node上自動分配一個目錄,因此無需指定宿主機Node上對應的目錄檔案。 這個目錄的初始內容為空,當Pod從Node上移除時,emptyDir中的資料會被永久刪除。emptyDir Volume主要用於某些應用程式無需永久儲存的臨時目錄,多個容器的共享目錄等。
官方文件:https://kubernetes.io/docs/concepts/storage/volumes#emptydir
示例:建立一個Pod掛載emptyDir:
emptydir.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-emptydir
namespace: default
labels:
app: pod-emptydir
spec:
containers:
- name: pod-emptydir
image: nginx:1.17.1
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /cache
name: cache-volume
resources:
requests:
cpu: "250m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
restartPolicy: Always
volumes:
- name: cache-volume
emptyDir:
{}
更新資源清單:
kubectl apply -f emptydir.yaml
檢視Pod描述資訊,可以看到對應的掛載卷為cache-volume
,型別為EmptyDir
:
然後去Pod所在的節點檢視對應的Volume掛在卷:
kubectl get pods -l app=pod-emptydir -o wide
kubectl get pods -l app=pod-emptydir -o yaml | grep uid
獲得對應Pod所在的節點以及uid資訊:
在對應的節點上檢視Pod相關資訊:
tree /var/lib/kubelet/pods/18168545-1292-4086-aaba-0bf71edadc0e
右下圖可知,臨時目錄在對應工作節點的/var/lib/kubelet/pods/18168545-1292-4086-aaba-0bf71edadc0e/volumes/
目錄下:
1.2 hostPath
hostPath Volume是指Pod掛載宿主機上的目錄或檔案。 hostPath Volume使得容器可以使用宿主機的檔案系統進行儲存,hostpath(宿主機路徑):節點級別的儲存卷,在pod被刪除,這個儲存卷還是存在的,不會被刪除,所以只要同一個pod被排程到同一個節點上來,在pod被刪除重新被排程到這個節點之後,對應的資料依然是存在的。
示例:建立一個Pod掛載hostPath型別的儲存卷:
hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-hostpath
namespace: default
labels:
app: pod-hostpath
spec:
containers:
- name: pod-hostpath-nginx
image: nginx:1.17.1
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /test-nginx
name: hostpath-volume
- name: pod-hostpath-tomcat
image: tomcat:8.5-jre8-alpine
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /test-tomcat
name: hostpath-volume
restartPolicy: Always
volumes:
- name: hostpath-volume
hostPath:
path: /data1
type: DirectoryOrCreate
更新資源清單:
kubectl apply -f hostpath.yaml
檢視Pod被排程到了哪個節點:
get pods -l app=pod-hostpath -o wide
結果如下:
前往對應的工作節點,檢視是否建立了/data1
目錄:
ll /data1/
結果如下:
進入/data1
目錄,建立一個資料夾,並且進入對應的Pod中檢查:
# 在對應的工作節點上執行
cd /data1 && mkdir -p testDir
結果如下:
# 到控制節點上執行進入Pod並檢查的操作
kubectl exec -it pod-hostpath -c pod-hostpath-nginx -- /bin/bash
ls -l /test-nginx
kubectl exec -it pod-hostpath -c pod-hostpath-tomcat -- /bin/bash
ls -l /test-tomcat
分別進入兩個Pod中檢查,都存在testDir
這個目錄:
由此可知,pod-hostpath-nginx
和pod-hostpath-tomcat
兩個Pod這兩個容器是共享儲存卷的。
hostPath型別儲存卷的缺點:
- 單節點:pod刪除之後重新建立必須排程到同一個node節點,資料才不會丟失
要解決單節點問題,可以使用分散式儲存來解決,例如:nfs、cephfs、glusterfs等。
1.3 nfs
1.3.1 搭建nfs服務
NFS服務端搭建:
# 1. nfs服務端安裝nfs-utils
yum install -y nfs-utils
# 2. 建立NFS共享的目錄
mkdir -pv /data/volumes
# 3. 配置nfs共享目錄
cat > /etc/exports << EOF
/data/volumes 192.168.126.40/24(rw,no_root_squash)
EOF
# 4. 啟動nfs服務
systemctl start nfs.service
systemctl status nfs.service
systemctl enable nfs.service
NFS客戶端搭建:
在Kubernetes的各個工作節點上操作:
yum install -y nfs-utils
systemctl enable nfs.service
# 手動掛載nfs
mkdir -p /test
mount 192.168.126.40:/data/volumes /test/
df -Th
掛載成功顯示如下:
# 手動解除安裝
umount /test
df -Th
解除安裝成功:
1.3.2 建立Pod掛載nfs作為儲存卷
Kubernetes掛載NFS的官方文件:https://kubernetes.io/zh/docs/concepts/storage/volumes/#nfs
nfs.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-nfs-volume
namespace: default
labels:
app: test-nfs-volume
spec:
containers:
- name: nfs-volume-nginx
image: nginx:1.17.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
volumeMounts:
- mountPath: /usr/share/nginx/html
name: nfs-volume
restartPolicy: Always
volumes:
- name: nfs-volume
nfs:
path: /data/volumes
server: 192.168.126.40
更新資源清單:
kubectl apply -f nfs.yaml
檢查Pod是否建立成功:
kubectl get pods -l app=test-nfs-volume -o wide
結果如下:
進入到NFS共享目錄下,建立一個index.html檔案:
# 在nfs-server伺服器上操作
cd /data/volumes/
echo 'NFS Volume Successed!' > index.html
效果如下:
通過curl Pod IP檢視結果:
curl 10.244.85.208
結果如下:
NFS掛載成功,nfs支援多個客戶端掛載,可以建立多個pod,掛載同一個nfs伺服器共享出來的目錄;但是nfs如果宕機了,資料也就丟失了,所以需要使用分散式儲存,常見的分散式儲存有glusterfs和cephfs。
2、PVC
官方文件:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes
2.1 什麼是PV?
PersistentVolume(PV)是群集中的一塊儲存,由管理員配置或使用儲存類動態配置。 它是叢集中的資源,就像pod是k8s叢集資源一樣。 PV是容量外掛,如Volumes,其生命週期獨立於使用PV的任何單個pod。
2.2 什麼是PVC?
PersistentVolumeClaim(PVC)是一個持久化儲存卷,我們在建立pod時可以定義這個型別的儲存卷。 它類似於一個pod。 Pod消耗節點資源,PVC消耗PV資源。 Pod可以請求特定級別的資源(CPU和記憶體)。 pvc在申請pv的時候也可以請求特定的大小和訪問模式(例如,可以一次讀寫或多次只讀)。
2.3 PVC和PV工作原理
PV是群集中的資源。 PVC是對這些資源的請求。
PV和PVC之間的相互作用遵循以下生命週期。
2.3.1 pv的供應方式
- 靜態的:叢集管理員建立了許多PV。它們包含可供群集使用者使用的實際儲存的詳細資訊。它們存在於Kubernetes API中,可供使用。
- 動態的:當管理員建立的靜態PV都不匹配使用者的PersistentVolumeClaim時,群集可能會嘗試為PVC專門動態配置卷。此配置基於StorageClasses,PVC必須請求儲存類,管理員必須建立並配置該類,以便進行動態配置。
2.3.2 繫結
使用者建立pvc並指定需要的資源和訪問模式。在找到可用pv之前,pvc會保持未繫結狀態。
2.3.3 使用
- 需要找一個儲存伺服器,把它劃分成多個儲存空間;
- k8s管理員可以把這些儲存空間定義成多個pv;
- 在pod中使用pvc型別的儲存卷之前需要先建立pvc,通過定義需要使用的pv的大小和對應的訪問模式,找到合適的pv;
- pvc被建立之後,就可以當成儲存捲來使用了,我們在定義pod時就可以使用這個pvc的儲存卷;
- pvc和pv它們是一一對應的關係,pv如果被pvc綁定了,就不能被其他pvc使用了;
- 我們在建立pvc的時候,應該確保和底下的pv能繫結,如果沒有合適的pv,那麼pvc就會處於pending狀態。
2.3.4 回收策略
當我們建立pod時如果使用pvc做為儲存卷,那麼它會和pv繫結,當刪除pod,pvc和pv繫結就會解除,解除之後和pvc繫結的pv卷裡的資料需要怎麼處理,目前,卷可以保留,回收或刪除:
- Retain
- Recycle (不推薦使用,1.15可能被廢棄了)
- Delete
從其宣告中釋放持久卷時會發生什麼。 有效選項是 Retain(手動建立的 PersistentVolumes 的預設值)、Delete(動態配置的 PersistentVolumes 的預設值)和 Recycle(已棄用)。 此 PersistentVolume 下的卷外掛必須支援回收。
2.3.4.1 Retain
當刪除pvc的時候,pv仍然存在,處於released狀態,但是它不能被其他pvc繫結使用,裡面的資料還是存在的,當我們下次再使用的時候,資料還是存在的,這個是預設的回收策略。
2.3.4.2 Delete
刪除pvc時即會從Kubernetes中移除PV,也會從相關的外部設施中刪除儲存資產。
2.4 通過PVC給Pod提供持久化儲存卷
2.4.1 建立NFS共享目錄
# 在nfs-server伺服器上操作
mkdir -p /data/volume_test/v{1,2,3,4,5,6,7,8,9,10}
# 配置nfs
cat > /etc/exports << EOF
/data/volumes 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v1 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v2 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v3 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v4 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v5 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v6 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v7 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v8 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v9 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v10 192.168.126.40/24(rw,no_root_squash)
EOF
# 重新載入配置
exportfs -arv
2.4.2 PV資源清單
通過kubectl explain pv
命令可以檢視pv資源物件的欄位和配置資訊。
-
apiVersion
:pv物件的API組和版本資訊。當前版本資訊為v1
,可以通過kubectl explain pv.apiVersion
檢視當前Kubernetes版本的API版本資訊。 -
kind
:資源物件型別,PersistentVolume
,可以通過kubectl explain pv.kind
查詢。 -
metadata
:PV資源物件的元資料資訊-
name
:PV物件的名稱 -
namespace
:PV資源物件所屬的名稱空間
-
-
spec
:PV資源物件的詳細配置-
accessModes
:AccessModes 包含可以掛載卷的訪問方式。參考:https://kubernetes.io/zh/docs/concepts/storage/persistent-volumes/#access-modes-
ReadWriteOnce
:卷可以被一個節點以讀寫方式掛載。 ReadWriteOnce 訪問模式也允許執行在同一節點上的多個 Pod 訪問卷。 -
ReadOnlyMany
:卷可以被多個節點以只讀方式掛載。 -
ReadWriteMany
:卷可以被多個節點以讀寫方式掛載。 -
ReadWriteOncePod
:卷可以被單個 Pod 以讀寫方式掛載。 如果你想確保整個叢集中只有一個 Pod 可以讀取或寫入該 PVC, 請使用ReadWriteOncePod 訪問模式。這隻支援 CSI 卷以及需要 Kubernetes 1.22 以上版本。
-
-
awsElasticBlockStore
:AWSElasticBlockStore 表示一個 AWS 磁碟資源,它附加到 kubelet 的主機,然後暴露給 pod。 -
azureDisk
:AzureDisk 表示主機上的 Azure 資料磁碟掛載,並將掛載繫結到 pod。 -
azureFile
:AzureFile 表示主機上的 Azure 檔案服務掛載,並將掛載繫結到 pod。 -
capacity
:持久卷的資源和容量的描述。參考:https://kubernetes.io/zh/docs/concepts/storage/persistent-volumes/#capacity 和 https://kubernetes.io/zh/docs/reference/glossary/?all=true#term-quantity-
storage
:PV儲存卷的大小。例如:1Gi
。
-
-
cephfs
:CephFS 表示主機上的 Ceph FS 掛載,共享 pod 的生命週期。 -
cinder
:Cinder 表示附加並安裝在 kubelets 主機上的 cinder 卷。 -
claimRef
:ClaimRef 是 PersistentVolume 和 PersistentVolumeClaim 之間雙向繫結的一部分。 繫結時預計為非零。 claim.VolumeName 是 PV 和 PVC 之間的權威繫結。 -
csi
:CSI(容器儲存介面)表示由某些外部 CSI 驅動程式(Beta 功能)處理的臨時儲存。 -
fc
:FC 表示連線到 kubelet 主機然後暴露給 pod 的光纖通道資源。 -
flexVolume
:FlexVolume 表示使用基於 exec 的外掛配置/附加的通用卷資源。 -
flocker
:Flocker 表示附加到 kubelet 主機的 Flocker 卷。 這取決於正在執行的 Flocker 控制服務。 -
gcePersistentDisk
:GCEPersistentDisk 表示一個 GCE 磁碟資源,它附加到 kubelet 的主機上,然後暴露給 pod。 -
glusterfs
:Glusterfs 表示主機上的 Glusterfs 掛載,共享一個 pod 的生命週期。 -
hostPath
:HostPath 表示主機上直接暴露給容器的預先存在的檔案或目錄。 這通常用於系統代理或其他允許檢視主機的特權事物。 大多數容器不需要這個。 -
iscsi
:ISCSI 代表一個 ISCSI 磁碟資源,它連線到 kubelet 的主機,然後暴露給 pod。 -
local
:Local 表示具有節點親和性的直連儲存。 -
mountOptions
:掛載選項列表,例如ro
、soft
。 -
nfs
:NFS 表示主機上的 NFS 掛載。 由管理員提供。 -
nodeAffinity
:NodeAffinity 定義了限制可以從哪些節點訪問此卷的約束。 此欄位影響使用此卷的 pod 的排程。 -
persistentVolumeReclaimPolicy
:PV回收策略,從其宣告中釋放持久卷時會發生什麼。 有效選項是 Retain(手動建立的 PersistentVolumes 的預設值)、Delete(動態配置的 PersistentVolumes 的預設值)和 Recycle(已棄用)。 此 PersistentVolume 下的卷外掛必須支援回收。 -
photonPersistentDisk
:PhotonPersistentDisk 表示附加並掛載在 kubelets 主機上的 PhotonController 永久磁碟。 -
portworxVolume
:PortworxVolume 表示連線並掛載在 kubelets 主機上的 portworx 卷。 -
quobyte
:Quobyte 表示共享 pod 生命週期的主機上的 Quobyte 掛載。 -
rbd
:RBD 表示在共享 pod 生命週期的主機上掛載的 Rados 塊裝置。 -
scaleIO
:ScaleIO 表示附加並安裝在 Kubernetes 節點上的 ScaleIO 持久卷。 -
storageClassName
:此持久卷所屬的 StorageClass 的名稱。 空值表示該卷不屬於任何 StorageClass。 -
storageos
:StorageOS 表示附加並安裝在 Kubernetes 節點上的 StorageOS 卷。 -
volumeMode
:volumeMode 定義卷是打算與格式化的檔案系統一起使用還是保持在原始塊狀態。 當規範中不包含檔案系統的值時,它是隱含的。 -
vsphereVolume
:VsphereVolume 表示附加並安裝在 kubelets 主機上的 vSphere 卷。
-
-
status
:Kubernetes建立完PV之後自動生成的狀態資訊,無法手動修改。
2.4.3 建立PV
pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: v1
namespace: default
spec:
capacity:
storage: 1Gi # pv的儲存空間容量
accessModes: ["ReadWriteOnce"]
nfs:
path: /data/volume_test/v1 # 把nfs的儲存空間建立成pv
server: 192.168.126.40
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v2
namespace: default
spec:
capacity:
storage: 2Gi # pv的儲存空間容量
accessModes: ["ReadWriteMany"]
nfs:
path: /data/volume_test/v2 # 把nfs的儲存空間建立成pv
server: 192.168.126.40
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v3
namespace: default
spec:
capacity:
storage: 3Gi # pv的儲存空間容量
accessModes: ["ReadOnlyMany"]
nfs:
path: /data/volume_test/v3 # 把nfs的儲存空間建立成pv
server: 192.168.126.40
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v4
namespace: default
spec:
capacity:
storage: 4Gi # pv的儲存空間容量
accessModes: ["ReadWriteOnce", "ReadWriteMany"]
nfs:
path: /data/volume_test/v4 # 把nfs的儲存空間建立成pv
server: 192.168.126.40
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v5
namespace: default
spec:
capacity:
storage: 5Gi # pv的儲存空間容量
accessModes: ["ReadWriteOnce", "ReadWriteMany"]
nfs:
path: /data/volume_test/v5 # 把nfs的儲存空間建立成pv
server: 192.168.126.40
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v6
namespace: default
spec:
capacity:
storage: 6Gi # pv的儲存空間容量
accessModes: ["ReadWriteOnce", "ReadWriteMany"]
nfs:
path: /data/volume_test/v6 # 把nfs的儲存空間建立成pv
server: 192.168.126.40
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v7
namespace: default
spec:
capacity:
storage: 7Gi # pv的儲存空間容量
accessModes: ["ReadWriteOnce", "ReadWriteMany"]
nfs:
path: /data/volume_test/v7 # 把nfs的儲存空間建立成pv
server: 192.168.126.40
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v8
namespace: default
spec:
capacity:
storage: 8Gi # pv的儲存空間容量
accessModes: ["ReadWriteOnce", "ReadWriteMany"]
nfs:
path: /data/volume_test/v8 # 把nfs的儲存空間建立成pv
server: 192.168.126.40
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v9
namespace: default
spec:
capacity:
storage: 9Gi # pv的儲存空間容量
accessModes: ["ReadWriteOnce", "ReadWriteMany"]
nfs:
path: /data/volume_test/v9 # 把nfs的儲存空間建立成pv
server: 192.168.126.40
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v10
namespace: default
spec:
capacity:
storage: 10Gi # pv的儲存空間容量
accessModes: ["ReadWriteOnce", "ReadWriteMany"]
nfs:
path: /data/volume_test/v10 # 把nfs的儲存空間建立成pv
server: 192.168.126.40
更新資源清單:
kubectl apply -f pv.yaml
Kubernetes會自動建立pv:
STATUS
為Available
表示PV是可用的。
2.4.4 建立PVC繫結PV
pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc1
namespace: default
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 2Gi
更新資源清單:
kubectl apply -f pvc.yaml
建立完成之後,檢視PVC和哪個PV繫結成功了:
STATUS
為Bound
表示已經被綁定了,CLAIN
表示綁定了哪一個PVC。
2.4.5 建立Pod掛載PVC
pod-pvc.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-pvc
namespace: default
labels:
app: pod-pvc
spec:
containers:
- name: nginx
image: nginx:1.17.1
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /usr/share/nginx/html
name: nginx-html
restartPolicy: Always
volumes:
- name: nginx-html
persistentVolumeClaim:
claimName: my-pvc1
更新資源清單:
kubectl apply -f pod-pvc.yaml
檢視Pod是否成功建立:
到nfs-serve節點上,在對應的共享路徑下建立index.html
:
cd /data/volume_test/v2/
echo 'PVC my-pvc1 Mounted Successed!' > index.html
效果如下:
然後返回控制節點,訪問Pod IP:
PV
和PVC
使用注意事項:
- 我們每次建立pvc的時候,需要事先有劃分好的pv,這樣可能不方便,那麼可以在建立pvc的時候直接動態建立一個pv這個儲存類,pv事先是不存在的。
- pvc和pv繫結,如果使用預設的回收策略retain,那麼刪除pvc之後,pv會處於released狀態,我們想要繼續使用這個pv,需要手動刪除pv,kubectl delete pv pv_name,刪除pv,不會刪除pv裡的資料,當我們重新建立pvc時還會和這個最匹配的pv繫結,資料還是原來資料,不會丟失。
3、Kubernetes儲存類StorageClass
上面提到的PV和PVC繫結的模式都需要提前建立好PV,然後再由PVC和PV進行繫結,但是如果成千上萬個PVC需要繫結PV,那麼我們需要手動建立深千上萬個PV,對於運維人員來說維護成本很高。所以Kubernetes提供了一種自動建立PV的機制,叫做StorageClass,它的作用就是建立PV模板。Kubernetes管理員提供建立StorageClass可以動態生成一個儲存卷PV供PVC使用。
每個StorageClass都包含欄位provisioner,parameters和reclaimPolicy。
具體來說,StorageClass會定義以下兩個部分:
- PV的屬性,比如PV儲存的大小、型別、名稱等
- 建立這種PV需要使用的儲存外掛,比如Ceph、NFS、Glusterfs等等
有了這兩部分資訊,Kubernetes就能夠根據使用者提交的PVC,找到對應的StorageClass,然後Kubernetes就會呼叫 StorageClass宣告的儲存外掛,創建出需要的PV。
3.1 StorageClass資源清單
通過命令kubectl explain storageclass
檢視StorageClass定義所需的欄位和配置資訊。
-
allowVolumeExpansion
:AllowVolumeExpansion 顯示儲存類是否允許卷擴充套件。布林型別,是否許卷擴充套件,PersistentVolume 可以配置成可擴充套件。將此功能設定為true時,允許使用者通過編輯相應的 PVC 物件來調整卷大小。當基礎儲存類的allowVolumeExpansion欄位設定為 true 時,以下型別的卷支援卷擴充套件。此功能僅用於擴容卷,不能用於縮小卷。
-
allowedTopologies
:限制可以動態供應卷的節點拓撲。 每個卷外掛都定義了自己支援的拓撲規範。 空的 TopologySelectorTerm 列表意味著沒有拓撲限制。 此欄位僅適用於啟用 VolumeScheduling 功能的伺服器。 -
apiVersion
:StorageClass所屬的API組和版本資訊,storage.k8s.io/v1
,可以根據kubectl explain storageclass.apiVersion
查詢當前Kubernetes版本中StorageClass的API組和版本資訊。 -
kind
:資源型別,StorageClass
,可以根據kubectl explain storageclass.kind
命令查詢資源型別 -
metadata
:StorageClass資源的元資料 -
mountOptions
:此儲存類的動態配置 PersistentVolume 是使用這些 mountOptions 建立的,例如 [ro
,soft
]。 未驗證 - 如果 PV 無效,則安裝 PV 將失敗。 -
parameters
:建立此儲存類的卷的配置程式的引數。 -
provisioner
:供應商,Provisioner 表示 Provisioner 的型別。StorageClass需要有一個供應者,用來確定我們使用什麼樣的儲存來建立pv。- 常見的供應商有:https://kubernetes.io/zh/docs/concepts/storage/storage-classes/#provisioner
- provisioner既可以由內部供應商提供,也可以由外部供應商提供,如果是外部供應商可以參考https://github.com/kubernetes-incubator/external-storage/下提供的方法建立。
- https://github.com/kubernetes-sigs/sig-storage-lib-external-provisioner
-
reclaimPolicy
:回收策略,預設的回收策略是Delete
。 -
volumeBindingMode
:VolumeBindingMode 指示應如何配置和繫結 PersistentVolumeClaims。 未設定時,使用VolumeBindingImmediate。 此欄位僅適用於啟用 VolumeScheduling 功能的伺服器。
這裡通過NFS演示StorageClass的使用。
3.2 安裝nfs provisioner
3.2.1 建立執行nfs-provisioner需要的sa賬號
nfs-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-provisioner
namespace: default
更新資源清單:
kubectl apply -f nfs-serviceaccount.yaml
結果如下:
什麼是sa?
sa全稱是ServiceAccount。ServiceAccount是為了方便Pod裡面的程序呼叫Kubernetes API或其他外部服務而設計的。
指定了serviceaccount之後,我們把pod創建出來了,我們在使用這個pod時,這個pod就有了我們指定的賬戶的許可權了。
3.2.2 對sa授權
kubectl create clusterrolebinding nfs-provisioner-clusterrolebinding --clusterrole=cluster-admin --serviceaccount=default:nfs-provisioner
效果如下:
3.2.3 安裝nfs-provisioner程式
3.2.3.1 配置NFS共享目錄
# 1. 建立nfs-provisioner共享目錄(在nfs-server伺服器上操作)
mkdir -p /data/nfs_pro
# 2. 配置nfs
# 配置nfs
cat > /etc/exports << EOF
/data/volumes 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v1 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v2 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v3 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v4 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v5 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v6 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v7 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v8 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v9 192.168.126.40/24(rw,no_root_squash)
/data/volume_test/v10 192.168.126.40/24(rw,no_root_squash)
/data/nfs_pro 192.168.126.40/24(rw,no_root_squash)
EOF
# 重新載入配置
exportfs -arv
3.2.3.2 建立Deployment執行nfs-provisioner
nfs-provisioner-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-provisioner
labels:
app: nfs-provisioner
spec:
selector:
matchLabels:
app: nfs-provisioner
strategy:
type: Recreate
replicas: 1
template:
metadata:
name: nfs-provisioner
labels:
app: nfs-provisioner
spec:
serviceAccountName: nfs-provisioner
containers:
- name: nfs-provisioner
image: registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /persistentvolumes
name: nfs-client-root
env:
- name: PROVISIONER_NAME
value: example.com/nfs
- name: NFS_SERVER
value: 192.168.126.40
- name: NFS_PATH
value: /data/nfs_pro
restartPolicy: Always
volumes:
- name: nfs-client-root
nfs:
path: /data/nfs_pro
server: 192.168.126.40
更新資源清單:
kubectl apply -f nfs-provisioner-deployment.yaml
檢查是否成功建立資源:
3.3 建立StorageClass動態供給PV
nfs-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-storageclass
namespace: default
provisioner: example.com/nfs # 此處的provisioner必須要和安裝的nfs-prosivioner的PROVISIONER_NAME保持一致
provisioner處寫的
example.com/nfs
應該跟安裝nfs provisioner時候的env下的PROVISIONER_NAME的value值保持一致。
更新資源清單:
kubectl apply -f nfs-storageclass.yaml
檢車是否成功建立StorageClass:
3.4 建立PVC通過StorageClass動態生成PV
nfs-persistentvolumeclaim.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc
namespace: default
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 2Gi
storageClassName: nfs-storageclass # 與定義的StorageClass中的name保持一致
更新資源清單:
kubectl apply -f nfs-persistentvolumeclaim.yaml
檢查PVC是否建立成功並且與動態生成的PV繫結:
PVC動態生成PV並繫結的步驟如下:
- 供應商:建立一個nfs provisioner
- 建立StorageClass,指向上一步中的供應商
- 建立PersistentVolumeClaim,指定StorageClass後動態生成PV並繫結
3.5 建立Pod掛載StorageClass動態生成的PVC
podMountPVC.yaml
apiVersion: v1
kind: Pod
metadata:
name: pvc-pod
namespace: default
labels:
app: pvc-pod
spec:
containers:
- name: pvc-pod-container
image: nginx:1.17.1
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /usr/share/nginx/html
name: nfs-pvc-volume
restartPolicy: Always
volumes:
- name: nfs-pvc-volume
persistentVolumeClaim:
claimName: nfs-pvc # PVC的名稱
更新資源清單:
kubectl apply -f podMountPVC.yaml
檢查Pod是否建立成功:
然後去nfs-server伺服器上進入到該PV對應的目錄下建立index.html
:
cd /data/nfs_pro/default-nfs-pvc-pvc-672785ee-acc5-482e-811a-71f8fdf76886
echo 'Create By nfs provisioner PV Successed!' > index.html
效果如下:
然後回到控制節點,訪問該Pod: