Kubernetes对象中的PersistentVolume、PersistentVolumeClaim和StorageClass的概念关系
Kubernetes容器要持久化數據,離不開volume,k8s的volume和Docker原生概念中的volume有一些差別,不過本次不講這個,本次要明確的是k8s持久化數據用到的幾個對象PersistentVolume、PersistentVolumeClaim和StorageClass,首先明確這既然都是k8s對象,就可以通過API來創建的。
? ? ? ? k8s的volume支持的類型有很多,例如emptyDir、hostPath、nfs等,這些相對好理解,還有一種就是ersistentVolumeClaim,剛開始接觸的時候不太理解這個對象該如何使用,本次主要介紹ersistentVolumeClaim相關的概念和使用方法。
? ? ? ? 開始先要提一下PersistentVolume(PV)對象,PersistentVolume和Volume一樣是群集中的一塊存儲區域,然而Kubernetes將PersistentVolume抽象成了一種集群資源,類似于集群中的節點(Node)對象,這意味著我們可以使用Kubernetes API來創建PersistentVolume對象。PV與Volume最大的不同是PV擁有著獨立于Pod的生命周期。
? ? ? ? 而PersistentVolumeClaim(PVC)代表了用戶對PV資源的請求。用戶需要使用PV資源時,只需要創建一個PVC對象(包括指定使用何種存儲資源,使用多少GB,以何種模式使用PV等信息),Kubernetes會自動為我們分配我們所需的PV。如果把PersistentVolume類比成集群中的Node,那么PersistentVolumeClaim就相當于集群中的Pod,Kubernetes為Pod分配可用的Node,類似的也可以理解成為PersistentVolumeClaim分配可用的PersistentVolume。
1、靜態創建PV對象
可以直接靜態創建一個PV對象,作為一個存儲供PVC使用,創建PV主要有下面幾個參數
accessModes 訪問模式有下面三種:
- ? ? ?ReadWriteOnce(RWO):是最基本的方式,可讀可寫,但只支持被單個 Pod 掛載。
- ? ? ?ReadOnlyMany(ROX):只讀模式,可以被多個 Pod 掛載。
- ? ? ?ReadWriteMany(RWX):可讀可寫,并且可以被被多個 Pod 掛載。
- ? ? ?Retain,不清理,刪除PVC時,PV仍然存在并標記為“released”(需要刪除時需要手動清理)
- ? ? ?Recycle,刪除數據,對卷執行清理(rm -rf / thevolume / *),并使其再次可用于新索引(只有 NFS 和 HostPath 支持)
- ? ? ?Delete,刪除存儲資源,會從Kubernetes中刪除PV對象,以及外部基礎結構中的關聯存儲資產,例如AWS EBS,GCE PD,Azure磁盤或Cinder卷
apiVersion: v1 kind: PersistentVolume metadata:name: pv0003 spec:capacity:storage: 5GivolumeMode: FilesystemaccessModes:- ReadWriteOncepersistentVolumeReclaimPolicy: RecyclestorageClassName: slowmountOptions:- hard- nfsvers=4.1nfs:path: /tmpserver: 172.17.0.2
? ? 定義PV時,我們需要指定其底層存儲的類型,例如上文中創建的PV,底層使用nfs存儲,支持的類型很多,例如awsElasticBlockStore、FC、nfs、RBD、CephFS、Hostpath、StorageOS等等,可以查看官方文檔。
? ? 可以查看當前集群下創建的PV對象,kubectl get PersistentVolume --all-namespaces
2、靜態創建PVC對象
? ? 創建PV之后,并沒有被使用,如果想使用這個PV就需要創建PVC了,最后在pod中指定使用這個PVC而建立起pod和PV的關系。
#靜態創建PVCapiVersion: v1 kind: PersistentVolumeClaim metadata:name: myclaim spec:accessModes:- ReadWriteOnce
volumeMode: Filesystemresources:requests:storage: 8GistorageClassName: slowselector:matchLabels:release: "stable" #pod使用PVC kind: Pod apiVersion: v1 metadata:name: mypod spec:containers:- name: myfrontendimage: dockerfile/nginxvolumeMounts:- mountPath: "/var/www/html"name: mypdvolumes:- name: mypdpersistentVolumeClaim:claimName: myclaim
? ??分析一下上面的代碼:
- 創建PVC時指定了accessModes?= ReadWriteOnce。這表明這個PVC希望使用accessModes = ReadWriteOnce的PV。
- 創建PVC時指定了volumeMode= Filesystem。這表明這個PVC希望使用volumeMode= Filesystem的PV。
- 創建PVC時指定了storageClassName: slow,此配置用于綁定PVC和PV,意思是這個PVC希望使用storageClassName=slow的PV。我們可以看到最上面創建PV時也包含storageClassName=slow的配置。
- PVC還可以指定PV必須滿足的Label,如加了selector匹配matchLabels: release: "stable"。這表明此PVC希望使用Label:release: "stable"的PV。
- 最后是resources聲明,跟pod一樣可以聲明使用特定數量的資源,storage: 8Gi表明此PVC希望使用8G的Volume資源。
? ? ? 通過上面的分析,我們可以看到PVC和PV的綁定,不是簡單的通過Label來進行。而是要綜合storageClassName,accessModes,matchLabels以及storage來匹配符合條件的PV進行綁定。
3、動態創建PV對象
? ??上面我們通過描述文件靜態創建PV對象最終完成和pod的綁定,這種直接通過描述文件創建PV的方式稱為靜態創建,這樣的創建方式有弊端,假如我們創建PV時指定大小為50G,而PVC請求80G的PV,那么此PVC就無法找到合適的PV來綁定。因此實際生產中更多的使用PV的動態創建。
? ??PV的動態創建依賴于StorageClass對象。我們不需要手動創建任何PV,所有的工作都由StorageClass為我們完成,可以查看集群中的StorageClass信息 ,kubectl get StorageClass --all-namespaces
?
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata:name: slow provisioner: kubernetes.io/glusterfs parameters:resturl: "http://192.168.10.100:8080"restuser: ""secretNamespace: ""secretName: "" reclaimPolicy: Retain allowVolumeExpansion: true?
?這個例子使用創建了一個基于glusterfs分布式存儲的StorageClass,只有allowVolumeExpansion=teue時,才能擴展PVC,要為PVC請求更大的卷,請編輯PVC對象并指定更大的大小,這會觸發底層PersistentVolume的卷的擴展。永遠不會創建新的,而是調整現有卷的大小。
StorageClass的定義包含四個部分:
- provisioner:指定 Volume 插件的類型,包括內置插件(如kubernetes.io/glusterfs、kubernetes.io/aws-ebs)和外部插件(如 external-storage 提供的 ceph.com/cephfs)。
- parameters:指定 provisioner 的選項,比如?glusterfs 支持 resturl、restuser 等參數。
- mountOptions:指定掛載選項,當 PV 不支持指定的選項時會直接失敗。比如 NFS 支持 hard 和 nfsvers=4.1 等選項。
- reclaimPolicy:指定回收策略,同 PV 的回收策略。
? ? ? ? 手動創建的PV時,我們指定了storageClassName=slow的配置項,然后Pod定義中也通過指定storageClassName=slow,從而完成綁定。而通過StorageClass實現動態PV時,我們只需要指定StorageClass的metadata.name即可,這個名稱非常重要,用戶通過名稱類請求特定的存儲類,儲類的對象一旦被創建,name將不能再更改。
? ? ? ? 回到上文中創建PVC的例子,此時PVC指定了storageClassName=slow。那么Kubernetes會在集群中尋找是否存在metadata.name=slow的StorageClass,如果存在,此StorageClass會自動為此PVC創建一個accessModes = ReadWriteOnce,并且大小為8GB的PV。
?
或者直接寫到一起
#上面的部分省略了volumeMounts:- name: data-dirmountPath: /var/mysql/data#volumes:#- name: data-dir# hostPath:# path: /opt/mysqlvolumeClaimTemplates:- metadata:#annotations: volume.alpha.kubernetes.io/storage-class: xxxxcreationTimestamp: nullname: data-dirspec:accessModes:- ReadWriteOnceresources:requests:storage: 10GistorageClassName: slowvolumeMode: Filesystemstatus:phase: Pending
?
? ? ? ? 下面是參考官方的一種比較通用的寫法,基于helm的,直接將PVC的代碼寫到volumes的后面,根據values.yaml中的參數生成是掛載PVC的存儲還是其他存儲,可以作為以后自己寫腳本的參考
volumes:- name: configconfigMap:name: {{ template "redis-ha.fullname" . }}-configmap- name: probesconfigMap:name: {{ template "redis-ha.fullname" . }}-probes{{- if .Values.sysctlImage.mountHostSys }}- name: host-syshostPath:path: /sys{{- end }} {{- if .Values.persistentVolume.enabled }}volumeClaimTemplates:- metadata:name: dataannotations:{{- range $key, $value := .Values.persistentVolume.annotations }}{{ $key }}: {{ $value }}{{- end }}spec:accessModes:{{- range .Values.persistentVolume.accessModes }}- {{ . | quote }}{{- end }}resources:requests:storage: {{ .Values.persistentVolume.size | quote }}{{- if .Values.persistentVolume.storageClass }}{{- if (eq "-" .Values.persistentVolume.storageClass) }}storageClassName: ""{{- else }}storageClassName: "{{ .Values.persistentVolume.storageClass }}"{{- end }}{{- end }} {{- else if .Values.hostPath.path }}- name: datahostPath:path: {{ tpl .Values.hostPath.path .}} {{- else }}- name: dataemptyDir: {} {{- end }}?
總結一下整個過程
1)集群管理員預先創建存儲類(StorageClass);
2)用戶創建使用存儲類的持久化存儲聲明(PVC:PersistentVolumeClaim);
3)存儲持久化聲明通知系統,它需要一個持久化存儲(PV: PersistentVolume);
4)系統讀取存儲類的信息;
5)系統基于存儲類的信息,在后臺自動創建PVC需要的PV;
6)用戶創建一個使用PVC的Pod;
7)Pod中的應用通過PVC進行數據的持久化;
8)而PVC使用PV進行數據的最終持久化處理。
?
官方文檔?https://kubernetes.io/docs/concepts/storage/persistent-volumes/
?
轉載于:https://www.cnblogs.com/yanh0606/p/11269142.html
總結
以上是生活随笔為你收集整理的Kubernetes对象中的PersistentVolume、PersistentVolumeClaim和StorageClass的概念关系的全部內容,希望文章能夠幫你解決所遇到的問題。