一、什么是StorageClass
Kubernetes提供了一套可以自動創建PV的機制,即:Dynamic Provisioning.而這個機制的核心在於:StorageClass這個API對象.
StorageClass對象會定義下面兩部分內容:
1,PV的屬性.比如,存儲類型,Volume的大小等.
2,創建這種PV需要用到的存儲插件
有了這兩個信息之后,Kubernetes就能夠根據用戶提交的PVC,找到一個對應的StorageClass,之后Kubernetes就會調用該StorageClass聲明的存儲插件,進而創建出需要的PV.
但是其實使用起來是一件很簡單的事情,你只需要根據自己的需求,編寫YAML文件即可,然后使用kubectl create命令執行即可
二、為什么需要StorageClass
在一個大規模的Kubernetes集群里,可能有成千上萬個PVC,這就意味着運維人員必須實現創建出這個多個PV,此外,隨着項目的需要,會有新的PVC不斷被提交,那么運維人員就需要不斷的添加新的,滿足要求的PV,否則新的Pod就會因為PVC綁定不到PV而導致創建失敗.而且通過 PVC 請求到一定的存儲空間也很有可能不足以滿足應用對於存儲設備的各種需求 而且不同的應用程序對於存儲性能的要求可能也不盡相同,比如讀寫速度、並發性能等,為了解決這一問題,Kubernetes 又為我們引入了一個新的資源對象:StorageClass,通過 StorageClass 的定義,管理員可以將存儲資源定義為某種類型的資源,比如快速存儲、慢速存儲等,用戶根據 StorageClass 的描述就可以非常直觀的知道各種存儲資源的具體特性了,這樣就可以根據應用的特性去申請合適的存儲資源了。
三、StorageClass運行原理及部署流程
要使用 StorageClass,我們就得安裝對應的自動配置程序,比如我們這里存儲后端使用的是 nfs,那么我們就需要使用到一個 nfs-client 的自動配置程序,我們也叫它 Provisioner,這個程序使用我們已經配置好的 nfs 服務器,來自動創建持久卷,也就是自動幫我們創建 PV。
1.自動創建的 PV 以${namespace}-${pvcName}-${pvName}這樣的命名格式創建在 NFS 服務器上的共享數據目錄中 2.而當這個 PV 被回收后會以archieved-${namespace}-${pvcName}-${pvName}這樣的命名格式存在 NFS 服務器上。
1.原理及部署流程說明
詳細的運作流程可以參考下圖:
搭建StorageClass+NFS,大致有以下幾個步驟:
1.創建一個可用的NFS Serve 2.創建Service Account.這是用來管控NFS provisioner在k8s集群中運行的權限 3.創建StorageClass.負責建立PVC並調用NFS provisioner進行預定的工作,並讓PV與PVC建立管理 4.創建NFS provisioner.有兩個功能,一個是在NFS共享目錄下創建掛載點(volume),另一個則是建了PV並將PV與NFS的掛載點建立關聯
四、創建StorageClass
1.創建NFS共享服務
該步驟比較簡單不在贅述,大家可以自行百度搭建
當前環境NFS server及共享目錄信息
IP: 192.168.248.202
Export PATH: /home/data/
建議:*(rw,insecure,sync,no_subtree_check,no_root_squash) no_subtree_check :即使輸出目錄是一個子目錄,nfs服務器也不檢查其父目錄的權限,這樣可以提高效率;chmod -R 777 /home/data/
2.使用以下文檔配置account及相關權限
rbac.yaml: #唯一需要修改的地方只有namespace,根據實際情況定義
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default #根據實際環境設定namespace,下面類同
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
3.創建NFS資源的StorageClass
nfs-StorageClass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: managed-nfs-storage
provisioner: qgg-nfs-storage #這里的名稱要和provisioner配置文件中的環境變量PROVISIONER_NAME保持一致
parameters:
archiveOnDelete: "false"
4.創建NFS provisioner
nfs-provisioner.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default #與RBAC文件中的namespace保持一致
spec:
replicas: 1
selector:
matchLabels:
app: nfs-client-provisioner
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: qgg-nfs-storage #provisioner名稱,請確保該名稱與 nfs-StorageClass.yaml文件中的provisioner名稱保持一致
- name: NFS_SERVER
value: 192.168.248.202 #NFS Server IP地址
- name: NFS_PATH
value: /home/data #NFS掛載卷
volumes:
- name: nfs-client-root
nfs:
server: 192.168.248.202 #NFS Server IP地址
path: /home/data #NFS 掛載卷
五、關於StorageClass回收策略對數據的影響
1.第一種配置
archiveOnDelete: "false" reclaimPolicy: Delete #默認沒有配置,默認值為Delete
測試結果:
1.pod刪除重建后數據依然存在,舊pod名稱及數據依然保留給新pod使用 2.sc刪除重建后數據依然存在,舊pod名稱及數據依然保留給新pod使用 3.刪除PVC后,PV被刪除且NFS Server對應數據被刪除
2.第二種配置
archiveOnDelete: "false" reclaimPolicy: Retain
測試結果:
1.pod刪除重建后數據依然存在,舊pod名稱及數據依然保留給新pod使用 2.sc刪除重建后數據依然存在,舊pod名稱及數據依然保留給新pod使用 3.刪除PVC后,PV不會別刪除,且狀態由Bound變為Released,NFS Server對應數據被保留 4.重建sc后,新建PVC會綁定新的pv,舊數據可以通過拷貝到新的PV中
3.第三種配置
archiveOnDelete: "ture" reclaimPolicy: Retain
結果:
1.pod刪除重建后數據依然存在,舊pod名稱及數據依然保留給新pod使用 2.sc刪除重建后數據依然存在,舊pod名稱及數據依然保留給新pod使用 3.刪除PVC后,PV不會別刪除,且狀態由Bound變為Released,NFS Server對應數據被保留 4.重建sc后,新建PVC會綁定新的pv,舊數據可以通過拷貝到新的PV中
4.第四種配置
archiveOnDelete: "ture" reclaimPolicy: Delete
結果:
1.pod刪除重建后數據依然存在,舊pod名稱及數據依然保留給新pod使用 2.sc刪除重建后數據依然存在,舊pod名稱及數據依然保留給新pod使用 3.刪除PVC后,PV不會別刪除,且狀態由Bound變為Released,NFS Server對應數據被保留 4.重建sc后,新建PVC會綁定新的pv,舊數據可以通過拷貝到新的PV中
總結:除以第一種配置外,其他三種配置在PV/PVC被刪除后數據依然保留
六、常見問題
1.如何設置默認的StorageClass
我們可以用 kubectl patch 命令來更新:
YAML文件
2.如何使用默認的StorageClass
如果集群有一個默認的StorageClass能夠滿足我們的需求,那么剩下所有需要做的就是創建PersistentVolumeClaim(PVC),剩下的都有默認的動態配置搞定,包括無需去指定storageClassName:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mypvc namespace: testns spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi
3.修改默回收策略(默認為Delete)
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: managed-nfs-storage annotations: provisioner: qgg-nfs-storage #or choose another name, must match deployment's env PROVISIONER_NAME' parameters: archiveOnDelete: "ture" #暫時不清楚該值對回收策略產生什么影響 reclaimPolicy: Retain #只有NFS 和hostPth支持兩種回收策略
4.能過刪除/關閉默認的StorageClass
不能刪除默認的StorageClass,因為它是作為集群的add-on安裝的,如果它被刪除,會被重新安裝。 當然,可以停掉默認的StorageClass行為,通過刪除annotation:storageclass.beta.kubernetes.io/is-default-class,或者設置為false。 如果沒有StorageClass對象標記默認的annotation,那么PersistentVolumeClaim對象(在不指定StorageClass情況下)將不自動觸發動態配置。相反,它們將回到綁定可用的*PersistentVolume(PV)*的狀態。
5.當刪除PersistentVolumeClaim(PVC)會發生什么
如果一個卷是動態配置的卷,則默認的回收策略為“刪除”。這意味着,在默認的情況下,當PVC被刪除時,基礎的PV和對應的存儲也會被刪除。如果需要保留存儲在卷上的數據,則必須在PV被設置之后將回收策略從delete更改為retain。
參考文檔:https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client