K8S 快速入门(十六)实战篇:StorageClass(存储类)
StorageClass
存储类 官方文档
上一节演示了 PVC的自动化实现方式:利用volumeClaimTemplates
这一节将讲解PV的自动化: 利用StorageClass实现,可以根据PVC需求,自动构建相对应的PV持久化存储卷,进一步简化运维管理成本。
1. 理论
在动态资源供应模式下,通过StorageClass和PVC完成资源动态绑定(系统自动生成PV),并供Pod使用的存储管理机制。
volumeClaimTemplates实现了pvc的自动化,StorageClass实现了pv的自动化
1.1 什么是StorageClass
Kubernetes提供了一套可以自动创建PV的机制,即:Dynamic Provisioning。而这个机制的核心在于StorageClass这个API对象。
StorageClass对象会定义下面两部分内容:
- 1. PV的属性。比如,存储类型,Volume的大小等。
- 2. 创建这种PV需要用到的存储插件,即存储制备器。
有了这两个信息之后,Kubernetes就能够根据用户提交的PVC,找到一个对应的StorageClass,之后Kubernetes就会调用该StorageClass声明的存储插件,进而创建出需要的PV。
但是其实使用起来是一件很简单的事情,你只需要根据自己的需求,编写YAML文件即可,然后使用kubectl create命令执行即可。
StorageClass 为管理员提供了描述存储 “类” 的方法。 不同的类型可能会映射到不同的服务质量等级或备份策略,或是由集群管理员制定的任意策略。 Kubernetes 本身并不清楚各种类代表的什么。这个类的概念在其他存储系统中有时被称为 “配置文件”。
1.2 为什么需要StorageClass
在一个大规模的Kubernetes集群里,可能有成千上万个PVC,这就意味着运维人员必须实现创建出这个多个PV,此外,随着项目的需要,会有新的PVC不断被提交,那么运维人员就需要不断的添加新的,满足要求的PV,否则新的Pod就会因为PVC绑定不到PV而导致创建失败。而且通过 PVC 请求到一定的存储空间也很有可能不足以满足应用对于存储设备的各种需求。
而且不同的应用程序对于存储性能的要求可能也不尽相同,比如读写速度、并发性能等,为了解决这一问题,Kubernetes 又为我们引入了一个新的资源对象:StorageClass,通过 StorageClass 的定义,管理员可以将存储资源定义为某种类型的资源,比如快速存储、慢速存储等,用户根据 StorageClass 的描述就可以非常直观的知道各种存储资源的具体特性了,这样就可以根据应用的特性去申请合适的存储资源了。
1.3 运行原理
要使用 StorageClass,我们就得安装对应的自动配置程序,比如我们这里存储后端使用的是 nfs,那么我们就需要使用到一个 nfs-client 的自动配置程序,我们也叫它 Provisioner
(制备器),这个程序使用我们已经配置好的 nfs 服务器,来自动创建持久卷,也就是自动帮我们创建 PV。
- 1. 自动创建的 PV 以
${namespace}-${pvcName}-${pvName}
这样的命名格式创建在 NFS 服务器上的共享数据目录中 - 2. 而当这个 PV 被回收后会以
archieved-${namespace}-${pvcName}-${pvName}
这样的命名格式存在 NFS 服务器上。
2. StorageClass 资源
每个 StorageClass 都包含 provisioner
、parameters
和 reclaimPolicy
字段, 这些字段会在 StorageClass 需要动态分配 PersistentVolume 时会使用到。
StorageClass 对象的命名很重要,用户使用这个命名来请求生成一个特定的类。 当创建 StorageClass 对象时,管理员设置 StorageClass 对象的命名和其他参数,一旦创建了对象就不能再对其更新。
管理员可以为没有申请绑定到特定 StorageClass 的 PVC 指定一个默认的存储类。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: standard
provisioner: kubernetes.io/aws-ebs
parameters:type: gp2
reclaimPolicy: Retain
allowVolumeExpansion: true
mountOptions:- debug
volumeBindingMode: Immediate
2.1 存储制备器
每个 StorageClass 都有一个制备器(Provisioner),用来决定使用哪个卷插件制备 PV。 该字段必须指定。
卷插件 | 内置制备器 | 配置例子 |
---|---|---|
AWSElasticBlockStore | ✓ | AWS EBS |
AzureFile | ✓ | Azure File |
AzureDisk | ✓ | Azure Disk |
CephFS | - | - |
Cinder | ✓ | OpenStack Cinder |
FC | - | - |
FlexVolume | - | - |
Flocker | ✓ | - |
GCEPersistentDisk | ✓ | GCE PD |
Glusterfs | ✓ | Glusterfs |
iSCSI | - | - |
Quobyte | ✓ | Quobyte |
NFS | - | - |
RBD | ✓ | Ceph RBD |
VsphereVolume | ✓ | vSphere |
PortworxVolume | ✓ | Portworx Volume |
ScaleIO | ✓ | ScaleIO |
StorageOS | ✓ | StorageOS |
Local | - | Local |
你不限于指定此处列出的 “内置” 制备器(其名称前缀为 “kubernetes.io” 并打包在 Kubernetes 中)。 你还可以运行和指定外部制备器,这些独立的程序遵循由 Kubernetes 定义的 规范。 外部供应商的作者完全可以自由决定他们的代码保存于何处、打包方式、运行方式、使用的插件(包括 Flex)等。 代码仓库 kubernetes-sigs/sig-storage-lib-external-provisioner 包含一个用于为外部制备器编写功能实现的类库。你可以访问代码仓库 kubernetes-sigs/sig-storage-lib-external-provisioner 了解外部驱动列表。
例如,NFS 没有内部制备器,但可以使用外部制备器。 也有第三方存储供应商提供自己的外部制备器。
后面会演示NFS
2.2 回收策略
由 StorageClass 动态创建的 PersistentVolume 会在类的 reclaimPolicy
字段中指定回收策略,可以是 Delete 或者 Retain。如果 StorageClass 对象被创建时没有指定 reclaimPolicy
,它将默认为 Delete
。
通过 StorageClass 手动创建并管理的 PersistentVolume 会使用它们被创建时指定的回收政策。
2.3 允许卷扩展
PersistentVolume 可以配置为可扩展。将此功能设置为 true
时,允许用户通过编辑相应的 PVC 对象来调整卷大小。
当下层 StorageClass 的 allowVolumeExpansion
字段设置为 true 时,以下类型的卷支持卷扩展。
卷类型 | Kubernetes 版本要求 |
---|---|
gcePersistentDisk | 1.11 |
awsElasticBlockStore | 1.11 |
Cinder | 1.11 |
glusterfs | 1.11 |
rbd | 1.11 |
Azure File | 1.11 |
Azure Disk | 1.11 |
Portworx | 1.11 |
FlexVolume | 1.13 |
CSI | 1.14 (alpha), 1.16 (beta) |
说明: 此功能仅可用于扩容卷,不能用于缩小卷。
2.4 挂载选项
由 StorageClass 动态创建的 PersistentVolume 将使用类中 mountOptions
字段指定的挂载选项。
如果卷插件不支持挂载选项,却指定了该选项,则制备操作会失败。 挂载选项在 StorageClass 和 PV 上都不会做验证,所以如果挂载选项无效,那么这个 PV 就会失败。
2.5 卷绑定模式
volumeBindingMode
字段控制了卷绑定和动态制备 应该发生在什么时候。
默认情况下,Immediate
模式表示一旦创建了 PersistentVolumeClaim 也就完成了卷绑定和动态制备。 对于由于拓扑限制而非集群所有节点可达的存储后端,PersistentVolume 会在不知道 Pod 调度要求的情况下绑定或者制备。
集群管理员可以通过指定 WaitForFirstConsumer
模式来解决此问题。 该模式将延迟 PersistentVolume 的绑定和制备,直到使用该 PersistentVolumeClaim 的 Pod 被创建。 PersistentVolume 会根据 Pod 调度约束指定的拓扑来选择或制备。这些包括但不限于 资源需求、 节点筛选器、 pod 亲和性和互斥性、 以及污点和容忍度。
以下插件支持动态供应的 WaitForFirstConsumer
模式:
- AWSElasticBlockStore
- GCEPersistentDisk
- AzureDisk
以下插件支持预创建绑定 PersistentVolume 的 WaitForFirstConsumer 模式:
- 上述全部
- Local
动态配置和预先创建的 PV 也支持 CSI卷, 但是你需要查看特定 CSI 驱动程序的文档以查看其支持的拓扑键名和例子。
2.6 允许的拓扑结构
当集群操作人员使用了 WaitForFirstConsumer
的卷绑定模式, 在大部分情况下就没有必要将制备限制为特定的拓扑结构。 然而,如果还有需要的话,可以使用 allowedTopologies
。
这个例子描述了如何将供应卷的拓扑限制在特定的区域,在使用时应该根据插件 支持情况替换 zone
和 zones
参数。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: standard
provisioner: kubernetes.io/gce-pd
parameters:type: pd-standard
volumeBindingMode: WaitForFirstConsumer
allowedTopologies:
- matchLabelExpressions:- key: failure-domain.beta.kubernetes.io/zonevalues:- us-central1-a- us-central1-b
3. 实战演示
3.1 部署流程
搭建StorageClass + NFS,大致有以下几个步骤:
1. 创建一个可用的NFS Server
2. 创建Service Account,这是用来管控NFS Provisioner 在k8s集群中运行的权限
NFS provisioner是一个provisioner相关的插件,需要从网络上下载,我们已经下载下来放到镜像库中了
下载以后需要以pod方式运行通过deployment部署导入到本地环境中创建StorageClass的时候需要指定provisioner
3. 创建StorageClass,负责建立PVC并调用NFS provisioner进行预定的工作,并让PV与PVC建立关联
4. 创建NFS provisioner,有两个功能,一个是在NFS共享目录下创建挂载点(volume),另一个则是建了PV并将PV与NFS的挂载点建立关联
3.2 创建Service Account
NFS Server在前面的章节中已经安装过了。
鉴权概述 官方文档
使用 RBAC 鉴权 官方文档
# rbac.yaml:#唯一需要修改的地方只有namespace,根据实际情况定义
apiVersion: v1
kind: ServiceAccount # 创建一个账户,主要用来管理NFS provisioner在k8s集群中运行的权限
metadata:name: nfs-client-provisionernamespace: 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: ServiceAccountname: nfs-client-provisionernamespace: default
roleRef:kind: ClusterRole # 哪个角色name: nfs-client-provisioner-runnerapiGroup: rbac.authorization.k8s.io
---
kind: Role # 创建角色
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: leader-locking-nfs-client-provisioner # 角色名namespace: default # Role需要指定名称空间,ClusterRole 不需要
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: ServiceAccountname: nfs-client-provisionernamespace: default
roleRef: # 绑定哪个角色kind: Rolename: leader-locking-nfs-client-provisionerapiGroup: rbac.authorization.k8s.io
先清空上一节的测试环境:
pvc绑定了pv,直接删除pv删除不掉:
3.3 创建StorageClass,指定provisioner
# 创建NFS资源的StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass # 创建StorageClass
metadata:name: managed-nfs-storage
provisioner: qgg-nfs-storage #这里的名称要和provisioner配置文件中的环境变量PROVISIONER_NAME保持一致
parameters: archiveOnDelete: "false"# 创建NFS provisioner
apiVersion: apps/v1
kind: Deployment # 部署nfs-client-provisioner
metadata:name: nfs-client-provisionerlabels:app: nfs-client-provisionernamespace: default #与RBAC文件中的namespace保持一致
spec:replicas: 1selector:matchLabels:app: nfs-client-provisionerstrategy:type: Recreateselector:matchLabels:app: nfs-client-provisionertemplate:metadata:labels:app: nfs-client-provisionerspec:serviceAccountName: nfs-client-provisioner # 指定serviceAccount!containers:- name: nfs-client-provisionerimage: hub.kaikeba.com/java12/nfs-client-provisioner:v1 #镜像地址volumeMounts: # 挂载数据卷到容器指定目录- name: nfs-client-rootmountPath: /persistentvolumesenv:- name: PROVISIONER_NAME # 配置provisioner的Namevalue: qgg-nfs-storage # 确保该名称与 StorageClass 资源中的provisioner名称保持一致- name: NFS_SERVER #绑定的nfs服务器value: 192.168.66.13- name: NFS_PATH #绑定的nfs服务器目录value: /opt/k8svolumes: # 申明nfs数据卷- name: nfs-client-rootnfs:server: 192.168.66.13path: /opt/k8s
3.4 创建pod测试
创建pod,申明PVC进行测试
# 申明一个PVC,指定StorageClass
kind: PersistentVolumeClaim
apiVersion: v1
metadata:name: test-claimannotations: # 通过annotations注解,和storage-class进行关联,为什么不使用storageClassName,因为版本比较低# 这里指定的名字就是上面创建的StorageClass的名字,让它帮我们创建PVvolume.beta.kubernetes.io/storage-class: "managed-nfs-storage"
spec:accessModes:- ReadWriteManyresources:requests:storage: 1Mi
---
# 创建测试pod,查看是否可以正常挂载
kind: Pod
apiVersion: v1
metadata:name: test-pod
spec:containers:- name: test-podimage: busybox:1.24command:- "/bin/sh"args:- "-c"- "touch /mnt/SUCCESS && exit 0 || exit 1" #创建一个SUCCESS文件后退出volumeMounts:- name: nfs-pvc # 挂载数据卷mountPath: "/mnt"restartPolicy: "Never"volumes:- name: nfs-pvcpersistentVolumeClaim: # 数据卷挂载的是pvcclaimName: test-claim #与PVC名称保持一致
测试是否会帮我自动创建pv:
看到自动创建了一个PV与PVC进行绑定。
清除环境
3.5 集合StatefulSet测试
StatefulSet+volumeClaimTemplates自动创建PV:
# StateFulDet+volumeClaimTemplates自动创建PV
---
apiVersion: v1
kind: Service
metadata:name: nginx-headlesslabels:app: nginx
spec:ports:- port: 80name: webclusterIP: None selector:app: nginx
---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:name: web
spec:serviceName: "nginx"replicas: 2template:metadata:labels:app: nginxspec:containers:- name: nginximage: ikubernetes/myapp:v1ports:- containerPort: 80name: webvolumeMounts:- name: wwwmountPath: /usr/share/nginx/htmlvolumeClaimTemplates: # 通过模板化方式绑定- metadata:name: www # 指定pvc的名字annotations:volume.beta.kubernetes.io/storage-class: "managed-nfs-storage" #只指定了storageClassspec:accessModes: [ "ReadWriteOnce" ]resources:requests:storage: 1Gi
看到是有序依次创建:
看到pvc是自动创建的,pv也是:
K8S 快速入门(十六)实战篇:StorageClass(存储类)相关推荐
- CarSim仿真快速入门(十六)—CarSim传感器仿真之ADAS Sensor Objects (2)
VS命令和计算顺序VS Commands and the Sequence of Calculations 如前所述,运动对象的运动可以使用内置的可配置函数SPEED_TARGET来获得速度,并使用L ...
- 《Autosar从入门到精通-实战篇》总目录_培训教程持续更新中...
目录 一.Autosar入门篇: 1.1 DBC专题(共9篇) 1.2 ARXML专题(共35篇) 1.2.1 CAN Matrix Arxml(共28篇) 1.2.2 ASWC Arxml(共7篇) ...
- python快速入门【六】----真题测试
python入门合集: python快速入门[一]-----基础语法 python快速入门[二]----常见的数据结构 python快速入门[三]-----For 循环.While 循环 python ...
- Systemd 入门教程:实战篇
Systemd 入门教程:实战篇 原文出处: 阮一峰(@ruanyf) http://blog.jobbole.com/98671/?utm_source=blog.jobbole.com& ...
- 教你从0到1搭建秒杀系统-Canal快速入门(番外篇)
Canal用途很广,并且上手非常简单,小伙伴们在平时完成公司的需求时,很有可能会用到.本篇介绍一下数据库中间件Canal的使用. 很多时候为了缩短调用延时,我们会对部分接口数据加入了缓存.一旦这些数据 ...
- 【Golang 快速入门】项目实战:即时通信系统
Golang 快速入门 即时通信系统 - 服务端 版本一:构建基础 Server 版本二:用户上线功能 版本三:用户消息广播机制 版本四:用户业务层封装 版本五:在线用户查询 版本六:修改用户名 版本 ...
- 【FPGA基础快速入门6】实战-----触摸按键控制LED灯的学习
[FPGA基础快速入门6]实战-----触摸按键控制LED灯的学习 触摸按键的种类 触摸按键主要可以分为四大类: 电阻式.电容式.红外感应式以及表面声波式. 1.电阻式触摸按键又多块导电薄膜按照按键的 ...
- 5加载stm32 keil_快速入门STM32单片机-软件篇
关于这个STM32的编程开发环境Keil,网上有太多相关的资源了,而且大都讲解的非常详细.所以本篇文章无意于深入细节,只会提供我学习时候的一些体会,帮助你更好的掌握相关知识. 1.标准外设库(Stan ...
- 带你快速入门AXI4总线--AXI4-Stream篇(1)----AXI4-Stream总线
写在前面 随着对XILINX器件使用的深入,发现越来越多的IP都选配了AXI4的接口.这使得只要学会了AXI4总线的使用,基本上就能对XILINX IP的使用做到简单的上手.所以学会AXI4总线,对X ...
最新文章
- c语言遇到非法字符,98行的四则计算器.(支持括号)加入了非法字符的检测
- pygame (1) 移动小乌龟
- require js define 函数
- java 7zip解压_Apache Commons Compress介绍-JAVA压缩解压7z文件
- 5-简单选择排序C实现(递增递减的简单转换)
- 前端学习(1872)vue之电商管理系统电商系统之完善登录之后的操作
- 服务器漏洞文件被删除漏洞,【华中科技大学 - 漏洞预警】Wordpress = 4.9.6 任意文件删除漏洞...
- three.js加入监控
- [BZOJ2733] [HNOI2012] 永无乡 (splay启发式合并)
- 转 XMLHttpRequest().readyState的五种状态详解
- 浅谈压缩感知(二十七):压缩感知重构算法之稀疏度自适应匹配追踪(SAMP)
- 【android自定义控件】TextView详解及自定义一
- 快逸报表之在IE打印问题
- Web漏洞扫描工具AWVS12使用详解
- 深入理解Instrument
- web前端笔记整理,从入门到上天,周周更新
- android微信分享怎么自定义样式,微信更新!主题皮肤终于支持自定义了,样式超多有个性...
- ctfshow刷题日记sql注入篇
- java路径是什么_什么是java路径?
- SAT OG 写作辅导:良知是一种比金钱名望和权力更有力的激励?
热门文章
- 华为起诉最新进展,国内航司暂停运行有关客机,收买家庭不得继续抚养被解救儿童,脸书创始人后悔没早学微信,这就是今天的大新闻...
- 决策树(Decision Trees)
- kindeditor 上传图片返回带 当前网址的图片地址
- 小米盒子 改装 无线打印服务器,教你给小米盒子换个超级简洁的“猫友桌面”...
- 手绘白板动画视频制作工具VideoScribe 3.11.2 Windows最新横屏竖屏方屏视频号普屏电商六合一汉化中文专业版画布和输出视频无水印支持720p和1080p高清输出
- mysql联合索引的理解
- ajax,HTTP原理 : 网络传输协议,网页从输入url到渲染的流程,函数防抖和节流
- 痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU启动那些事(3)- Serial ISP模式(blhost)
- JUC--005--locks1
- Defina脚本 - 恶灵塔任务大全