Kubernetes中的storageclass存储类
华子目录
存储类storageclass
尽管PersistentVolumeClaim(pvc) 允许用户消耗抽象的存储资源, 常见的情况是针对不同的问题,用户需要的是具有不同属性(如,性能的PersistentVolume卷。 集群管理员需要能够提供不同性质的PersistentVolume, 并且这些PV卷之间的差别不仅限于卷大小和访问模式,同时又不能将卷是如何实现的这些细节暴露给用户。 为了满足这类需求,就有了存储类(StorageClass)资源。
存储类的作用
一、定义存储特性
StorageClass为管理员提供了一种描述存储的方式,允许他们定义特定的存储提供者(如AWS EBS、Azure Disk、GCE Persistent Disk等)、预配置的策略(如备份策略、加密)、IO性能、访问模式等。这使得用户能够以抽象的方式使用这些存储,而无需关心后端存储的具体实现细节。
二、动态卷供应
当用户在创建持久卷声明(PersistentVolumeClaim,PVC)时,只需要指定StorageClassName,Kubernetes即可根据这个StorageClass自动创建持久卷(PersistentVolume,PV)及底层存储。这大大减少了手动创建并维护PV的工作量,提高了存储管理的灵活性和效率。
三、管理多种存储类型
在Kubernetes集群中,可能需要连接到不同类型的存储,如SSD和HDD等。StorageClass可以帮助管理这些存储选项,通过定义不同的StorageClass来区分不同类型的存储,从而满足应用程序对存储性能、容量等方面的不同需求。
四、抽象存储细节
通过使用StorageClass,用户不需要了解后端存储的具体实现细节,只需要知道不同的StorageClass名称及其提供的存储类型和性能。这使得存储管理更加简单和直观,同时也提高了系统的可扩展性和可维护性。
五、支持存储扩展和回收策略
StorageClass还支持存储卷的扩展和回收策略的配置。例如,可以设置是否允许卷扩展,以及当PVC被删除时PV的回收策略(如Delete或Retain)。这些配置使得存储管理更加灵活和可控。
六、应用场景
StorageClass在Kubernetes中的应用场景非常广泛,特别是在需要持久化存储的应用程序中。例如,在部署需要存储数据的集群时(如Elasticsearch集群),每个节点都需要存储数据,而传统的PV只能挂载到一个Pod上。通过定义StorageClass并配合StatefulSet控制器,可以为每个有状态的Pod自动创建PVC并进行挂载,从而实现数据的持久化存储。
StorageClass说明
StorageClass为管理员提供了描述存储类的方法。不同的类型可能会映射到不同的服务质量等级或备份策略,或是由集群管理员制定的任意策略。Kubernetes本身并不清楚各种类代表的什么Kubernetes存储类的概念类似于一些其他存储系统设计中的"配置文件"- 每个
StorageClass都包含provisioner、parameters和reclaimPolicy字段, 这些字段会在StorageClass动态制备PersistentVolume以满足PersistentVolumeClaim(PVC) 时使用到 StorageClass对象的命名很重要,用户使用这个命名来请求生成一个特定的类。 当创建StorageClass对象时,管理员设置StorageClass对象的命名和其他参数
默认StorageClass
- 可以将某个
StorageClass标记为集群的默认存储类。当一个PVC没有指定storageClassName时,会使用默认的StorageClass。如果在集群中的多个StorageClass上将storageclass.kubernetes.io/is-default-class注解设置为true,然后创建一个未设置storageClassName的PersistentVolumeClaim(PVC),Kubernetes将使用最近创建的默认StorageClass - 可以在创建新的
PVC时不指定storageClassName,即使在集群中没有默认StorageClass的情况下也可以这样做。 在这种情况下,新的PVC会按照定义的方式进行创建,并且该PVC的storageClassName将保持不设置, 直到有可用的默认StorageClass为止 - 可以拥有一个
没有任何默认StorageClass的集群。 如果集群中没有StorageClass标记为默认(例如,云服务提供商还没有为你设置默认值),那么Kubernetes将无法为需要StorageClass的PersistentVolumeClaim应用默认值 - 默认
StorageClass变得可用时,控制平面会查找所有未设置storageClassName的现有PVC。 对于那些storageClassName值为空或没有此键的PVC,控制平面将更新它们, 将storageClassName设置为匹配新的默认StorageClass。但是如果有一个现成的PVC,其storageClassName为"", 并且之前就已经配置了默认的StorageClass,那么该PVC将不会被更新 - 当
默认的StorageClass存在时,为了继续绑定到storageClassName为""的PV, 需要将关联PVC的storageClassName设置为""
StorageClass的属性
属性说明:https://kubernetes.io/zh/docs/concepts/storage/storage-classes/
Provisioner(存储制备器):用来决定使用哪个卷插件制备PV,该字段必须指定。可以指定内部分配器,也可以指定外部分配器。外部分配器的代码地址为:kubernetes-incubator/external-storage,其中包括NFS和Ceph等Reclaim Policy(回收策略):通过reclaimPolicy字段指定创建的Persistent Volume的回收策略,回收策略包括:Delete或者Retain,没有指定默认为Delete
存储制备器
- 每个
StorageClass都有一个制备器(Provisioner),用来决定使用哪个卷插件制备PV。该字段必须指定

- 除了
"内置" 制备器(其名称前缀为"kubernetes.io"并打包在Kubernetes中)。还可以运行和指定外部制备器,这些独立的程序遵循由Kubernetes定义的规范。外部供应商的作者完全可以自由决定他们的代码保存于何处、打包方式、运行方式、使用的插件(包括Flex)等。代码仓库kubernetes-sigs/sig-storage-lib-external-provisioner包含一个用于为外部制备器编写功能实现的类库。可以访问代码仓库kubernetes-sigs/sig-storage-lib-external-provisioner了解外部驱动列表 例如,NFS没有内部制备器,但可以使用外部制备器。也有第三方存储供应商提供自己的外部制备器
存储制备器NFS Client Provisioner
源码地址:https://github.com/kubernetes-sigs/nfs-subdir-external-provisionerNFS Client Provisioner是一个automatic provisioner,使用NFS作为存储,自动创建PV和对应的PVC。k8s本身不提供NFS存储,需要外部先有一套NFS存储服务PV以${namespace}-${pvcName}-${pvName}的命名格式提供(在NFS服务器上)PV回收的时候,如果设置的回收策略是保留,则会以archieved-${namespace}-${pvcName}-${pvName}的命名格式在NFS服务器上进行打包
什么是卷插件
在Kubernetes(K8s)中,卷插件(Volume Plugins)是K8s存储系统的重要组成部分,它们允许用户将外部存储系统或特定类型的存储卷集成到K8s集群中,从而实现数据的持久化存储和管理。以下是对K8s中卷插件的详细解析:
一、卷插件的作用
卷插件主要用于扩展K8s的存储功能,使其能够支持多种不同的存储后端,如网络存储、本地存储、云存储等。通过卷插件,用户可以将这些存储后端挂载到Pod中,从而实现数据的持久化存储和共享。
二、卷插件的类型
K8s支持多种类型的卷插件,包括但不限于以下几种:
EmptyDir:一种临时目录,用于存储Pod中的临时数据。当Pod被删除时,EmptyDir中的数据也会被删除。HostPath:将节点上的文件系统目录挂载到Pod中。这种类型通常用于开发或测试环境,不推荐在生产环境中使用。- GCEPersistentDisk:Google Cloud Platform的持久化磁盘。
- AWSElasticBlockStore:Amazon Web Services的Elastic Block Store。
NFS:网络文件系统,允许Pod访问远程NFS服务器上的文件。- CephFS:一种分布式文件系统,提供了高性能和可扩展性。
- Cinder:OpenStack的块存储服务。
- GlusterFS:一个开源的分布式文件系统,提供了高可用性、高扩展性和高性能。
- FlexVolume:一种通用卷插件,允许用户指定自定义的驱动程序来管理存储卷。
- CSI(Container Storage Interface):一种标准的存储接口,使得存储插件可以以容器的方式运行,并与K8s集群进行交互。CSI插件支持多种存储后端,并且具有更高的可扩展性和灵活性。
三、如何使用卷插件
使用K8s中的卷插件通常涉及以下几个步骤:
配置存储卷插件:首先,需要编写一个StorageClass定义文件,指定要使用的存储卷插件及其相关参数。创建存储卷声明(PVC):然后,需要创建一个PersistentVolumeClaim(PVC)来请求存储卷。PVC中指定了存储卷的访问模式、大小以及要使用的StorageClass的名称。K8s会根据PVC中的请求自动找到合适的存储卷并绑定到PVC上。创建Pod并挂载存储卷:最后,可以创建一个Pod来挂载PVC中的存储卷。在Pod的定义文件中,需要指定要挂载的存储卷的名称以及挂载路径。当Pod被创建时,K8s会自动将PVC绑定到的存储卷挂载到指定的路径上。
部署NFS Client Provisioner存储分配器
创建sa并授权
[root@k8s-master volume]# vim rbac.yml
apiVersion: v1 #Kubernetes API的版本,这里是v1
kind: Namespace #创建的资源类型是Namespace
metadata: #namespace的元数据
name: nfs-client-provisioner #创建的命名空间的名称,这里被命名为nfs-client-provisioner。命名空间的名称在集群内必须是唯一的
#这个配置的作用是在Kubernetes集群中创建一个名为nfs-client-provisioner的新命名空间
---
apiVersion: v1
kind: ServiceAccount #资源类型是ServiceAccount
metadata: #ServiceAccount的元数据
name: nfs-client-provisioner #ServiceAccount的名称
namespace: nfs-client-provisioner #指定了ServiceAccount所属的命名空间
#这段配置创建了一个名为nfs-client-provisioner的ServiceAccount,它位于名为nfs-client-provisioner的命名空间中
---
apiVersion: rbac.authorization.k8s.io/v1 #API版本是rbac.authorization.k8s.io/v1,这是rbac相关资源(如Role、ClusterRole、RoleBinding、ClusterRoleBinding等)的API版本
kind: ClusterRole #Kubernetes资源类型是ClusterRole
metadata: #ClusterRole的元数据
name: nfs-client-provisioner-runner #ClusterRole的名称
rules: #ClusterRole的权限规则
- apiGroups: [""] #第一条规则允许对nodes资源进行get、list和watch操作
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""] #第二条规则允许对persistentvolumes资源进行get、list、watch、create和delete操作
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""] #第三条规则允许对persistentvolumeclaims资源进行get、list、watch和update操作
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"] #第四条规则允许对storageclasses资源进行get、list和watch操作
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""] #第五条规则允许对events资源进行create、update和patch操作
resources: ["events"]
verbs: ["create", "update", "patch"]
#这个ClusterRole为nfs-client-provisioner提供了必要的权限来动态地管理NFS存储卷,包括创建、删除持久卷,响应持久卷请求,以及记录相关事件
---
apiVersion: rbac.authorization.k8s.io/v1 #API版本是rbac.authorization.k8s.io/v1,这是rbac相关资源(如Role、ClusterRole、RoleBinding、ClusterRoleBinding等)的API版本
kind: ClusterRoleBinding #这是RBAC相关资源(如Role、ClusterRole、RoleBinding、ClusterRoleBinding等)的API版本
metadata: #ClusterRoleBinding的元数据
name: run-nfs-client-provisioner #ClusterRoleBinding的名称
subjects: #ClusterRoleBinding的主体列表,即哪些用户、组或服务账户将被授予ClusterRole的权限
- kind: ServiceAccount #主体的类型是ServiceAccount
name: nfs-client-provisioner #ServiceAccount的名称,与之前定义的ServiceAccount名称一致
namespace: nfs-client-provisioner #ServiceAccount所在的命名空间
roleRef: #定义了ClusterRoleBinding引用的ClusterRole
kind: ClusterRole #指明引用的资源类型是ClusterRole
name: nfs-client-provisioner-runner #ClusterRole的名称,与之前定义的ClusterRole名称一致
apiGroup: rbac.authorization.k8s.io #API组,对于ClusterRole来说,这个值通常是rbac.authorization.k8s.io
#这个ClusterRoleBinding将nfs-client-provisioner-runner ClusterRole的权限授予了nfs-client-provisioner ServiceAccount
---
apiVersion: rbac.authorization.k8s.io/v1 #API版本是rbac.authorization.k8s.io/v1,这是rbac相关资源(如Role、ClusterRole、RoleBinding、ClusterRoleBinding等)的API版本
kind: Role #表示定义的对象类型是一个角色(Role)。角色是权限的集合,可以授予给特定的用户或服务账户
metadata: #role角色的元数据
name: leader-locking-nfs-client-provisioner #角色的名称
namespace: nfs-client-provisioner #指定了角色所在的命名空间
rules: #角色拥有的权限
- apiGroups: [""] #指定了API组。空字符串""表示核心组(Core Group)
resources: ["endpoints"] #指定了角色可以访问的资源类型,这里是endpoints。Endpoints资源用于存储服务(Service)的IP地址和端口号
verbs: ["get", "list", "watch", "create", "update", "patch"] #列出了角色可以对指定的资源执行的操作。在这个例子中,角色可以执行get(获取)、list(列出)、watch(监听变化)、create(创建)、update(更新)和patch(部分更新)操作
---
apiVersion: rbac.authorization.k8s.io/v1 #API版本是rbac.authorization.k8s.io/v1,这是rbac相关资源(如Role、ClusterRole、RoleBinding、ClusterRoleBinding等)的API版本
kind: RoleBinding #RoleBinding资源。RoleBinding用于将角色(Role)或集群角色(ClusterRole)绑定到一个或多个主体(subject),这些主体通常是用户(User)、组(Group)或服务账户(ServiceAccount)
metadata: #RoleBinding的元数据
name: leader-locking-nfs-client-provisioner #RoleBinding的名称
namespace: nfs-client-provisioner #RoleBinding所在的命名空间
subjects: #RoleBinding绑定到的主体列表
- kind: ServiceAccount #主体类型,这里是服务账户(ServiceAccount)
name: nfs-client-provisioner #服务账户的名称,这里是nfs-client-provisioner
namespace: nfs-client-provisioner #服务账户所在的命名空间,这里同样是nfs-client-provisioner
roleRef: #RoleBinding引用的角色
kind: Role #角色类型,这里是Role
name: leader-locking-nfs-client-provisioner #角色的名称,这里与RoleBinding的名称相同,即leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io #API组,这里是RBAC的API组
[root@k8s-master volume]# kubectl apply -f rbac.yml
namespace/nfs-client-provisioner 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
[root@k8s-master volume]# kubectl -n nfs-client-provisioner get sa
NAME SECRETS AGE
default 0 27s
nfs-client-provisioner 0 27s
[root@k8s-master volume]# vim deployment.yml
apiVersion: apps/v1 #API版本是apps/v1
kind: Deployment #Deployment资源
metadata: #Deployment的元数据
name: nfs-client-provisioner #Deployment的名称
labels:
app: nfs-client-provisioner #标签app: nfs-client-provisioner
namespace: nfs-client-provisioner #Deployment所在的命名空间,这里是nfs-client-provisioner
spec: #Deployment的规格
replicas: 1 #Pod的副本数量为1
strategy: #Pod的更新策略
type: Recreate #更新策略类型为重建(Recreate),即先销毁旧的Pod,再创建新的Pod
selector: #Pod的选择器,用于匹配哪些Pod属于这个Deployment
matchLabels:
app: nfs-client-provisioner #匹配标签app: nfs-client-provisioner
template: #Pod的模板
metadata: #Pod的元数据
labels:
app: nfs-client-provisioner #Pod定义标签
spec: #Pod的规格
serviceAccountName: nfs-client-provisioner #指定Pod使用的服务账户(ServiceAccount)名称,这里是nfs-client-provisioner
containers: #Pod中的容器列表
- name: nfs-client-provisioner
image: sig-storage/nfs-subdir-external-provisioner:v4.0.2
volumeMounts: #容器挂载的卷列表
- name: nfs-client-root #挂载的卷名称,这里与后面定义的卷名称对应
mountPath: /persistentvolumes #挂载路径,即容器内的路径
env: #容器的环境变量列表
- name: PROVISIONER_NAME
value: k8s-sigs.io/nfs-subdir-external-provisioner #NFS存储卷配置器的名称,这里是k8s-sigs.io/nfs-subdir-external-provisioner
- name: NFS_SERVER
value: 172.25.254.250 #NFS服务器的IP地址,这里是172.25.254.250
- name: NFS_PATH
value: /nfsdata #NFS服务器上存储数据的路径,这里是/nfsdata
volumes: #Pod中的卷列表
- name: nfs-client-root #卷的名称,这里与前面容器挂载的卷名称对应
nfs: #NFS类型的卷
server: 172.25.254.250 #NFS服务器的IP地址
path: /nfsdata #NFS服务器上存储数据的路径
#这个Deployment将部署一个Pod,该Pod运行NFS客户端动态存储卷配置器,它使用指定的NFS服务器和路径来动态地为Kubernetes集群提供存储卷。通过配置环境变量,NFS客户端动态存储卷配置器知道如何注册到Kubernetes集群中,并响应存储卷的创建和删除请求


nfs-subdir-external-provisioner是存储类用到的外部插件
[root@k8s-master volume]# docker load -i nfs-subdir-external-provisioner-4.0.2.tar
[root@k8s-master volume]# docker tag registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2 harbor.huazi.org/sig-storage/nfs-subdir-external-provisioner:v4.0.2
[root@k8s-master volume]# docker push harbor.huazi.org/sig-storage/nfs-subdir-external-provisioner:v4.0.2
[root@k8s-master volume]# kubectl apply -f deployment.yml
deployment.apps/nfs-client-provisioner created
[root@k8s-master volume]# kubectl -n nfs-client-provisioner get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
nfs-client-provisioner 1/1 1 1 27s
创建StorageClass存储类
[root@k8s-master volume]# vim class.yml
apiVersion: storage.k8s.io/v1 #API版本是storage.k8s.io/v1,这是StorageClass资源的稳定版本
kind: StorageClass #指定这是一个StorageClass资源
metadata: #StorageClass的元数据
name: nfs-client #StorageClass的名称
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner #指定了动态存储卷的提供者,这里是k8s-sigs.io/nfs-subdir-external-provisioner。这意味着当需要创建新的存储卷时,Kubernetes将调用这个NFS客户端动态存储卷配置器来创建
parameters: #这是一个可选字段,用于向存储卷提供者传递额外的配置参数
archiveOnDelete: "false" #这个参数告诉NFS客户端动态存储卷配置器,在删除PVC(PersistentVolumeClaim)时,是否应该将对应的NFS子目录归档(或保留)。这里设置为"false",意味着当PVC被删除时,对应的NFS子目录也会被删除
[root@k8s-master volume]# kubectl apply -f class.yml
storageclass.storage.k8s.io/nfs-client created
#StorageClass的缩写sc
[root@k8s-master volume]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-client k8s-sigs.io/nfs-subdir-external-provisioner Delete Immediate false 34s
创建pvc
[root@k8s-master volume]# vim pvc.yml
apiVersion: v1 #API版本是v1
kind: PersistentVolumeClaim #PersistentVolumeClaim资源
metadata: #PVC的元数据
name: test-claim #PVC的名称
spec: #PVC的规格
storageClassName: nfs-client #指定了这个PVC应该使用的StorageClass的名称,这里是nfs-client。这意味着Kubernetes将使用这个StorageClass的配置来动态地创建一个满足PVC要求的PersistentVolume(PV)
accessModes: #PVC的访问模式列表
- ReadWriteMany #多点读写
resources: #PVC请求的存储资源
requests: #请求的存储大小和类型
storage: 1G #请求的存储大小为1GB
#创建这个PVC后,Kubernetes将查找一个匹配的StorageClass(在这个例子中是nfs-client),并根据PVC的规格和请求的参数动态地创建一个PersistentVolume(PV)。一旦PV被成功创建并绑定到PVC上,用户就可以在Pod中使用这个PVC来访问存储资源了
[root@k8s-master volume]# kubectl apply -f pvc.yml
persistentvolumeclaim/test-claim created
[root@k8s-master volume]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
test-claim Bound pvc-a164d606-732f-4005-a6a6-4798fdbc75f4 1G RWX nfs-client <unset> 90s
#在nfs服务器上可以看到
[root@harbor ~]# cd /nfsdata/
[root@harbor nfsdata]# ls
default-test-claim-pvc-a164d606-732f-4005-a6a6-4798fdbc75f4
#当我们删掉pvc后
[root@k8s-master volume]# kubectl delete -f pvc.yml
persistentvolumeclaim "test-claim" deleted
#再查看nfs服务器,发现pv已经被自动删除了
[root@harbor nfsdata]# ls
[root@harbor nfsdata]#
[root@k8s-master volume]# kubectl apply -f pvc.yml
persistentvolumeclaim/test-claim created
创建测试pod
[root@k8s-master volume]# vim pod.yml
apiVersion: v1 #API版本是v1
kind: Pod #指定这是一个Pod资源
metadata: #Pod的元数据
name: test-pod #Pod的名称,这里是test-pod
spec: #Pod的规格
containers:
- name: test-pod
image: busybox
command: #容器启动时执行的命令
- "/bin/sh"
args:
- "-c" #容器将执行/bin/sh -c "touch /mnt/SUCCESS && exit 0 || exit 1",这个命令会在/mnt目录下创建一个名为SUCCESS的文件,如果成功则退出状态码为0,否则为1
- "touch /mnt/SUCCESS && exit 0 || exit 1"
volumeMounts: #容器内挂载的卷列表
- name: nfs-pvc #挂载的卷的名称,与Pod规格中的volumes部分定义的卷名称相对应
mountPath: "/mnt" #卷在容器内的挂载路径
restartPolicy: "Never" #Pod的重启策略。在这个例子中,如果容器退出,Pod将不会被重启
volumes: #Pod中使用的卷列表
- name: nfs-pvc #卷的名称,与volumeMounts中引用的名称相对应
persistentVolumeClaim: #指定这个卷是一个PersistentVolumeClaim
claimName: test-claim #PVC的名称
#创建这个Pod后,Kubernetes将尝试找到名为test-claim的PVC,并查找与之绑定的PersistentVolume(PV)。一旦找到了匹配的PV,Pod中的容器就可以通过/mnt路径访问这个NFS存储卷了。容器将尝试在/mnt目录下创建一个名为SUCCESS的文件,如果成功,Pod将正常退出(状态码0),否则将异常退出(非0状态码)
[root@k8s-master volume]# kubectl apply -f pod.yml
pod/test-pod created
[root@k8s-master volume]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-pod 0/1 Completed 0 38s 10.244.2.38 k8s-node2.org <none> <none>
[root@harbor nfsdata]# ls
default-test-claim-pvc-4460dd22-b4d8-4192-b249-3b687dacdf39
[root@harbor nfsdata]# cd default-test-claim-pvc-4460dd22-b4d8-4192-b249-3b687dacdf39/
[root@harbor default-test-claim-pvc-4460dd22-b4d8-4192-b249-3b687dacdf39]# ls
SUCCESS
[root@harbor default-test-claim-pvc-4460dd22-b4d8-4192-b249-3b687dacdf39]# ll
总用量 0
-rw-r--r-- 1 root root 0 11月 4 22:36 SUCCESS
pod--->pvc--->pv--->storageclass
设置默认的存储类
更多推荐


所有评论(0)