如何在AWS EKS中调度MongoDB副本至不同可用区并与PV同区
问题背景
我有一个AWS EKS集群(版本v1.26.11-eks-8cb36c9),已使用v0.9.0版本的MongoDB Operator部署MongoDB副本集(镜像为quay.io/mongodb/mongodb-community-server:7.0.0-ubi8),部署文件及执行命令如下:
部署文件
apiVersion: mongodbcommunity.mongodb.com/v1 kind: MongoDBCommunity metadata: name: mongodb-test namespace: mongodb-test spec: members: 3 type: ReplicaSet version: "7.0.0" security: authentication: modes: ["SCRAM"] users: - name: mongouser db: admin passwordSecretRef: # a reference to the secret that will be used to generate the user's password name: password roles: - name: clusterAdmin db: admin - name: userAdminAnyDatabase db: admin scramCredentialsSecretName: mongodb-scram statefulSet: spec: template: spec: nodeSelector: server: mongo # resources can be specified by applying an override # per container name. containers: - name: mongod resources: limits: cpu: "0.3" memory: 700M requests: cpu: "0.2" memory: 500M - name: mongodb-agent resources: limits: cpu: "0.2" memory: 500M requests: cpu: "0.1" memory: 250M volumeClaimTemplates: - metadata: name: data-volume spec: resources: storageClassName: sc1 requests: storage: 10Gi - metadata: name: logs-volume spec: storageClassName: sc1 resources: requests: storage: 2Gi
部署命令
kubectl apply -f mongodb-kubernetes-operator/crd/mongodbcommunity.mongodb.com_mongodbcommunity.yaml kubectl get crd/mongodbcommunity.mongodbcommunity.mongodb.com kubectl apply -k mongodb-kubernetes-operator/rbac/ --namespace mongodb-test kubectl create -f mongodb-kubernetes-operator/manager/manager.yaml --namespace mongodb-test kubectl apply -f replicaset/rbac -n mongodb-test kubectl apply -f replicaset/replica-set.yaml -n mongodb-test
需求咨询
需要实现以下两个需求:
- 将MongoDB副本调度至不同可用区;
- 确保副本与其对应的持久化卷(Persistent Volume)处于同一可用区,示例:replica1及对应PV在eu-west-1a,replica2及对应PV在eu-west-1b,replica3及对应PV在eu-west-1c。
解决方案
这两个需求完全可以实现,具体配置如下:
1. 调度副本到不同可用区
MongoDB Operator基于StatefulSet部署副本集,可通过Pod拓扑分布约束结合节点的可用区标签实现跨AZ调度:
在原部署文件的spec.statefulSet.spec.template.spec下添加拓扑分布约束:
topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: app: mongodb-test # 需匹配你的MongoDB实例标签,可通过`kubectl get pods -n mongodb-test --show-labels`查看实际标签
该配置会强制每个可用区最多运行1个MongoDB副本,确保副本分布在不同AZ。AWS EKS默认会给节点添加topology.kubernetes.io/zone标签,值为节点所在AZ(如eu-west-1a)。
2. 确保副本与PV同AZ
需从存储类和卷声明模板两方面配置:
存储类(StorageClass)配置
确保你的存储类sc1开启WaitForFirstConsumer绑定模式,并限制PV可创建的AZ范围:
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: sc1 provisioner: ebs.csi.aws.com # 使用AWS EBS CSI驱动 volumeBindingMode: WaitForFirstConsumer # 关键:等待Pod调度后再创建PV,确保PV与Pod同AZ allowedTopologies: - matchLabelExpressions: - key: topology.kubernetes.io/zone values: - eu-west-1a - eu-west-1b - eu-west-1c parameters: type: gp3 # 根据需求选择存储类型,如gp2、io1等
卷声明模板无需额外修改
原部署文件中的volumeClaimTemplates保持不变即可,开启WaitForFirstConsumer后,Kubernetes会自动根据Pod调度的AZ创建对应区域的EBS卷,确保PV与Pod在同一AZ。
最终调整后的部署文件片段
整合拓扑分布约束后的spec.statefulSet部分:
spec: statefulSet: spec: template: spec: nodeSelector: server: mongo topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: app: mongodb-test # 替换为你的MongoDB实例实际标签 # 容器资源配置保持不变
内容的提问来源于stack exchange,提问作者Sebinn Sebastian
相关产品推荐
相关产品推荐

