部署StatefulSet并挂载云盘存储卷时,可能会因为可用区配置、云盘类型等问题导致应用创建失败。本文提供了云盘存储多可用区部署的配置优化建议,帮助您避免因底层配置导致的问题,最大限度地减少应用发布中断。
方案背景
Kubernetes强大的容器编排能力,使得用户在Kubernetes上构建大规模的有状态应用(StatefulSet)变得越来越简单。虽然Kubernetes简化了应用分发部署的流程,但是也隐藏了底层的硬件逻辑,用户很难感知具体的硬件逻辑,这可能会导致一些非预期的情况。
在多可用区构成的集群下,需要应用部署在A可用区,最后发现实际部署在B可用区。
创建云盘存储卷时,出现错误,例如动态创建PV失败且提示InvalidDataDiskCatagory.NotSupported。
挂载应用时,出现错误
The instanceType of the specified instance does not support this disk category
。调度应用时,出现错误
0/x node are available, x nodes had volume node affinity conflict
。
以上这些问题均会导致应用发布中断受阻,本文提供了一些高可用配置建议,可以减少上述问题的发生。
推荐配置
配置目标
对于StatefulSet,推荐使用云盘进行持久化存储。相对于NAS,云盘更加稳定,数据传输带宽更好。
集群内包含多个可用区,确保机器和存储资源满足需求。
当集群可用区内的节点均不可用时,可立即弹出节点进行匹配。
使用高可用的StorageClass,避免云盘挂载失败。
确保应用可以均匀分配至各个节点(各个可用区)。
节点池推荐配置
每个节点池使用单一可用区。
每新增一个可用区,建议新建一个节点池。具体操作,请参见创建和管理节点池。
创建节点池时,确保每个节点池对应各自不同的可用区,建议使用节点池名称区分不同的可用区。
开启节点池的弹性伸缩功能。具体操作,请参见启用节点自动伸缩。
当前可用区没有可用的节点时,系统会自动弹出一个对应可用区的节点供Pod调度,如下图所示。
多可用区内尽量使用同一类型的ECS资源,或者支持同一种类型块存储的ECS资源。
某些类型的云盘不支持挂载到某些规格的ECS实例。即使在同一个可用区调度,也可能因为有节点不支持声明的云盘,导致Pod因云盘挂载问题而无法启动。
在节点池上对所有节点池进行污点配置,确保不会有其他非预期应用被调度过来影响当前应用。
集群推荐配置
确保集群版本不低于1.20。
确保集群的CSI组件版本不低于1.22。更多信息,请参见管理csi-plugin和csi-provisioner组件。
使用高可用的StorageClass。
YAML示例如下:
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: alicloud-disk-topology-alltype parameters: type: cloud_essd,cloud_ssd,cloud_efficiency provisioner: diskplugin.csi.alibabacloud.com reclaimPolicy: Delete volumeBindingMode: WaitForFirstConsumer allowVolumeExpansion: true allowedTopologies: - matchLabelExpressions: - key: topology.diskplugin.csi.alibabacloud.com/zone values: - cn-beijing-a - cn-beijing-b
部分参数说明如下:
type: cloud_essd,cloud_ssd,cloud_efficiency
:结合云盘库存,按照ESSD云盘、SSD云盘、高效云盘的顺序依次尝试创建,避免因云盘库存不足而导致云盘创建失败,进而导致Pod无法启动。volumeBindingMode: WaitForFirstConsumer
:先调度Pod到某一个特定的节点后,再根据StorageClass的配置创建云盘,可以保证云盘和节点处于同一可用区,避免因可用区不一致而导致云盘挂载失败,进而导致Pod无法启动。allowedTopologies
:可以将制作存储卷的拓扑限制在特定的地域可用区。当volumeBindingMode
为WaitForFirstConsumer
时,调度器将根据StorageClass的拓扑结构对Pod进行调度,以满足云盘的创建需求。
应用推荐配置
以下给出了标准StatefulSet应用配置的模板,您可以根据需求自行定义应用配置。
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: "mysql"
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
topologySpreadConstraints:
- labelSelector:
matchLabels:
app: mysql
maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "mysql"
volumeMounts:
- name: disk-csi
mountPath: /var/lib/mysql
tolerations:
- key: "app"
operator: "Exists"
effect: "NoSchedule"
volumeClaimTemplates:
- metadata:
name: disk-csi
spec:
accessModes: [ "ReadWriteMany" ]
storageClassName: alicloud-disk-topology-alltype
resources:
requests:
storage: 40Gi
部分参数说明如下:
topologySpreadConstraints
:尽量让Pod分布在不同的可用区。更多信息,请参见Topology Spread Constraints。volumeClaimTemplates
:可以根据指定的Replicas数量自动创建对应数量的云盘,便于快速扩展。
当PV被动态创建出来,PV对应的YAML中会包含PV所在节点上的可用区信息。此PV以及关联的PVC只能在节点的可用区内进行调度,不会被调度到可用区之外,以此来确保Pod能挂载成功。
相关文档
如果您需要加强云盘存储数据的安全性,请参见云盘存储数据安全最佳实践。
如果您需要实时了解云盘的使用情况,请参见容器存储监控概述。
如果您的云盘大小不满足要求或磁盘已满,请参见扩容云盘存储卷。
如果您还有其他云盘挂载的问题,请参见云盘存储卷FAQ。