使用StatefulSet搭建MongoDB集群

 

1.目的 

为每一个MongoDB实例在共享存储(本例使用GlusterFS)中都申请一片存储空间,以实现一个无单点故障,高可用,可动态发展的MongoDB集群,架构图如下

 

2.前提条件

在创建statuefulSet之前,需要确保在kubenetes集群中管理员已经创建好共享存储,并能够与StorageClass对接,以实现动态存储供应的模式,使用GlusterFS作为共享存储

3.部署StatufulSet

为了完成MongoDB集群的搭建,需要部署以下三个资源对象

1)一个StoragerClass:用于StatefulSet自动为各个应用pod申请pvc

2)一个Headless Service:用于设置MongoDB实例的域名

3)一个StatefulSet

首先创建StorageClass 的配置文件

apiVersion: storage.k8s.io/v1
kind: SrorageClass
metadata:
  name: fast
provisioner: kubenetes.io/glusterfs
parameters:
  resturl:  "http://<heketi-rest-url>"
运行kubectl create命令创建该StorageClass: 
 
接下来,创建对应的Headless Service。mongo-sidecar作为MongoDB集群的管理者,将使用此Headless Service来维护各个MongoDB实例之间
的集群关系,以及集群规模变化时的自动更新。mongo-headless-service.yaml文件的内容如下
apiVersion: v1
kind: Service
metadata:
  name: mongo
  labels:
    name: mongo
spec:
  ports:
  - port: 27017
    targePort: 27017
  clusterIP: None
  selector:
    role: mongo

  运行kubectl create -f  mongo-headless-service.yaml创建Headless Service

最后创建MongoDB ,StatuefulSet,statuefulSet-mongo.yaml文件的内容

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongo
spec:
  serviceName: "mongo"
  replicas: 3
  template:
    metadata:
      labels:
        role: mongo
        environment: test
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: mongo
        image: mongo
        command:
        - mongod
        - "--replset"
        - rs0
        - "--smallfiles"
        - "--noprealloc"
        ports:
        - containerPort: 27017
        volumeMounts:
         -  name: mongo-persistent-storage
             mountpath: /data/db
      - name: mongo-sidecar
         iamge: cvallance/mongo-k8s-sidecar
         env: 
         - name: MONGO_SIDECAR_POD_LABELS
            value: "role=mongo, environment=test"
         - name: KUBERNETES_MONGO_SERVICE_NAME
            value: "mongo"
  volumeClaimTemplates:
  - metadata: 
       name: mongo-persistent-storage
       annotations:
         volume.beta.kubernetes.io/storage-class: "fast"
    spec: 
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 100Gi

  

对其中的主要配置说明如下。
(1)在该StatefulSet的定义中包括两个容器:mongo和mongo-sidecar。mongo是主服务程序,mongo-sidecar是将多个mongo实例进行集群设置的工具。mongo-sidecar中的环境变量如下。
◎ MONGO_SIDECAR_POD_LABELS:设置为mongo容器的标签,用于sidecar查询它所要管理的MongoDB集群实例。
◎ KUBERNETES_MONGO_SERVICE_NAME:它的值为mongo,表示sidecar将使用mongo这个服务名来完成MongoDB集群的设置。
(2)replicas=3表示这个MongoDB集群由3个mongo实例组成。
(3)volumeClaimTemplates是StatefulSet最重要的存储设置。在annotations段设置volume.beta.kubernetes.io/storage-class="fast"表示使用名为fast的StorageClass自动为每个mongo
Pod实例都分配后端存储。resources.requests.storage=100Gi表示为每个mongo实例都分配100GiB的磁盘空间。
使用kubectl create命令创建这个StatefulSet:  最终可以看到StatefulSet依次创建并启动了3个mongo Pod实例,它们的名字依次为mongo-0、mongo-1、mongo-2:
kubectl get pods -l role=mongo
 
StatefulSet会用volumeClaimTemplates中的定义为每个Pod副本都创建一个PVC实例,每个PVC实例的名称都由StatefulSet定义中volumeClaimTemplates的名称和Pod副本的名称组合而成,
查看系统中的PVC便可以验证这一点: kubectl get pvc         
至此,一个由3个实例组成的MongoDB集群就创建完成了,其中的每个实例都拥有稳定的名称(DNS域名格式)和独立的存储空间。

4.查看MongoDB集群的状态

登录任意一个mongo Pod,在mongo命令行界面用rs.status()命令查看MongoDB集群的状态,可以看到mongo集群已通过sidecar完成了创建。在集群中包含3个节点,
每个节点的名称都是StatefulSet设置的DNS域名格式的网络标识名称: 
kubectl  exec -it  mongo-0 -- mongo
对于需要访问这个mongo集群的Kubernetes集群内部的客户端来说,可以通过Headless Service“mongo”获取后端的所有Endpoints列表,
并组合为数据库链接串,例如“mongodb://mongo-0.mongo,mongo-1.mongo,mongo-2.mongo:27017/dbname_?”。

5.StatefulSet的常见应用场景

下面对MongoDB集群常见的两种场景进行操作,说明StatefulSet对有状态应用的自动化管理功能。

5.1MongoDB集群的扩容

假设在系统运行过程中,3个mongo实例不足以满足业务的要求,这时就需要对mongo集群进行扩容,仅需要通过StatefulSet进行scale操作,就能实现在mongo集群中自动添加新的mongo节点

使用kubectl scale命令将StatefulSet设置为4个实例: kubectl scale --replicas=4 statefulet mongo

等待一会儿查看实例: kubectl get po -l role=mongo

进入某个实例查看集群状态,可以看到第四个节点已经加入 kubectl exec -it mongo-0 -- mongo              rs.status()

同时,系统也为mongo-3分配了一个新的PVC用于保存数据,此处不再赘述,有兴趣的读者可自行查看系统为mongo-3绑定的Volume设置和后端GlusterFS共享存储的资源分配情况。

5.2自动故障恢复(MongoDB高可用)

假设在系统运行过程中,某个mongo实例或其所在的主机发生故障, 则statefulset将会自动重建该mongo实例, 并保证其身份(id)和使用的数据(pvc)不变

以mongo-0实例发生故障为例,statefulset将会自动重建mongo-0实例,并为其挂载之前分配的pvc“mongo-persistent-storager-mongo-0”。mongo-0服务在重新启动后,原数据库中的数据不会丢失,可继续使用

kubectl get po -l role=mongo -o yaml

  

 

posted @ 2023-07-12 16:55  小-y  阅读(11)  评论(0)    收藏  举报