目录
一、前言
1、k8s简介
2、MongoDB介绍
3、为什么要使用MongoDB
4、Mongodb高可用方案
二、环境准备
1、k8s集群搭建
2、MongoDB镜像准备
3、NFS存储准备
4、PV准备
5、准备configmap文件
6、创建Service
三、创建MongoDB服务
1、导入镜像
2、初始化mongo集群
3、添加外部访问
一、前言
1、k8s简介
Kubernetes单词起源于希腊语, 是“舵手”或者“领航员、飞行员”的意思。
Kubernetes(简称K8s)的前世今生可以追溯到谷歌(Google)内部的一个项目,它起源于2003年,当时谷歌正面临着不断增长的应用程序和服务的管理挑战。这个项目最初被称为"Borg",是一个早期的容器编排系统。Borg 的成功经验成为 Kubernetes 开发的契机。
有关k8s起源的介绍,请参考《初识K8s之前世今生、架构、组件、前景》这篇文章
Kubernetes的优点包括可移植性、可伸缩性和扩展性。它使用轻型的YAML清单文件实现声明性部署方法,对于应用程序更新,无需重新构建基础结构。管理员可以计划和部署容器,根据需要扩展容器并管理其生命周期。借助Kubernetes的开放源代码API,用户可以通过首选编程语言、操作系统、库和消息传递总线来构建应用程序,还可以将现有持续集成和持续交付(CI/CD)工具集成。
2、MongoDB介绍
MongoDB是一个基于分布式文件存储的数据库,由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富、最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
3、为什么要使用MongoDB
- 灵活的数据模型:MongoDB采用文档型数据存储,文档以JSON格式存储,无需严格的预定义模式,使得数据存储更加灵活,适应数据模型的变化。
- 适用于大规模数据:MongoDB支持水平扩展和垂直扩展,可以处理大规模数据集,并提供高吞吐量和低延迟的查询性能。
- 高性能:MongoDB具有高效的查询引擎和索引机制,支持各种复杂的查询操作,并能够快速地返回结果,满足实时数据处理和分析的需求。
- 高可用性:MongoDB支持副本集和分片集群,提供自动故障转移和自动恢复功能,确保数据的持久性和可靠性,降低了系统的停机时间。
- 丰富的功能:MongoDB提供了丰富的功能和工具,包括复制、分片、索引、聚合框架、地理空间查询等,满足了各种数据管理和分析的需求。
- 易于部署和管理:MongoDB提供了简单易用的管理界面和命令行工具,支持各种部署方式,包括单节点部署、副本集部署和分片集群部署,便于开发人员快速构建和部署应用程序。
- 活跃的社区和生态系统:MongoDB拥有庞大的开发者社区和丰富的生态系统,提供了各种工具、驱动程序和扩展,支持开发人员快速构建和部署应用程序。
4、Mongodb高可用方案
MongoDB的高可用方案主要包括复制集(Replica Set)和分片集群(Sharded Cluster)。
复制集:
复制集是MongoDB实现高可用性的基础方案。它由多个MongoDB实例组成,包括一个主节点(Primary)和多个从节点(Secondary)。主节点负责处理所有的写操作,并将数据变更的操作日志(Oplog)复制给从节点。从节点则复制主节点的数据,并可以处理读操作。当主节点发生故障时,从节点会通过选举产生新的主节点,确保服务的连续性。这种架构可以提供一定程度的数据冗余,防止数据丢失。但需要注意的是,复制集最多只能容忍一个节点的故障,当多个节点同时发生故障时,系统将无法正常运行。
分片集群:
分片集群是通过将数据划分为多个分片(Shard)存储在多台服务器上来实现高可用的方案。每个分片可以是一个独立的MongoDB副本集,包含主节点和从节点。应用程序通过路由器(Router)连接到分片集群,并根据分片键将数据路由到相应的分片。这种架构可以实现水平扩展,提高系统的吞吐量和存储能力。
二、环境准备
1、k8s集群搭建
这里我们使用的 k8s 集群的版本是 v1.23.1,如果还未搭建k8s集群,可以参考《在Centos中搭建 K8s 1.23 集群超详细讲解》这篇文章
2、MongoDB镜像准备
准备部署MongoDB所需的docker镜像,离线的镜像包我已经传到资源列表《mongo:4.2的docker镜像离线包》中了,大家可以自行下载,下载完成后,使用 docker load -i mongo.tar.gz 命令导入到work节点即可
3、NFS存储准备
后端存储我们使用网络存储NFS,这样,即使Pod漂移或被误删除,数据依然还在,不会丢失,NFS Server 的搭建请参考《搭建NFS服务器,部署k8s集群,并在k8s中使用NFS作为持久化储存》这篇文章
安装完成后,在NFS服务器上,创建3个数据目录,供Mongo集群使用
[root@nfs data]# mkdir /data/mongo-1 -p && mkdir /data/mongo-2 -p && mkdir /data/mongo-3 -p
[root@nfs data]# mkdir /data/mongo-1/data -p && mkdir /data/mongo-2/data -p && mkdir /data/mongo-3/data -p
[root@nfs data]# mkdir /data/mongo-1/key -p && mkdir /data/mongo-2/key -p && mkdir /data/mongo-3/key -p
添加权限
[root@nfs data]# vim /etc/exports
#添加如下内容
/data/ *(rw,sync,no_root_squash)
[root@nfs data]# exportfs -arv
exporting *:/data
4、PV准备
上面在NFS服务器上创建了3个数据目录,用于存储mongo的数据,接下来创建3个PV。调用上面的NFS存储
在k8s Master节点上编辑创建PV的YAML文件
[root@master1 mongo]# vim pv.yaml
# 添加以下内容
apiVersion: v1
kind: PersistentVolume
metadata:
name: mongo-pv-1
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 5Gi
nfs:
path: /data/mongo-1
readOnly: false
server: 192.168.40.179
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: mongo-pv-2
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 5Gi
nfs:
path: /data/mongo-2
readOnly: false
server: 192.168.40.179
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: mongo-pv-3
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 5Gi
nfs:
path: /data/mongo-3
readOnly: false
server: 192.168.40.179
[root@master1 mongo]# kubectl apply -f pv.yaml
persistentvolume/mongo-pv-1 created
persistentvolume/mongo-pv-2 created
persistentvolume/mongo-pv-3 created
5、准备configmap文件
[root@master1 mongo]# vim config.yaml
# 添加如下内容
apiVersion: v1
data:
mongod.conf: |-
dbpath=/mongo/data
#logpath=/mongo/log/mongodb.log
pidfilepath=/mongo/key/master.pid
directoryperdb=true
logappend=true
bind_ip=0.0.0.0
port=27017
kind: ConfigMap
metadata:
name: mongodb-conf
namespace: mongo
[root@master1 mongo]# kubectl apply -f config.yaml
6、创建Service
在k8s Master节点上编写创建Service所需的YAML文件
[root@master1 mongo]# vim service.yaml
#输入以下内容
apiVersion: v1
kind: Service
metadata:
namespace: mongo
name: mongo-1 #需要与podname同名
labels:
name: mongo
spec:
ports:
- name: mongo-port
port: 27017
clusterIP: None
selector:
name: mongo-1
---
apiVersion: v1
kind: Service
metadata:
namespace: mongo
name: mongo-2 #需要与podname同名
labels:
name: mongo
spec:
ports:
- name: mongo-port
port: 27017
clusterIP: None
selector:
name: mongo-2
---
apiVersion: v1
kind: Service
metadata:
namespace: mongo
name: mongo-3 #需要与podname同名
labels:
name: mongo
spec:
ports:
- name: mongo-port
port: 27017
clusterIP: None
selector:
name: mongo-3
[root@master1 mongo]# kubectl apply -f service.yaml
三、创建MongoDB服务
1、导入镜像
在k8s 各work节点上,导入mongo的镜像
[root@node1 ~]# docker load -i mongo.tar.gz
2、编辑创建mongo的YAML文件
[root@master1 mongo]# vim mongo-sts.yaml
#添加如下内容
apiVersion: apps/v1
kind: StatefulSet
metadata:
namespace: mongo
name: mongo-1
spec:
selector:
matchLabels:
name: mongo-1
serviceName: "mongo-1"
replicas: 1
podManagementPolicy: Parallel
template:
metadata:
labels:
name: mongo-1
app: mongo-cluster
spec:
containers:
- name: mongo
image: mongo:4.2
imagePullPolicy: IfNotPresent
command:
- mongod
- "-f"
- "/etc/mongod.conf"
- "--bind_ip_all"
- "--replSet"
- rs0
ports:
- containerPort: 27017
volumeMounts:
- name: mongo-cnf-volume
mountPath: /etc/mongod.conf/
subPath: mongod.conf
- name: mongo-dir
mountPath: /mongo
volumes:
- name: mongo-cnf-volume #映射configMap信息
configMap:
name: mongodb-conf
items:
- key: mongod.conf
path: mongod.conf
volumeClaimTemplates:
- metadata:
name: mongo-dir
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 5Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
namespace: mongo
name: mongo-2
spec:
selector:
matchLabels:
name: mongo-2
serviceName: "mongo-2"
replicas: 1
podManagementPolicy: Parallel
template:
metadata:
labels:
name: mongo-2
app: mongo-cluster
spec:
containers:
- name: mongo
image: mongo:4.2
imagePullPolicy: IfNotPresent
command:
- mongod
- "-f"
- "/etc/mongod.conf"
- "--bind_ip_all"
- "--replSet"
- rs0
ports:
- containerPort: 27017
volumeMounts:
- name: mongo-cnf-volume
mountPath: /etc/mongod.conf/
subPath: mongod.conf
- name: mongo-dir
mountPath: /mongo
volumes:
- name: mongo-cnf-volume #映射configMap信息
configMap:
name: mongodb-conf
items:
- key: mongod.conf
path: mongod.conf
volumeClaimTemplates:
- metadata:
name: mongo-dir
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 5Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
namespace: mongo
name: mongo-3
spec:
selector:
matchLabels:
name: mongo-3
serviceName: "mongo-3"
replicas: 1
podManagementPolicy: Parallel
template:
metadata:
labels:
name: mongo-3
app: mongo-cluster
spec:
containers:
- name: mongo
image: mongo:4.2
imagePullPolicy: IfNotPresent
command:
- mongod
- "-f"
- "/etc/mongod.conf"
- "--bind_ip_all"
- "--replSet"
- rs0
ports:
- containerPort: 27017
volumeMounts:
- name: mongo-cnf-volume
mountPath: /etc/mongod.conf/
subPath: mongod.conf
- name: mongo-dir
mountPath: /mongo
volumes:
- name: mongo-cnf-volume #映射configMap信息
configMap:
name: mongodb-conf
items:
- key: mongod.conf
path: mongod.conf
volumeClaimTemplates:
- metadata:
name: mongo-dir
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 5Gi
[root@master1 mongo]# kubectl apply -f mongo-sts.yaml
[root@master ~]# kubectl exec -it mongo-1-0 -n mongo -- /bin/bash
2、初始化mongo集群
进入到第一个pod中
[root@master ~]# kubectl exec -it mongo-1-0 -n mongo -- /bin/bash
root@mongo-1-0:/# mongo
初始化集群
rs.initiate({ _id:"rs0", // replSet指定的名称
members:[{ _id:0, host:"mongo-1.mongo.svc.cluster.local:27017" // 主节点ip与端口,
}]
})
将mongo-2和mongo-3加入到集群
rs0:PRIMARY> rs.add("mongo-2.mongo.svc.cluster.local:27017")
rs0:PRIMARY> rs.add("mongo-3.mongo.svc.cluster.local:27017")
3、添加外部访问
[root@master mongo]# vim nodeport.yaml
#添加如下内容
#master nodeport service
apiVersion: v1
kind: Service
metadata:
name: mongo-1-front-service
labels:
name: mongo-1
namespace: mongo
spec:
selector:
name: mongo-1
type: NodePort
externalTrafficPolicy: Cluster
ports:
- name: mongo-http
nodePort: 30882
port: 27017
protocol: TCP
targetPort: 27017
---
#slave nodeport service
apiVersion: v1
kind: Service
metadata:
name: mongo-2-front-service
labels:
name: mongo-2
namespace: mongo
spec:
selector:
name: mongo-2
type: NodePort
externalTrafficPolicy: Cluster
ports:
- name: mongo-http
nodePort: 30883
port: 27017
protocol: TCP
targetPort: 27017
---
#slave nodeport service
apiVersion: v1
kind: Service
metadata:
name: mongo-3-front-service
labels:
name: mongo-3
namespace: mongo
spec:
selector:
name: mongo-3
type: NodePort
externalTrafficPolicy: Cluster
ports:
- name: mongo-http
nodePort: 30883
port: 27017
protocol: TCP
targetPort: 27017
[root@master mongo]# kubectl apply -f nodeport.yaml
至此,mongo集群部署完成,通过nodeport即可外部访问使用