通过存储多可用区部署优化,可以帮您最大程度的减少应用发布中断。本文介绍存储在多可用区部署时的推荐配置。
背景信息
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:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "mysql"
volumeMounts:
- name: disk-csi
mountPath: /var/lib/mysql
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: app
operator: In
values:
- mysql
topologyKey: failure-domain.beta.kubernetes.io/zone
tolerations:
- key: "app"
operator: "Exists"
effect: "NoSchedule"
volumeClaimTemplates:
- metadata:
name: disk-csi
spec:
accessModes: [ "ReadWriteMany" ]
storageClassName: alicloud-disk-topology-alltype
resources:
requests:
storage: 40Gi
部分参数说明如下:
- podAntiAffinity:
尽量让高可用的Pod分布在不同的可用区。
- volumeClaimTemplates:
您可以根据指定Replicas的数量自动创建对应数量的云盘,便于快速扩展。