一、需求背景
1、现状描述
(1)、针对近期出现的mongodb未授权的安全问题,导致mongodb数据会被非法访问。应安全平台部的要求,需要对所有mongodb进行鉴权设置,目前活动侧总共有4台,用于某XX产品;
(2)、某XX产品用到4台mongodb,属于2015年机房裁撤的范围;
(3)、早期的4台mongodb采用是的M1机型,同时在架构上采取了路由分片的模式。从目前来看,无论是数据量上,还是访问量上,都比较小,在资源上有点浪费,在架构上属于过早设计。
而本次新建的mongodb集群,采用的是副本集模式,且机型选为B6,机器数量为3台。
2、服务器信息
3、架构图
4、系统环境
CentOS 6.3 x86_64
5、软件包地址
http://downloads.mongodb.org/linux/mongodb-linux-x86_64-2.6.7.tgz
二、MongoDB集群部署
1、mongodb基础安装
略过(直接从官方下载二进制包解压到“/usr/local”路径)
# mkdir -p /data/mongodb/data/repair
# mkdir -p /usr/local/mongodb/{etc,run}
# mkdir -p /data/mongodb/logs
2、前期准备工作
(1)、副本集名称设置
# vim /usr/local/mongodb/etc/mongod.conf
初期的配置:
dbpath = /data/mongodb/data
logpath = /data/mongodb/logs/mongod.log
repairpath = /data/mongodb/data/repair
pidfilepath = /usr/local/mongodb/run/mongod.pid
directoryperdb = true
logappend = true
noauth = true
bind_ip = 你的IP
port = 27017
quota = true
quotaFiles = 65535
maxConns = 20000
fork = true
nssize = 16
rest = true
httpinterface = true
journal = true
oplogSize = 2000
cpu = true
replSet = fenglingSet
(2)、启动参数
对于NUMA架构的CPU,需要增加以下启动参数:
# vim /usr/local/mongodb/etc/mongod
…..
numactl --interleave=all
…..
(3)、完整的启动脚本
# vim /usr/local/mongodb/etc/mongod
#!/bin/bash## this script start and stop the mongodb daemon ## chkconfig: - 85 15 # description: mongodb is a document key-value database # processname: mongod # config: /usr/local/mongodb/etc/mongod.conf # pidfile: /usr/local/mongodb/run/mongod.pid # # code by rocketzhang # PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin mongod="/usr/local/mongodb/bin/mongod" prog=mongod OPTIONS="--fork --config /usr/local/mongodb/etc/mongod.conf" RETVAL=0 start() { echo -n $"Starting $prog......" numactl --interleave=all $mongod $OPTIONS RETVAL=$? echo [ $RETVAL -eq 0 ] return $RETVAL } stop() { echo -n $"Stopping $prog......" /sbin/killproc -9 $prog RETVAL=$? echo [ $RETVAL -eq 0 ] return $RETVAL } case "$1" in start) start ;; stop) stop ;; restart) stop sleep 1 start ;; *) echo $"Usage: $prog {start|stop|restart}" exit 1 esac
# ln -s /usr/local/mongodb/etc/mongod /etc/init.d/mongod
# chmod +x /usr/local/mongodb/etc/mongod
(4)、服务启动
# service mongod start
注意:
3台节点服务器皆做同样设置。
3、副本集设置
# /usr/local/mongodb/bin/mongo --host 10.157.23.13 --port 27017
> use admin
> config={ _id:"fenglingSet", members:[{_id:0,host:"10.157.23.13:27017"},{_id:1,host:"10.193.23.11:27017"},{_id:2,host:"10.193.24.171:27017"}]}
> rs.initiate(config);
> rs.status();
4、其他说明
(1)、集群状态信息查看
# /usr/local/mongodb/bin/mongo --host 10.157.23.13 --quiet --eval "printjson(rs.status())"
(2)、设置副本节点可读
mongodb默认是从主节点读写数据的,副本节点上不允许读,需要设置副本节点可以读。
# /usr/local/mongodb/bin/mongo --host 10.193.24.171 --port 27017
> db.getMongo().setSlaveOk();
注意:
重启服务后,需要重新设置。
(3)、节点角色
PRIMARY节点可读可写,SECONDARY节点仅可读。
三、MongoDB授权设置
1、单机模式
(1)、账号添加
# /usr/local/mongodb/bin/mongo --host XXX.XXX.XXX.XXX --port 27017
> use admin
> db.addUser("huodong", "tenmongo$2356")
> db.system.users.find()
(2)、配置修改并重启服务
# vim /usr/local/mongodb/etc/mongod.conf
……
auth = ture
…..
# service mongod restart
(3)、连接测试
# /usr/local/mongodb/bin/mongo XXX.XXX.XXX.XXX:27017/admin -uhuodong -p'tenmongo$2356'
2、集群模式(本次采用)
(1)、keyfile文件创建
# cd /usr/local/mongodb/etc
# openssl rand -base64 513 > keyfile
# chmod 600 keyfile
注意:
需要将keyfile也同步到其他节点服务器上。
(2)、账号添加
# /usr/local/mongodb/bin/mongo --host 10.157.23.13 --port 27017
> use admin
> db.addUser("huodong", "tenmongo$2356")
> db.system.users.find()
(3)、配置修改并重启服务
# vim /usr/local/mongodb/etc/mongod.conf
# service mongod restart
最终的配置:
dbpath = /data/mongodb/data
logpath = /data/mongodb/logs/mongod.log
repairpath = /data/mongodb/data/repair
pidfilepath = /usr/local/mongodb/run/mongod.pid
directoryperdb = true
logappend = true
auth = true
clusterAuthMode = keyFile
keyFile = /usr/local/mongodb/etc/keyfile
bind_ip = 10.157.23.13
port = 27017
quota = true
quotaFiles = 16
maxConns = 20000
fork = true
nssize = 16
rest = true
httpinterface = true
journal = true
oplogSize = 2000
cpu = true
replSet = fenglingSet
注意:
需要在其他节点服务器上,也做同样设置。
(4)、简单测试
# /usr/local/mongodb/bin/mongo 10.157.23.13:27017/admin -uhuodong -p'tenmongo$2356'
# /usr/local/mongodb/bin/mongo --host 10.157.23.13 -uhuodong -p'tenmongo$2356' admin --quiet --eval "printjson(rs.status())"
四、PRIMARY节点自动Failover(业务侧)
1、业务侧服务器分布
2、账号添加(mongodb集群上进行)
# /usr/local/mongodb/bin/mongo 10.157.23.13:27017/admin -uhuodong -p'tenmongo$2356'
> use admin
> db.addUser("check_health", "tenmongo$2356")
3、Failover监控设置
(1)、HAPROXY配置(对应的VIP:10.153.224.44)
# vim /usr/local/haproxy/etc/haproxy.conf
……
listen FENGLING_MONGO_SERVER
bind 0.0.0.0:27017
mode tcp
balance roundrobin
option tcpka
server MONGO_SERVER1 10.157.23.13:27017 maxconn 1500 check inter 2000 rise 2 fall 3 weight 1
server MONGO_SERVER2 10.193.23.11:27017 maxconn 1500 check inter 2000 rise 2 fall 3 weight 1
server MONGO_SERVER3 10.193.24.171:27017 maxconn 1500 check inter 2000 rise 2 fall 3 weight 1
……
# service haproxy reload
(2)、监控脚本
# vim /data/scripts/check_mongo_primary.sh
#!/bin/sh #====================================================================== ## MongoDB副本集PRIMARY角色异常监控告警 ## ## code by rocketzhang #====================================================================== PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin MONGO_BIN_PATH="/usr/local/mongodb/bin/mongo" MONITOR="/usr/local/oms/agent/alarm/BusMonitorAgent" TOKEN="fengling_mongodb" TITLE="MongoDB副本集PRIMARY角色异常监控" SRV_IPADDR="10.153.224.44" SRV_PORT="27017" ## S代表TCP协议,U代表UDP协议 PROT_OPT="S" SCAN_FLAG=0 HOSTS_FILE="/etc/hosts" for ((i=0; i<3; i++)); do RETVAL=`/usr/bin/nmap -n -s${PROT_OPT} -p ${SRV_PORT} ${SRV_IPADDR} | grep open` [[ -n "${RETVAL}" ]] && SCAN_FLAG=1;break || sleep 10 done if [[ ${SCAN_FLAG} -eq 0 ]]; then CONTENT="MongoDB集群存在异常,27017端口不可达!" ${MONITOR} -c 2 -f ${TOKEN} -t "${TITLE}" -i "${CONTENT}" fi CURRENT_MONGO_MASTER=`awk '/fl.mongo.qq.com/{print $1}' /etc/hosts` NEW_MONGO_MASTER=`${MONGO_BIN_PATH} --host ${SRV_IPADDR} -ucheck_health -p'tenmongo$2356' admin --quiet --eval "printjson(rs.status())" | grep -B 3 PRIMARY | awk -F ':' '/name/{print $2}' | sed 's/ "//'` if [[ "${NEW_MONGO_MASTER}" != "${CURRENT_MONGO_MASTER}" ]]; then sed -i '/fl.mongo.qq.com/d' ${HOSTS_FILE} echo "${NEW_MONGO_MASTER} fl.mongo.qq.com" >> ${HOSTS_FILE} /sbin/service nscd restart >/dev/null 2>&1 CONTENT="MongoDB副本集PRIMARY角色已自动切换,请尽快确认!" ${MONITOR} -c 2 -f ${TOKEN} -t "${TITLE}" -i "${CONTENT}" fi
(3)、crontab信息添加
# touch /var/run/check_primary.lock
# echo ' touch /var/run/check_primary.lock' >> /etc/rc.d/rc.local
# crontab -uroot -e
* * * * * (flock --timeout=0 /var/run/check_primary.lock /data/scripts/check_mongo_primary.sh >/dev/null 2>&1)
注意:
业务侧通过fl.mongo.qq.com域名进行mongodb集群访问,当mongodb集群的primary节点发生故障时,会自动选举剩下的其中的一个节点为primary角色,然后业务侧的监控脚本会自动发现最新的primary节点,并刷新本地的hosts配置。整个切换过程对业务侧保持透明,当然当数据与访问量到了一定规模时,我们也不推荐采用此架构模式,此时可以考虑自动路由分片的架构模式。
附录
1、参考资料
http://www.lanceyan.com/tech/mongodb/mongodb_repset1.html
http://www.lanceyan.com/tech/mongodb_repset2.html
http://www.lanceyan.com/tech/arch/mongodb_shard1.html
2、数据迁移
(1)、工具一
http://duoyun.org/topic/5173d275cbce24580a033bd8
http://pan.baidu.com/s/15YsBs 提取密码:levr
(2)、工具二
https://github.com/10gen-labs/mongo-connector
本次的迁移命令:
/usr/local/mongodb/bin/mongosync -h 10.217.121.216:27020 --to 10.157.23.13:27017 --tu huodong --tp 'tenmongo$2356' –oplog