基于动态存储卷机制,可为每个应用副本自动创建并挂载一个独立的云盘,适用于数据库、中间件等等对 I/O 和延迟要求较高的场景,同时能够简化存储的生命周期管理。
工作原理
在StatefulSet中使用云盘动态存储卷的流程如下:
定义模板
新建或使用默认 StorageClass,作为动态创建云盘的模板,规定其类型、性能、回收策略等关键参数。在应用中声明存储需求
在StatefulSet中定义
volumeClaimTemplates,并引用 StorageClass,声明Pod待使用的PVC的规格,如存储容量、访问模式等。自动化创建并挂载存储卷
StatefulSet 创建 Pod 时,系统会基于模板自动为其生成一个唯一的 PVC。CSI组件会根据 StorageClass 的规则创建 PV 并与 PVC 绑定,最终将该云盘挂载到 Pod 中。
适用范围
可用区限制:除ESSD同城冗余云盘外,其他云盘类型无法跨可用区挂载,只能挂载到同一可用区下的Pod。
实例规格族限制:部分云盘类型仅支持挂载到特定的实例规格族。
CSI组件限制:已安装csi-plugin组件和csi-provisioner组件。
CSI组件默认安装,请确保未手动卸载。可在页面查看安装情况。建议升级csi-plugin和csi-provisioner至最新版本。
虚拟节点限制:如需在虚拟节点上使用云盘,需遵循集群和kube-scheduler版本要求。
灵骏节点限制:如需在灵骏节点上使用云盘,需满足以下前提条件和配置要求。
步骤一:选择StorageClass
为便于使用,ACK提供多种默认StorageClass。由于StorageClass创建后无法修改,若默认配置不满足需求,可通过手动创建StorageClass新建。
使用默认StorageClass
可从以下默认StorageClass中选择一个,在应用的storageClassName字段中引用其名称即可。
StorageClass名称 | 动态创建的云盘类型 |
| 默认先调度Pod再创建云盘,避免因可用区不匹配导致挂载失败( |
| ESSD云盘,默认为PL1性能级别,云盘容量大小最低为20 GiB。 重要 云盒内的ESSD云盘仅支持PL0级别,需手动创建StorageClass并指定 |
| SSD云盘,云盘容量大小最低为20 GiB。 |
| 高效云盘,云盘容量大小最低为20 GiB。 |
可通过kubectl describe sc <storageclass-name>查看StorageClass详细配置。手动创建StorageClass
kubectl
创建
disk-sc.yaml。示例以使用
volumeBindingMode: WaitForFirstConsumer延迟绑定PV的StorageClass为例。apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: # StorageClass名称 name: alicloud-disk-wait-for-first-consumer # 驱动类型,使用阿里云云盘CSI插件时固定为此值。 provisioner: diskplugin.csi.alibabacloud.com parameters: # 云盘类型,按优先级自适应选择 type: cloud_auto,cloud_essd,cloud_ssd # 文件系统类型 fstype: ext4 diskTags: "a:b,b:c" encrypted: "false" # ESSD云盘的性能级别 performanceLevel: PL1 provisionedIops: "40000" burstingEnabled: "false" # 绑定模式,多可用区场景下建议使用WaitForFirstConsumer volumeBindingMode: WaitForFirstConsumer # 回收策略 reclaimPolicy: Retain # 是否允许存储卷扩容 allowVolumeExpansion: true # 拓扑限制:限制云盘只能在指定的可用区创建 allowedTopologies: - matchLabelExpressions: - key: topology.diskplugin.csi.alibabacloud.com/zone values: # 替换为实际可用区 - cn-hangzhou-i - cn-hangzhou-k主要参数说明如下:
参数
说明
provisioner驱动类型,必填参数。使用阿里云云盘CSI插件时固定为
diskplugin.csi.alibabacloud.com。parameterstype云盘类型,必填参数。可取值:
cloud_essd(默认值):ESSD云盘cloud_auto:ESSD AutoPL云盘cloud_essd_entry:ESSD Entry云盘cloud_ssd:SSD云盘cloud_efficiency:高效云盘elastic_ephemeral_disk_standard:标准版弹性临时盘elastic_ephemeral_disk_premium:高级版弹性临时盘cloud_regional_disk_auto:ESSD同城冗余云盘
支持任意组合,例如
type: cloud_ssd,cloud_essd,cloud_auto。系统将按配置顺序依次尝试创建。最终创建的云盘类型受节点实例、所在可用区云盘支持情况等因素影响。resourceGroupId云盘所属资源组。默认为
""。regionId云盘所在地域,与集群地域相同。
fstype云盘使用的文件系统。可取值:
ext4(默认)、xfs。mkfsOptions云盘格式化参数,如
mkfsOptions: "-O project,quota"。diskTags云盘标签。例如
diskTags: "a:b,b:c",也可使用diskTags/a: b的格式指定。CSI组件需为v1.30.3及以上版本。encrypted云盘是否加密。默认为
false,不加密。performanceLevelESSD云盘性能级别,取值
PL0、PL1(默认)、PL2或PL3。通过云盒使用时需设置为
PL0。volumeExpandAutoSnapshot【废弃】自CSI 1.31.4版本起已废弃。
provisionedIops使用ESSD AutoPL云盘时,配置云盘的预配置性能(IOPS)。
burstingEnabled使用ESSD AutoPL云盘时,是否开启Burst(性能突发)。默认为
false,不开启。multiAttach是否开启云盘多重挂载功能。默认为
false,不开启。volumeBindingMode云盘的绑定模式。可取值:
Immediate(默认):先创建云盘再创建Pod。WaitForFirstConsumer:延迟绑定,即先调度Pod,再根据Pod所在可用区创建云盘。多可用区场景下,建议使用
WaitForFirstConsumer,以优化因云盘和ECS节点不在同一可用区导致的挂载失败。如需调度到虚拟节点,采用特定调度方式或添加了特定Annotation时,不支持使用
WaitForFirstConsumer类型的StorageClass,请参见挂载云盘的Pod调度至虚拟节点时,PVC一直处于Pending状态怎么办?。
reclaimPolicy云盘回收策略。
Delete(默认):删除PVC时,PV和云盘会一起删除。Retain:删除PVC时,PV和云盘数据不会被删除,需手动删除。对数据安全性要求高时,推荐使用
Retain,以免误删数据。
allowVolumeExpansion配置为
true时,允许在线扩容云盘存储卷。allowedTopologies限制云盘只能在特定的拓扑域中创建。
key:拓扑域标签。支持以下取值:topology.diskplugin.csi.alibabacloud.com/zone:阿里云 CSI 插件提供的专用拓扑key。alibabacloud.com/ecs-instance-id:使用弹性临时盘时,支持指定节点。
values:包含可用区或节点 ID 的列表。
创建StorageClass。
kubectl create -f disk-sc.yaml查看StorageClass。
kubectl get sc输出中,StorageClass已创建,处于
WaitForFirstConsumer绑定模式。NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE alicloud-disk-wait-for-first-consumer diskplugin.csi.alibabacloud.com Retain WaitForFirstConsumer true 10s
控制台
在ACK集群列表页面,单击目标集群名称,在集群详情页左侧导航栏,选择。
单击创建,选择存储卷类型为云盘,完成参数配置,然后单击创建。
参数
描述
参数
默认参数:
type。云盘类型,必填参数。可取值:
cloud_essd(默认值):ESSD云盘cloud_auto:ESSD AutoPL云盘cloud_essd_entry:ESSD Entry云盘cloud_ssd:SSD云盘cloud_efficiency:高效云盘elastic_ephemeral_disk_standard:标准版弹性临时盘elastic_ephemeral_disk_premium:高级版弹性临时盘cloud_regional_disk_auto:ESSD同城冗余云盘
支持任意组合,例如
type: cloud_ssd,cloud_essd,cloud_auto。系统将按配置顺序依次尝试创建。最终创建的云盘类型受节点实例、所在可用区云盘支持情况等因素影响。
回收策略
云盘回收策略。
Delete(默认):删除PVC时,PV和云盘会一起删除。Retain:删除PVC时,PV和云盘数据不会被删除,需手动删除。对数据安全性要求高时,推荐使用
Retain,以免误删数据。
绑定模式
云盘的绑定模式。可取值:
Immediate(默认):先创建云盘再创建Pod。WaitForFirstConsumer:延迟绑定,即先调度Pod,再根据Pod所在可用区创建云盘。多可用区场景下,建议使用
WaitForFirstConsumer,以优化因云盘和ECS节点不在同一可用区导致的挂载失败。如需调度到虚拟节点,采用特定调度方式或添加了特定Annotation时,不支持使用
WaitForFirstConsumer类型的StorageClass,请参见挂载云盘的Pod调度至虚拟节点时,PVC一直处于Pending状态怎么办?。
创建完成后,可在存储类页面查看新创建的StorageClass。
步骤二:创建应用并挂载云盘
以StatefulSet为例介绍如何挂载云盘存储卷。
云盘为非共享存储,未开启多重挂载时一次只能挂载一个Pod。在多副本 Deployment 中共享PVC会导致新Pod无法挂载仍被旧Pod占用的云盘而启动失败。推荐使用StatefulSet或单独为Pod挂载云盘。
如仍需在Deployment中使用云盘,建议使用云盘作为临时存储卷。如需启用多重挂载,请参见使用NVMe云盘多重挂载及Reservation。
创建
statefulset.yaml。以下示例创建了包含2个Pod的StatefulSet,使用
volumeClaimTemplates来为每个 Pod 自动创建并绑定独立的持久化存储。apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: serviceName: "nginx" replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: # 建议配置以下securityContext以优化挂载性能 securityContext: fsGroup: 1000 fsGroupChangePolicy: "OnRootMismatch" containers: - name: nginx image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6 ports: - containerPort: 80 volumeMounts: # 将数据卷挂载到容器的/data目录 # name需与volumeClaimTemplates中定义的metadata.name一致 - name: pvc-disk mountPath: /data # 定义PVC模板 volumeClaimTemplates: - metadata: name: pvc-disk spec: # 访问模式 accessModes: [ "ReadWriteOnce" ] # 关联此前创建的StorageClass storageClassName: "alicloud-disk-wait-for-first-consumer" resources: requests: # 申请的存储容量,即云盘大小 storage: 20Gi重要在 Pod 中配置
securityContext.fsgroup会导致kubelet在挂载卷时递归修改文件权限(chmod/chown)。若文件数量庞大,将显著延长挂载时间。对于1.20及以上版本的集群,建议将
fsGroupChangePolicy配置为OnRootMismatch,仅在首次挂载且卷根目录权限不匹配时才执行递归的权限变更,以优化挂载性能。若性能仍不满足要求或需更精细的权限控制,建议使用initContainer在主应用容器启动前自行执行权限调整命令。创建StatefulSet。
kubectl create -f statefulset.yaml确认Pod处于Running状态。
kubectl get pod -l app=nginx查看挂载路径,确认已挂载云盘。
本示例Pod名称为
web-1,请按实际替换。kubectl exec web-1 -- df -h /data预期输出:
Filesystem Size Used Avail Use% Mounted on /dev/vdb 20G 24K 20G 1% /data
步骤三:模拟Pod故障,验证持久化存储
通过“写入数据 -> 删除 Pod -> 检查数据”的流程,来验证存储在云盘上的数据在 Pod 重建后是否仍然存在。
在 Pod 中写入测试数据。
以Pod
web-1为例,在其挂载的云盘路径/data下创建一个test文件。kubectl exec web-1 -- touch /data/test kubectl exec web-1 -- ls /data预期输出:
lost+found test模拟 Pod 故障,删除 Pod。
kubectl delete pod web-1再次执行
kubectl get pod -l app=nginx,可以发现已自动创建一个同名的Podweb-1。验证新 Pod 中的数据。
在新Pod
web-1中再次检查/data目录。kubectl exec web-1 -- ls /data预期输出中,此前创建的 test 文件依然存在,表明即使 Pod 被删除重建,数据也实现了持久化存储。
lost+found test
应用于生产环境
高可用性
云盘选型
需综合评估其性能、计费以及节点的可用区和实例规格族,确保Pod能被调度至兼容的节点。
选择云盘类型时,SSD云盘、高效云盘已逐步停止售卖。建议选用ESSD PL0云盘或ESSD Entry云盘替换高效云盘,选用ESSD AutoPL云盘替换SSD云盘。
构建跨可用区容灾方案
应用层容灾: 对于数据库等关键业务,在多个可用区部署应用实例,并通过应用自身的数据同步机制实现高可用。
存储层容灾:选用支持多可用区容灾的云盘类型,将数据实时同步写入同一地域的不同可用区,实现跨可用区的故障恢复,请参见使用ESSD同城冗余云盘。
数据安全与备份
性能与成本优化
计费说明
常见问题
挂载云盘的Pod调度至虚拟节点时,PVC一直处于Pending状态怎么办?
可能是使用了不支持虚拟节点调度场景的StorageClass。当通过特定标签(Label)或注解(Annotation)将Pod调度到虚拟节点时,不支持使用volumeBindingMode: WaitForFirstConsumer模式的StorageClass。
原因:
WaitForFirstConsumer模式依赖kube-scheduler为Pod选择一个物理节点,从而确定其可用区,然后再根据可用区创建云盘。但虚拟节点的部分调度机制不遵循此流程,导致CSI无法获取可用区信息,继而无法创建PV,PVC便处于Pending状态。如遇问题,请检查Pod或其命名空间中是否包含以下任意一种配置:
Label:
alibabacloud.com/eci: "true":调度至ECI Pod。alibabacloud.com/acs: "true":调度至ACS Pod。
指定节点:
通过
spec.nodeName直接指定一个节点(节点名称前缀为virtual-kubelet)。
Annotation:
k8s.aliyun.com/eci-vswitch:指定ECI Pod的交换机。k8s.aliyun.com/eci-fail-strategy: "fail-fast":ECI Pod的故障处理策略为快速失败。
如何为单个Pod或单副本Deployment挂载云盘存储卷?
对于不需要多副本伸缩和稳定网络标识的简单应用,可手动创建PVC并将其挂载到Pod或Deployment,以实现持久化存储。
链路为:选择StorageClass -> 创建PVC -> 在应用中挂载PVC。
创建PVC,申请存储资源。
kubectl
创建
disk-pvc.yaml。apiVersion: v1 kind: PersistentVolumeClaim metadata: name: disk-pvc spec: # 访问模式 accessModes: - ReadWriteOnce volumeMode: Filesystem resources: requests: # 申请的存储容量,即云盘大小 storage: 20Gi # 关联此前创建的StorageClass storageClassName: alicloud-disk-topology-alltype相关参数说明如下:
参数
说明
accessModes存储卷的访问模式。可取值:
ReadWriteOnce、ReadOnlyMany或ReadWriteMany。具体取决于StorageClass中的multiAttach配置以及PVC中的volumeMode配置。multiAttach表示是否开启云盘多重挂载。默认为false,不开启。multiAttach为false,volumeMode配置为任意值时,访问模式仅支持ReadWriteOnce。multiAttach为true,volumeMode为Filesystem时,访问模式仅支持ReadWriteOnce和ReadOnlyMany。multiAttach为true,volumeMode为Block时,三种访问模式均支持。
重要此场景下,访问模式通常为
ReadWriteOnce(RWO) ,即同一时间只能被一个Pod挂载。因此Deployment副本数不能大于1。如尝试扩容,新Pod会因无法挂载已被占用的云盘而一直处于Pending状态。volumeMode存储卷的模式。可取值:
Filesystem(默认):存储卷会被格式化并挂载为目录。Block:存储卷以未格式化的块设备形式直接提供给 Pod。
storage申请的存储容量大小。不同云盘类型的容量范围不同。请确保
storage取值符合其引用的 StorageClass 所对应的云盘类型的容量限制,以免云盘创建失败。storageClassName待绑定的StorageClass。
创建PVC。
kubectl create -f disk-pvc.yaml查看PVC。
kubectl get pvc输出中,由于StorageClass使用
WaitForFirstConsumer模式,此时PVC处于Pending状态,直到第一个使用它的 Pod 被成功调度。NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE disk-pvc Pending alicloud-disk-wait-for-first-consumer <unset> 14s
控制台
在集群管理页左侧导航栏,选择。
在存储声明页面,单击创建,选择存储声明类型为云盘,按照页面提示完成参数的配置。
参数
描述
分配模式
选择使用存储类动态创建。
已有存储类
默认创建或手动创建的StorageClass。
总量
申请的存储容量大小。不同云盘类型的容量范围不同。请确保
storage取值符合其引用的 StorageClass 所对应的云盘类型的容量限制,以免云盘创建失败。访问模式
仅支持ReadWriteOnce,表示卷只能被一个Pod以读写方式挂载。
创建完成后,可在存储声明页面查看新创建的PVC。
在应用中挂载PVC。
创建
disk-deployment.yaml。部署Deployment。
kubectl create -f disk-deployment.yaml
验证挂载结果。
确认Pod已经成功运行。
kubectl get pods -l app=nginx-single进入Pod内部,检查
/data目录是否已成功挂载云盘。# 获取Pod名称 POD_NAME=$(kubectl get pods -l app=nginx-single -o jsonpath='{.items[0].metadata.name}') # 执行df -h命令 kubectl exec $POD_NAME -- df -h /data输出如下,表明20GiB的云盘已成功挂载。
Filesystem Size Used Avail Use% Mounted on /dev/vdb 20G 24K 20G 1% /data
相关文档
使用云盘存储卷时如遇问题,请参见云盘存储卷FAQ。
云盘多可用区部署的配置优化建议,请参见云盘存储卷的高可用配置建议。
如集群仍在使用废弃的Flexvolume组件,请迁移Flexvolume至CSI。
关于如何创建工作负载,请参见创建有状态工作负载StatefulSet、创建无状态工作负载Deployment。
如果不再使用某块云盘且希望云盘停止计费时,可以释放云盘。释放后,云盘及存储在云盘上的数据会被删除、云盘停止计费。