在k8s中對於存儲的資源抽象了兩個概念,分別是PersistentVolume(PV)、PersistentVolumeClaim(PVC)。
- PV是集群中的資源
- PVC是對這些資源的請求。
PV和PVC都只是抽象的概念,在k8s中是通過插件的方式提供具體的存儲實現,目前包含有NFS、ceph、iSCSI和雲提供商指定的存儲系統,
一、認識PV/PVC/StorageClass
1、概念介紹
管理存儲是管理計算的一個明顯問題。該PersistentVolume子系統為用戶和管理員提供了一個API,用於抽象如何根據消費方式提供存儲的詳細信息。為此,我們引入了兩個新的API資源:PersistentVolume和PersistentVolumeClaim
PV :PersistentVolume(持久化卷),是對底層的共享存儲的一種抽象,PV 由管理員進行創建和配置,它和具體的底層的共享存儲技術的實現方式有關,比如 Ceph、GlusterFS、NFS 等,都是通過插件機制完成與共享存儲的對接。
PersistentVolumeClaim(PVC)是由用戶進行存儲的請求。 它類似於pod。 Pod消耗節點資源,PVC消耗PV資源。Pod可以請求特定級別的資源(CPU和內存)。聲明可以請求特定的大小和訪問模式(例如,可以一次讀/寫或多次只讀)。
雖然PersistentVolumeClaims允許用戶使用抽象存儲資源,但是PersistentVolumes對於不同的問題,用戶通常需要具有不同屬性(例如性能)。群集管理員需要能夠提供各種PersistentVolumes不同的方式,而不僅僅是大小和訪問模式,而不會讓用戶了解這些卷的實現方式。對於這些需求,有StorageClass 資源。
StorageClass為管理員提供了一種描述他們提供的存儲的“類”的方法。 不同的類可能映射到服務質量級別,或備份策略,或者由群集管理員確定的任意策略。 Kubernetes本身對於什么類別代表是不言而喻的。 這個概念有時在其他存儲系統中稱為“配置文件”。
PV是運維人員來創建的,開發操作PVC,可是大規模集群中可能會有很多PV,如果這些PV都需要運維手動來處理這也是一件很繁瑣的事情,所以就有了動態供給概念,也就是Dynamic Provisioning,動態供給的關鍵就是StorageClass,它的作用就是創建PV模板。創建StorageClass里面需要定義PV屬性比如存儲類型、大小等;另外創建這種PV需要用到存儲插件。最終效果是,用戶提交PVC,里面指定存儲類型,如果符合我們定義的StorageClass,則會為其自動創建PV並進行綁定。
PVC和PV是一一對應的。
PV和PVC中的spec關鍵字段要匹配,比如存儲(storage)大小。
PV和PVC中的storageClassName字段必須一致。
2、生命周期
PV是群集中的資源。PVC是對這些資源的請求,並且還充當對資源的檢查。PV和PVC之間的相互作用遵循以下生命周期:
Provisioning ——-> Binding ——–>Using——>Releasing——>Recycling
- 供應准備Provisioning---通過集群外的存儲系統或者雲平台來提供存儲持久化支持。
- - 靜態提供Static:集群管理員創建多個PV。 它們攜帶可供集群用戶使用的真實存儲的詳細信息。 它們存在於Kubernetes API中,可用於消費
- - 動態提供Dynamic:當管理員創建的靜態PV都不匹配用戶的PersistentVolumeClaim時,集群可能會嘗試為PVC動態配置卷。 此配置基於StorageClasses:PVC必須請求一個類,並且管理員必須已創建並配置該類才能進行動態配置。 要求該類的聲明有效地為自己禁用動態配置。
- 綁定Binding---用戶創建pvc並指定需要的資源和訪問模式。在找到可用pv之前,pvc會保持未綁定狀態。
- 使用Using---用戶可在pod中像volume一樣使用pvc。
- 釋放Releasing---用戶刪除pvc來回收存儲資源,pv將變成“released”狀態。由於還保留着之前的數據,這些數據需要根據不同的策略來處理,否則這些存儲資源無法被其他pvc使用。
- 回收Recycling---pv可以設置三種回收策略:保留(Retain),回收(Recycle)和刪除(Delete)。
- - 保留策略:允許人工處理保留的數據。
- - 刪除策略:將刪除pv和外部關聯的存儲資源,需要插件支持。
- - 回收策略:將執行清除操作,之后可以被新的pvc使用,需要插件支持。
注:目前只有NFS和HostPath類型卷支持回收策略,AWS EBS,GCE PD,Azure Disk和Cinder支持刪除(Delete)策略。
3、PV類型
- GCEPersistentDisk
- AWSElasticBlockStore
- AzureFile
- AzureDisk
- FC (Fibre Channel)
- Flexvolume
- Flocker
- NFS
- iSCSI
- RBD (Ceph Block Device)
- CephFS
- Cinder (OpenStack block storage)
- Glusterfs
- VsphereVolume
- Quobyte Volumes
- HostPath (Single node testing only – local storage is not supported in any way and WILL NOT WORK in a multi-node cluster)
- Portworx Volumes
- ScaleIO Volumes
- StorageOS
4、PV卷階段狀態
- Available – 資源尚未被claim使用
- Bound – 卷已經被綁定到claim了
- Released – claim被刪除,卷處於釋放狀態,但未被集群回收。
- Failed – 卷自動回收失敗
二、創建PV演示
1、准備nfs服務
在nfs服務器上先建立存儲卷對應的目錄
[root@nfs ~]# cd /data/volumes/ [root@nfs volumes]# mkdir v{1,2,3,4,5} [root@nfs volumes]# ls index.html v1 v2 v3 v4 v5 [root@nfs volumes]# echo "<h1>NFS stor 01</h1>" > v1/index.html [root@nfs volumes]# echo "<h1>NFS stor 02</h1>" > v2/index.html [root@nfs volumes]# echo "<h1>NFS stor 03</h1>" > v3/index.html [root@nfs volumes]# echo "<h1>NFS stor 04</h1>" > v4/index.html [root@nfs volumes]# echo "<h1>NFS stor 05</h1>" > v5/index.html
修改nfs的配置
[root@nfs volumes]# vim /etc/exports /data/volumes/v1 192.168.130.0/24(rw,no_root_squash) /data/volumes/v2 192.168.130.0/24(rw,no_root_squash) /data/volumes/v3 192.168.130.0/24(rw,no_root_squash) /data/volumes/v4 192.168.130.0/24(rw,no_root_squash) /data/volumes/v5 192.168.130.0/24(rw,no_root_squash)
查看nfs的配置
[root@nfs volumes]# exportfs -arv exporting 192.168.130.0/24:/data/volumes/v5 exporting 192.168.130.0/24:/data/volumes/v4 exporting 192.168.130.0/24:/data/volumes/v3 exporting 192.168.130.0/24:/data/volumes/v2 exporting 192.168.130.0/24:/data/volumes/v1
配置生效
[root@nfs volumes]# showmount -e Export list for nfs: /data/volumes/v5 192.168.130.0/24 /data/volumes/v4 192.168.130.0/24 /data/volumes/v3 192.168.130.0/24 /data/volumes/v2 192.168.130.0/24 /data/volumes/v1 192.168.130.0/24
2、在master上創建PV
編寫yaml文件,並創建pv。創建5個pv,存儲大小各不相同,是否可讀也不相同
# vim pv-damo.yaml apiVersion: v1 kind: PersistentVolume metadata: name: pv001 labels: name: pv001 spec: nfs: path: /data/volumes/v1 server: nfs accessModes: ["ReadWriteMany","ReadWriteOnce"] capacity: storage: 2Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv002 labels: name: pv002 spec: nfs: path: /data/volumes/v2 server: nfs accessModes: ["ReadWriteOnce"] capacity: storage: 5Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv003 labels: name: pv003 spec: nfs: path: /data/volumes/v3 server: nfs accessModes: ["ReadWriteMany","ReadWriteOnce"] capacity: storage: 20Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv004 labels: name: pv004 spec: nfs: path: /data/volumes/v4 server: nfs accessModes: ["ReadWriteMany","ReadWriteOnce"] capacity: storage: 10Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv005 labels: name: pv005 spec: nfs: path: /data/volumes/v5 server: nfs accessModes: ["ReadWriteMany","ReadWriteOnce"] capacity: storage: 15Gi 注:accessModes:支持三種類型 ReadWriteMany 多路讀寫,卷能被集群多個節點掛載並讀寫 ReadWriteOnce 單路讀寫,卷只能被單一集群節點掛載讀寫 ReadOnlyMany 多路只讀,卷能被多個集群節點掛載且只能讀 nfs,它支持全部三種。但是ISCI就不支持ReadWriteMany;HostPath就不支持ReadOnlyMany和ReadWriteMany # kubectl apply -f pv-damo.yaml persistentvolume/pv001 created persistentvolume/pv002 created persistentvolume/pv003 created persistentvolume/pv004 created persistentvolume/pv005 created
查看pv狀態
kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv001 5Gi RWO,RWX Retain Available 9s pv002 5Gi RWO Retain Available 9s pv003 5Gi RWO,RWX Retain Available 9s pv004 10Gi RWO,RWX Retain Available 9s pv005 15Gi RWO,RWX Retain Available 9s
3、創建PVC,綁定PV
編寫yaml文件,並創建pvc。創建一個pvc,需要6G存儲;所以不會匹配pv001、pv002、pv003
vim vol-pvc-demo.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mypvc namespace: default spec: accessModes: ["ReadWriteMany"] resources: requests: storage: 6Gi --- apiVersion: v1 kind: Pod metadata: name: vol-pvc namespace: default spec: volumes: - name: html persistentVolumeClaim: claimName: mypvc containers: - name: myapp image: ikubernetes/myapp:v1 volumeMounts: - name: html mountPath: /usr/share/nginx/html/ kubectl apply -f vol-pvc-demo.yaml persistentvolumeclaim/mypvc created pod/vol-pvc created
查詢驗證:pvc已經綁定到pv004上
# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE mypvc Bound pv004 10Gi RWO,RWX 24s # kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv001 5Gi RWO,RWX Retain Available 1m pv002 5Gi RWO Retain Available 1m pv003 5Gi RWO,RWX Retain Available 1m pv004 10Gi RWO,RWX Retain Bound default/mypvc 1m pv005 15Gi RWO,RWX Retain Available 1m
查詢業務驗證
# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE vol-pvc 1/1 Running 0 59s 10.244.2.117 node2 # curl 10.244.2.117 <h1>NFS stor 04</h1>
三、動態存儲StorageClass
nfs默認不支持動態存儲,使用了第三方的NFS插件 external-storage,nfs-client-provisioner
。
1、流程圖
2、創建rbac授權
# cat rbac.yaml
apiVersion: v1 kind: ServiceAccount metadata: name: nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: default --- 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 # replace with namespace where provisioner is deployed namespace: default 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的nfs-client-provisioner
apiVersion: apps/v1 kind: Deployment metadata: name: nfs-client-provisioner labels: app: nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: default spec: replicas: 1 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: fuseim.pri/ifs - name: NFS_SERVER value: 10.10.10.60 - name: NFS_PATH value: /ifs/kubernetes volumes: - name: nfs-client-root nfs: server: 10.10.10.60 path: /ifs/kubernetes
注:
-value: 10.10.10.60 、server: 10.10.10.60 #換成自己nfs的ip
- name:
NFS_PATH value: /xxx/xxxx ##nfs共享的目錄。
4、創建客戶端
kubectl apply -f deployment.yaml
5、創建storage class
kubectl apply -f class.yaml
reclaimPolicy:有兩種策略:Delete、Retain。默認是Delet
fuseim.pri/ifs為上面deployment上創建的PROVISIONER_NAM(在“3、創建nfs的nfs-client-provisioner”)
6、查看 nfs 客戶端 和 storage class
客戶端 # kubectl get pod NAME READY STATUS RESTARTS AGE nfs-client-provisioner-7695c66c6b-56sbw 1/1 Running 0 10m storage class # kubectl get sc NAME PROVISIONER AGE managed-nfs-storage fuseim.pri/ifs 10m
7、創建PVC
kind: PersistentVolumeClaim apiVersion: v1 metadata: name: test-claim annotations: volume.beta.kubernetes.io/storage-class: "managed-nfs-storage" spec: accessModes: # 策略 - ReadWriteMany resources: requests: storage: 1Mi # 請求空間大小
創建PersistenetVolumeClaim
kubectl apply -f test-claim.yaml
查看 pvc
# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE test-claim Bound pvc-2febc25a-d2b0-11e9-9623-000c29b3776e 1Mi RWX managed-nfs-storage 14s
8、部署測試pod
kind: Pod apiVersion: v1 metadata: name: test-pod spec: containers: - name: test-pod image: nginx command: - "/bin/sh" args: - "-c" - "touch /mnt/SUCCESS && exit 0 || exit 1" volumeMounts: - name: nfs-pvc # 綁定pvc mountPath: "/mnt" restartPolicy: "Never" volumes: - name: nfs-pvc #pvc 通過pvc 動態創建pv persistentVolumeClaim: claimName: test-claim
創建 測試 pod
kubectl apply -f test-pod.yaml kubectl get pod | grep pod test-pod 0/1 Completed 0 81s kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-e78d0817-d2b0-11e9-9623-000c29b3776e 1Mi RWX Delete Bound default/test-claim managed-nfs-storage 22m
https://github.com/kubernetes-retired/external-storage github項目地址external-storage
https://www.cnblogs.com/panwenbin-logs/p/12196286.html 實戰,分析案例詳細
https://blog.csdn.net/weixin_30119911/article/details/112337003 實戰,tomcat使用storageclass