k8s----持久化存储 storage class
上面介绍的PV和PVC模式都是需要先创建好PV,然后定义好PVC和pv进行一对一的Bond,但是如果PVC请求成千上万,那么就需要创建成千上万的PV,对于运维人员来说维护成本很高,Kubernetes提供一种自动创建PV的机制,叫,它的作用就是创建PV的模板。k8s集群管理员通过创建storageclass可以动态生成一个存储卷pv供k8s pvc使用。每个StorageClass都包含字段pro
目录
二、安装nfs provisioner,用于配合存储类动态生成pv
5、创建pod,挂载storageclass动态生成的pvc:storage-pvc
6、删除read-pod ,删除pvc 会自动删除pv ,所以默认的回收策略是delete是可以验证出来的
一、概述
上面介绍的PV和PVC模式都是需要先创建好PV,然后定义好PVC和pv进行一对一的Bond,但是如果PVC请求成千上万,那么就需要创建成千上万的PV,对于运维人员来说维护成本很高,Kubernetes提供一种自动创建PV的机制,叫StorageClass,它的作用就是创建PV的模板。k8s集群管理员通过创建storageclass可以动态生成一个存储卷pv供k8s pvc使用。
每个StorageClass都包含字段provisioner,parameters和reclaimPolicy。
具体来说,StorageClass会定义以下两部分:
1、PV的属性 ,比如存储的大小、类型等;
2、创建这种PV需要使用到的存储插件,比如Ceph、NFS等
有了这两部分信息,Kubernetes就能够根据用户提交的PVC,找到对应的StorageClass,然后Kubernetes就会调用 StorageClass声明的存储插件,创建出需要的PV。
StorageClass运行原理
-
volumeClaimTemplates实现了pvc的自动化,StorageClass实现了pv的自动化
-
每个 StorageClass 都包含 provisioner、parameters 和 reclaimPolicy 字段, 这些字段会在 StorageClass 需要动态分配 PersistentVolume 时会使用到。
-
StorageClass 对象的命名很重要,用户使用这个命名来请求生成一个特定的类。 当创建 StorageClass 对象时,管理员设置 StorageClass 对象的命名和其他参数,一旦创建了对象就不能再对其更新。
-
管理员可以为没有申请绑定到特定 StorageClass 的 PVC 指定一个默认的存储类
要使用 StorageClass,我们就得安装对应的自动配置程序,比如我们这里存储后端使用的是 nfs,那么我们就需要使用到一个 nfs-client 的自动配置程序,我们也叫它 Provisioner(制备器),这个程序使我们已经配置好的 nfs 服务器,来自动创建持久卷,也就是自动帮我们创建 PV。
搭建StorageClass+NFS,大致有以下几个步骤:
1.创建一个可用的NFS Serve(实际存储文件的空间)
2.创建Service Account 这是用来管控NFS provisioner在k8s集群中运行的权限
3.创建StorageClass 负责建立PVC并调用NFS provisioner进行预定的工作,并让PV与PVC建立管理
4.创建NFS provisioner(存储制备器)
1)每个 StorageClass 都有一个制备器(Provisioner)用来决定使用哪个卷插件制备 PV。 该字段必须指定。
2)主要有两个功能
一个是在NFS共享目录下创建挂载点(volume)
另一个则是建了PV并将PV与NFS的挂载点建立关联
StorageClass 动态供给
核心架构
graph TB
PVC-->|1.申请存储| StorageClass
StorageClass-->|2.调用| Provisioner
Provisioner-->|3.创建| PV
PV-->|4.绑定| PVC
Pod-->|5.挂载| PVC
存储方案选型对比
特性 | emptyDir | hostPath | NFS | PVC+StorageClass |
---|---|---|---|---|
持久性 | ❌ Pod删除消失 | ⚠️ 节点故障丢失 | ✅ 持久化 | ✅ 持久化 |
多节点共享 | ❌ | ❌ | ✅ | ✅ |
动态扩容 | ❌ | ❌ | ❌ | ✅ |
生产环境适用性 | 低 | 低 | 中 | 高 |
典型场景 | 临时缓存 | 节点日志收集 | 团队文件共享 | 数据库/有状态服务 |
storageclass字段
#查看定义的storageclass需要的字段
[root@k8s-master~]# kubectl explain storageclass
KIND: StorageClass
VERSION: storage.k8s.io/v1
DESCRIPTION:
StorageClass describes the parameters for a class of storage for which
PersistentVolumes can be dynamically provisioned.
StorageClasses are non-namespaced; the name of the storage class according
to etcd is in ObjectMeta.Name.
FIELDS:
allowVolumeExpansion <boolean>
allowedTopologies <[]Object>
apiVersion <string>
kind<string>
metadata<Object>
mountOptions <[]string>
parameters <map[string]string>
provisioner<string> -required-
reclaimPolicy <string>
volumeBindingMode <string>
二、安装nfs provisioner,用于配合存储类动态生成pv
案例:
1、创建运行nfs-provisioner需要的sa账号
(在nfs服务器上操作)
注意名称一定要相同
[root@k8s-master pvc]# cat sa.yaml
apiVersion: v1
kind: Namespace
metadata:
name: newnfs
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
namespace: newnfs
---
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
namespace: newnfs
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
namespace: newnfs
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
namespace: newnfs
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: newnfs
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
[root@k8s-master pvc]# kubectl apply -f sa.yaml
namespace/newnfs created
serviceaccount/nfs-client-provisioner created
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner created
role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
2、安装nfs-provisioner程序
#把/data变成nfs共享的目录
[root@k8s-master pvc]# vim /etc/exports
/data 192.168.158.0/24(rw,sync,no_root_squash)
/data 192.168.158.0/24(rw,no_root_squash)
/data/v1 192.168.158.0/24(rw,no_root_squash)
/data/v2 192.168.158.0/24(rw,no_root_squash)
/data/v3 192.168.158.0/24(rw,no_root_squash)
/data/v4 192.168.158.0/24(rw,no_root_squash)
/data/v5 192.168.158.0/24(rw,no_root_squash)
/data/v6 192.168.158.0/24(rw,no_root_squash)
/data/v7 192.168.158.0/24(rw,no_root_squash)
/data/v8 192.168.158.0/24(rw,no_root_squash)
/data/v9 192.168.158.0/24(rw,no_root_squash)
/data/v10 192.168.158.0/24(rw,no_root_squash)
~
[root@k8s-master pvc]# vim nfs.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: nfs-client-provisioner
namespace: newnfs
spec:
replicas: 1
selector:
matchLabels:
app: nfs-client-provisioner
strategy:
type: Recreate #设置升级策略为删除再创建(默认为滚动更新)
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner #上一步创建的ServiceAccount名称
containers:
- name: nfs-client-provisioner
image: registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME # Provisioner的名称,以后设置的storageclass要和这个保持一致
value: storage-nfs
- name: NFS_SERVER # NFS服务器地址,需和valumes参数中配置的保持一致
value: 192.168.158.33
- name: NFS_PATH # NFS服务器数据存储目录,需和volumes参数中配置的保持一致
value: /data
- name: ENABLE_LEADER_ELECTION
value: "true"
volumes:
- name: nfs-client-root
nfs:
server: 192.168.158.33 # NFS服务器地址
path: /data # NFS共享目录
更新资源清单文件
[root@k8s-master pvc]# kubectl apply -f nfs.yaml
deployment.apps/nfs-client-provisioner created
查看nfs-provisioner是否正常运行
[root@k8s-master pvc]# kubectl -n newnfs get pods | grep nfs
NAME READY STATUS RESTARTS AGE
nfs-client-provisioner-9b865c8cb-w7txl 1/1 Running 0 119s
[root@k8s-master pvc]# kubectl -n newnfs get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
nfs-client-provisioner 1/1 1 1 2m38s
3 创建storageclass,动态供给pv
server nfs 版本是v4
[root@k8s-master pvc]# vim sc.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
namespace: newnfs
name: nfs-storage
annotations:
storageclass.kubernetes.io/is-default-class: "false" ## 是否设置为默认的storageclass
provisioner: storage-nfs ## 动态卷分配者名称,必须和上面创建的deploy中环境变量“PROVISIONER_NAME”变量值一致
parameters:
archiveOnDelete: "true" ## 设置为"false"时删除PVC不会保留数据,"true"则保留数据
mountOptions:
- hard ## 指定为硬挂载方式
- nfsvers=4 ## 指定NFS版本,这个需要根据NFS Server版本号设置nfs
[root@k8s-master pvc]# kubectl apply -f sc.yaml
storageclass.storage.k8s.io/nfs-storage created
查看storageclass是否创建成功
[root@k8s-master pvc]# kubectl -n newnfs get storageclasses.storage.k8s.io
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-storage storage-nfs Delete Immediate false 23s
显示内容如上,说明storageclass创建成功了
注意:provisioner处写的example.com/nfs应该跟安装nfs provisioner时候的env下的PROVISIONER_NAME的value值保持一致,如下:
env: name: PROVISIONER_NAME value: storage-nfs
4、创建pvc,通过storageclass动态生成pv
[root@k8s-master pvc]# vim pvc1.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: storage-pvc
namespace: newnfs
spec:
storageClassName: nfs-storage ## 需要与上面创建的storageclass的名称一致
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Mi
提交资源清单
[root@k8s-master pvc]# kubectl apply -f pvc1.yaml
persistentvolumeclaim/storage-pvc created
查看是否动态生成了pv,pvc是否创建成功,并和pv绑定
[root@k8s-master pvc]# kubectl -n newnfs get persistentvolumeclaims
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
storage-pvc Bound pvc-db0dc568-7b80-4fc9-b9ad-d9f7c5642cb7 1Mi RWO nfs-storage 30s
[root@k8s-master pvc]# kubectl -n newnfs get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-db0dc568-7b80-4fc9-b9ad-d9f7c5642cb7 1Mi RWO Delete Bound newnfs/storage-pvc nfs-storage 77s
[root@k8s-master pvc]# kubectl -n newnfs get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
storage-pvc Bound pvc-db0dc568-7b80-4fc9-b9ad-d9f7c5642cb7 1Mi RWO nfs-storage 84s
[root@k8s-master pvc]#
步骤总结:
1、供应商:创建一个nfs provisioner
2、创建storageclass,storageclass指定刚才创建的供应商
3、创建pvc,这个pvc指定storageclass
5、创建pod,挂载storageclass动态生成的pvc:storage-pvc
[root@k8s-master pvc]# vim read-pod.yaml
kind: Pod
apiVersion: v1
metadata:
name: read-pod
namespace: newnfs
spec:
containers:
- name: read-pod
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs-pvc
mountPath: /usr/share/nginx/html
restartPolicy: "Never"
volumes:
- name: nfs-pvc
persistentVolumeClaim:
claimName: storage-pvc
更新资源清单文件
[root@k8s-master pvc]# kubectl apply -f read-pod.yaml
pod/read-pod created
查看pod是否创建成功
[root@k8s-master ~]# kubectl -n newnfs get pod read-pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
read-pod 1/1 Running 0 4m26s 10.244.36.115 k8s-node1 <none> <none>
查看一下路径
[root@k8s-master pvc]# kubectl -n newnfs get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
storage-pvc Bound pvc-db0dc568-7b80-4fc9-b9ad-d9f7c5642cb7 1Mi RWO nfs-storage 27m
##在NFS服务端写入首页
[root@k8s-master pvc]# cd /data/newnfs-storage-pvc-pvc-db0dc568-7b80-4fc9-b9ad-d9f7c5642cb7/
[root@k8s-master newnfs-storage-pvc-pvc-db0dc568-7b80-4fc9-b9ad-d9f7c5642cb7]# echo nfs > index.html
##测试访问
[root@k8s-master newnfs-storage-pvc-pvc-db0dc568-7b80-4fc9-b9ad-d9f7c5642cb7]# cd
[root@k8s-master ~]# curl 10.244.36.115
nfs
查看index.html的物理位置
6、删除read-pod ,删除pvc 会自动删除pv ,所以默认的回收策略是delete是可以验证出来的
###删除 read-pod 后 pv 没有变化
[root@k8s-master data]# ls
index.html newnfs-storage-pvc-pvc-db0dc568-7b80-4fc9-b9ad-d9f7c5642cb7 v1 v10 v2 v3 v4 v5 v6 v7 v8 v9
[root@k8s-master data]# kubectl -n newnfs get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-db0dc568-7b80-4fc9-b9ad-d9f7c5642cb7 1Mi RWO Delete Bound newnfs/storage-pvc nfs-storage 31m
[root@k8s-master data]# kubectl -n newnfs delete pod read-pod
pod "read-pod" deleted
[root@k8s-master data]# kubectl -n newnfs get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-db0dc568-7b80-4fc9-b9ad-d9f7c5642cb7 1Mi RWO Delete Bound newnfs/storage-pvc nfs-storage 32m
###再删除 pvc , pv发生变化,没有了
[root@k8s-master data]# kubectl -n newnfs delete pvc storage-pvc
persistentvolumeclaim "storage-pvc" deleted
[root@k8s-master data]# kubectl -n newnfs get pv
No resources found
##在NFS服务端发生如下变化,会将原来的nfspv进行更改名称归档
archived-pvc-db0dc568-7b80-4fc9-b9ad-d9f7c5642cb7
[root@k8s-master data]# ls
archived-pvc-db0dc568-7b80-4fc9-b9ad-d9f7c5642cb7 index.html v1 v10 v2 v3 v4 v5 v6 v7 v8 v9
重新更新pvc文件,会发现物理nfs中多了一个目录。
newnfs-storage-pvc-pvc-4218d83c-d5f6-4dab-bc4e-fd638d4d59fb
[root@k8s-master data]# cd /root/pvc
[root@k8s-master pvc]# kubectl apply -f pvc1.yaml
persistentvolumeclaim/storage-pvc created
[root@k8s-master pvc]# cd /data
[root@k8s-master data]# ls
archived-pvc-db0dc568-7b80-4fc9-b9ad-d9f7c5642cb7 v1 v3 v6 v9
index.html v10 v4 v7
newnfs-storage-pvc-pvc-4218d83c-d5f6-4dab-bc4e-fd638d4d59fb v2 v5 v8
[root@k8s-master data]#
更多推荐
所有评论(0)