通过存储多可用区部署优化,可以帮您最大限度地减少应用发布中断,确保关键业务系统和应用在各种故障情况下能持续运行。本文介绍存储在多可用区部署时的推荐配置。
背景信息
Kubernetes强大的容器编排能力,使得用户在Kubernetes上构建大规模的有状态应用变得越来越简单。虽然Kubernetes简化了应用分发部署的流程,但是也隐藏了底层的硬件逻辑,用户很难感知具体的硬件逻辑,由此可能会导致如下一些非预期的情况。
在多可用区构成的集群下,需要部署在A可用区,最后发现实际部署在B可用区。
创建云盘(PV/PVC)时,出现错误InvalidDataDiskCatagory.NotSupported。更多信息,请参见动态创建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。
以上这些问题,均会导致应用发布中断受阻,本文推荐一种存储多可用区部署的最佳配置,最大程度的减少上述问题。
推荐配置
使用云盘进行持久化存储,相对于NAS更加稳定,数据传输带宽更好。
集群内包含三个可用区,确保机器和存储资源满足需求。
当集群可用区内的节点均不可用时,可立即弹出节点进行匹配。
使用高可用类型的云盘避免云盘挂载失败。
确保应用可以均匀分配至各个节点(各个可用区)。
节点池推荐配置
每个节点池使用单一可用区,每新增一个可用区,都需要新建节点池。具体操作,请参见创建节点池。
重要创建节点池时,确保每个节点池对应各自不同的可用区,建议使用节点池名称区分不同的可用区。
开启节点池的弹性伸缩功能。具体操作,请参见节点自动伸缩。
多可用区内尽量使用同一类型的ECS资源,或者支持同一种类型块存储的ECS资源。
在节点池上对所有节点池进行污点配置,确保不会有其他非预期应用被调度过来影响当前应用。
配置说明如下:
每个节点池使用单一可用区,同时开启节点池的弹性伸缩功能。
当前可用区没有可用的节点时,系统会自动弹出一个对应可用区的节点供Pod调度,如下图所示。
使用单一类型的ECS资源。
ECS和块存储有对应关系,即使在同一个可用区调度,也可能因为有节点不支持声明的块存储,导致Pod因云盘挂载问题而无法启动。
集群推荐配置
确保集群版本不低于1.20。
确保集群的CSI组件版本不低于1.22。更多信息,请参见csi-provisioner。
使用高可用类型的云盘,存储类StorageClass模板如下:
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:
保证CSI组件优先创建ESSD云盘,如果可用区内ESSD云盘库存不足时,可以创建SSD云盘。不会因云盘库存不足等原因导致应用无法启动。
volumeBindingMode: WaitForFirstConsumer:
Kubernetes提供的一种创建云盘的方式,它可以先让Pod进行调度,等到Pod被调度到某一个特定的节点后,CSI才开始根据StorageClass的配置进行云盘创建,此时,您就可以根据Pod所在节点上的信息来创建云盘。
allowedTopologies:
可以将制作卷的拓扑限制在特定的区域。当StorageClass为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能挂载成功。
相关文档
如果您需要加强云盘存储数据的安全性,请参见云盘存储数据安全最佳实践。
如果您需要实时了解云盘的使用情况,请参见使用csi-plugin组件监控节点侧存储资源。
如果您的云盘大小不满足要求或磁盘已满,请参见扩容云盘数据卷。
如果您还有其他云盘挂载的问题,请参见云盘存储卷FAQ。