Mongodb集群

一、分片集群介绍

1.1 集群组件
  • shard :每个分片是整体数据的一部分子集,每个分片都可以部署副本集;
  • mongos:数据库集群请求的入口,所有请求需要经过mongos协调;
  • config servers:配置服务器,存储所有数据库元数据(分片,路由)的配置。从MongoDB 3.4开始,必须将配置服务器部署为副本集;
1.2 集群要求
  • 一般要求生产环境通常为>=2个副本+1个仲裁;
  • 配置仲裁,否则主副本集挂了,从副本集是不会升级为主的;
1.3 集群架构


二、分片集群部署

2.1 Mongodb安装

本文部署为单机多实例分片集群,Mongodb安装请参考

集群配置流程梳理 :

  1. 本次实现3个分片,每个分片都有一个副本集,一个仲裁
  2. 配置config组件,初始化config副本集
  3. 配置分片,配置分片副本集,初始化副本集
  4. 配置mongos路由,加载config副本集
  5. 查看集群状态,测试集群
2.2 创建目录文件
mkdir -p /data/resource/mongodb/mongos/{log,conf}
mkdir -p /data/resource/mongodb/{node1,node2,node3}/{mongoconf,shard1,shard2,shard3}/{data,log,conf}
mkdir -p /data/resource/mongodb/auth
2.3 配置config副本
# config-1
vim /data/resource/mongodb/node1/mongoconf/conf/mongoconf.conf
#
logpath=/data/resource/mongodb/node1/mongoconf/log/mongoconf.log
pidfilepath=/data/resource/mongodb/node1/mongoconf/log/node1.pid
dbpath=/data/resource/mongodb/node1/mongoconf/data
logappend=true
bind_ip=0.0.0.0
port=21010
fork=true
auth=false
maxConns=20000
syncdelay=60
oplogSize=1000
configsvr=true
replSet=replconf
journal=true
journalCommitInterval=200
# config-2
vim /data/resource/mongodb/node2/mongoconf/conf/mongoconf.conf
#
logpath=/data/resource/mongodb/node2/mongoconf/log/mongoconf.log
pidfilepath=/data/resource/mongodb/node2/mongoconf/log/node2.pid
dbpath=/data/resource/mongodb/node2/mongoconf/data
logappend=true
bind_ip=0.0.0.0
port=21020
fork=true
auth=false
maxConns=20000
syncdelay=60
oplogSize=1000
configsvr=true
replSet=replconf
journal=true
journalCommitInterval=200
# config-3
vim /data/resource/mongodb/node3/mongoconf/conf/mongoconf.conf
#
logpath=/data/resource/mongodb/node3/mongoconf/log/mongoconf.log
pidfilepath=/data/resource/mongodb/node3/mongoconf/log/node3.pid
dbpath=/data/resource/mongodb/node3/mongoconf/data
logappend=true
bind_ip=0.0.0.0
port=21030
fork=true
auth=false
maxConns=20000
syncdelay=60
oplogSize=1000
configsvr=true
replSet=replconf
journal=true
journalCommitInterval=200
#启动配置服务
mongod -f /data/resource/mongodb/node1/mongoconf/conf/mongoconf.conf
mongod -f /data/resource/mongodb/node2/mongoconf/conf/mongoconf.conf
mongod -f /data/resource/mongodb/node3/mongoconf/conf/mongoconf.conf
#初始配置副本集,登录任意config进行配置即可,下述_id要和config配置文件中的replSet值一致
mongo --host 127.0.0.1 --port 21010
#
use admin
config = {
    _id:"replconf",
    members:[
        {_id:0,host:"127.0.0.1:21010"},
        {_id:1,host:"127.0.0.1:21020"},
        {_id:2,host:"127.0.0.1:21030"},
    ]
}
rs.initiate(config);
rs.status();
2.4 配置shard1集群
# shard1-node1
vim /data/resource/mongodb/node1/shard1/conf/shard.conf
#
dbpath=/data/resource/mongodb/node1/shard1/data
logpath=/data/resource/mongodb/node1/shard1/log/shard.log
bind_ip=0.0.0.0
port=21011
fork=true
logappend=true
oplogSize=4096
journal=true
shardsvr=true
replSet=shard1
auth=false
# shard1-node2
vim /data/resource/mongodb/node2/shard1/conf/shard.conf
#
dbpath=/data/resource/mongodb/node2/shard1/data
logpath=/data/resource/mongodb/node2/shard1/log/shard.log
bind_ip=0.0.0.0
port=21012
fork=true
logappend=true
oplogSize=4096
journal=true
shardsvr=true
replSet=shard1
auth=false
# shard1-node3
vim /data/resource/mongodb/node3/shard1/conf/shard.conf
#
dbpath=/data/resource/mongodb/node3/shard1/data
logpath=/data/resource/mongodb/node3/shard1/log/shard.log
bind_ip=0.0.0.0
port=21013
fork=true
logappend=true
oplogSize=4096
journal=true
shardsvr=true
replSet=shard1
auth=false
#启动分片1集群
mongod -f /data/resource/mongodb/node1/shard1/conf/shard.conf
mongod -f /data/resource/mongodb/node2/shard1/conf/shard.conf
mongod -f /data/resource/mongodb/node3/shard1/conf/shard.conf
#初始化分片1集群,连接到任意一个分片实例即可,arbiterOnly:true表示为仲裁
mongo --host 127.0.0.1 --port 21011
#
use admin
config = {
    _id:"shard1",
    members:[
        {_id:0,host:"127.0.0.1:21011"},
        {_id:1,host:"127.0.0.1:21012"},
        {_id:2,host:"127.0.0.1:21013",arbiterOnly:true}
    ]
}
rs.initiate(config);
rs.status();
2.5 配置shard2集群
# shard2-node1
vim /data/resource/mongodb/node1/shard2/conf/shard.conf
#
dbpath=/data/resource/mongodb/node1/shard2/data
logpath=/data/resource/mongodb/node1/shard2/log/shard.log
bind_ip=0.0.0.0
port=21021
fork=true
logappend=true
oplogSize=4096
journal=true
shardsvr=true
replSet=shard2
auth=false
# shard2-node2
vim /data/resource/mongodb/node2/shard2/conf/shard.conf
#
dbpath=/data/resource/mongodb/node2/shard2/data
logpath=/data/resource/mongodb/node2/shard2/log/shard.log
bind_ip=0.0.0.0
port=21022
fork=true
logappend=true
oplogSize=4096
journal=true
shardsvr=true
replSet=shard2
auth=false
# shard2-node3
vim /data/resource/mongodb/node3/shard2/conf/shard.conf
#
dbpath=/data/resource/mongodb/node3/shard2/data
logpath=/data/resource/mongodb/node3/shard2/log/shard.log
bind_ip=0.0.0.0
port=21023
fork=true
logappend=true
oplogSize=4096
journal=true
shardsvr=true
replSet=shard2
auth=false
#启动分片2集群
mongod -f /data/resource/mongodb/node1/shard2/conf/shard.conf
mongod -f /data/resource/mongodb/node2/shard2/conf/shard.conf
mongod -f /data/resource/mongodb/node3/shard2/conf/shard.conf
#初始化分片2集群,连接到任意一个分片实例即可,arbiterOnly:true表示为仲裁
mongo --host 127.0.0.1 --port 21021
#
use admin
config = {
    _id:"shard2",
    members:[
        {_id:0,host:"127.0.0.1:21021"},
        {_id:1,host:"127.0.0.1:21022"},
        {_id:2,host:"127.0.0.1:21023",arbiterOnly:true}
    ]
}
rs.initiate(config);
rs.status();
2.6 配置shard3集群
# shard3-node1
vim /data/resource/mongodb/node1/shard3/conf/shard.conf
#
dbpath=/data/resource/mongodb/node1/shard3/data
logpath=/data/resource/mongodb/node1/shard3/log/shard.log
bind_ip=0.0.0.0
port=21031
fork=true
logappend=true
oplogSize=4096
journal=true
shardsvr=true
replSet=shard3
auth=false
# shard3-node2
vim /data/resource/mongodb/node2/shard3/conf/shard.conf
#
dbpath=/data/resource/mongodb/node2/shard3/data
logpath=/data/resource/mongodb/node2/shard3/log/shard.log
bind_ip=0.0.0.0
port=21032
fork=true
logappend=true
oplogSize=4096
journal=true
shardsvr=true
replSet=shard3
auth=false
# shard3-node3
vim /data/resource/mongodb/node3/shard3/conf/shard.conf
#
dbpath=/data/resource/mongodb/node3/shard3/data
logpath=/data/resource/mongodb/node3/shard3/log/shard.log
bind_ip=0.0.0.0
port=21033
fork=true
logappend=true
oplogSize=4096
journal=true
shardsvr=true
replSet=shard3
auth=false
#启动分片3集群
mongod -f /data/resource/mongodb/node1/shard3/conf/shard.conf
mongod -f /data/resource/mongodb/node2/shard3/conf/shard.conf
mongod -f /data/resource/mongodb/node3/shard3/conf/shard.conf
#初始化分片3集群,连接到任意一个分片实例即可,arbiterOnly:true表示为仲裁
mongo --host 127.0.0.1 --port 21031
#
use admin
config = {
    _id:"shard3",
    members:[
        {_id:0,host:"127.0.0.1:21031"},
        {_id:1,host:"127.0.0.1:21032"},
        {_id:2,host:"127.0.0.1:21033",arbiterOnly:true}
    ]
}
rs.initiate(config);
rs.status();
2.6 配置mongos路由
vim /data/resource/mongodb/mongos/conf/mongos.conf
#
logpath=/data/resource/mongodb/mongos/log/mongos.log
bind_ip=0.0.0.0
port=20000
fork=true
logappend=true
maxConns=20000
configdb=replconf/127.0.0.1:21010,127.0.0.1:21020,127.0.0.1:21030 #指定config节点
#
mongos -f /data/resource/mongodb/mongos/conf/mongos.conf
2.7 启动分片功能
#此时未设置分片,需要登录mongos启用分片
mongo 127.0.0.1:20000
#
db.runCommand({addshard:"shard1/127.0.0.1:21011,127.0.0.1:21012,127.0.0.1:21013"})
db.runCommand({addshard:"shard2/127.0.0.1:21021,127.0.0.1:21022,127.0.0.1:21023"})
db.runCommand({addshard:"shard3/127.0.0.1:21031,127.0.0.1:21032,127.0.0.1:21033"})
sh.status()
2.8 集群安全认证
#副本集中的每个mongod实例都使用keyfile的内容作为共享密码,只有具有正确密钥文件的mongod或者mongos实例可以连接到副本集
openssl rand -base64 756 > /data/resource/mongodb/auth/auth.key
chmod 400 /data/resource/mongodb/auth/auth.key

#未启用认证的情况下建议预先创建好一个管理员账号和密码
#注意,如果连接的shard不是PRIMARY则无法创建用户
mongo --host 127.0.0.1 --port 21011
mongo --host 127.0.0.1 --port 21021
mongo --host 127.0.0.1 --port 21031
mongo 127.0.0.1:20000
#
use admin
db.createUser(
    {
        user:"root",
        pwd:"root123",
        roles:[{role:"root",db:"admin"}]
    }
)
show users

#将集群中的所有mongod和mongos全部关闭
pkill mongod
pkill mongos
#修改配置文件参数,除mongos外所有服务都需要添加
auth=true
keyFile=/data/resource/mongodb/auth/auth.key
clusterAuthMode=keyFile

#mongos服务则添加服务参数
keyFile=/data/resource/mongodb/auth/auth.key
clusterAuthMode=keyFile
#重新启动config集群
mongod -f /data/resource/mongodb/node1/mongoconf/conf/mongoconf.conf
mongod -f /data/resource/mongodb/node2/mongoconf/conf/mongoconf.conf
mongod -f /data/resource/mongodb/node3/mongoconf/conf/mongoconf.conf

#重新启动shard1集群
mongod -f /data/resource/mongodb/node1/shard1/conf/shard.conf
mongod -f /data/resource/mongodb/node2/shard1/conf/shard.conf
mongod -f /data/resource/mongodb/node3/shard1/conf/shard.conf

#重新启动shard2集群
mongod -f /data/resource/mongodb/node1/shard2/conf/shard.conf
mongod -f /data/resource/mongodb/node2/shard2/conf/shard.conf
mongod -f /data/resource/mongodb/node3/shard2/conf/shard.conf

#重新启动shard3集群
mongod -f /data/resource/mongodb/node1/shard3/conf/shard.conf
mongod -f /data/resource/mongodb/node2/shard3/conf/shard.conf
mongod -f /data/resource/mongodb/node3/shard3/conf/shard.conf

#重新启动mongos路由
mongos -f /data/resource/mongodb/mongos/conf/mongos.conf
#连接mongos检查集群状态,此时需要认证才能访问到集群
mongo 127.0.0.1:20000
#
use admin
db.auth('root','root123')
show users
sh.status()
2.9 开启数据库分片
#创建一个新数据库
use admin
db.auth('root','root123')
use school
db.createUser({"user":"zhangsan","pwd":"123","roles":[{"role":"dbOwner","db":"school"}]})

#给新库启用分片
use admin
db.runCommand( { enablesharding :"school"});
db.stats();

三、集群安全调优

3.1 配置文件参数
# 修改集群配置文件参数(所有服务)
bind_ip=127.0.0.1,10.0.6.7 #监听地址,不建议0.0.0.0
noscripting=true #禁用服务端执行JavaScript脚本,防止执行恶意脚本消耗系统资源
3.2 文件目录权限
chmod 600 /data/resource/mongodb/auth/auth.key
chown -R mongo:mongo /data/resource/mongodb
chmod -R 660 /data/resource/mongodb