Docker部署一个MongoDB集群

本文介绍在docker环境下安装mongodb的副本集 的集群方式, 后续还会进行java编程访问副本集, 以及如何管理这个集群的实验, 具体链接参考文档最后的链接

MongoDB简介

MongoDB是一个基于分布式文件存储的数据库,它是一个介于关系数据库和非关系数据库之间的产品,其主要目标是在键/值存储方式(提供了高性能和高度伸缩性)和传统的RDBMS系统(具有丰富的功能)之间架起一座桥梁,它集两者的优势于一身。

MongoDB支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型,也因为他的存储格式也使得它所存储的数据在Nodejs程序应用中使用非常流畅。

既然称为NoSQL数据库,Mongo的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

但是,MongoDB也不是万能的,同MySQL等关系型数据库相比,它们在针对不同的数据类型和事务要求上都存在自己独特的优势。在数据存储的选择中,坚持多样化原则,选择更好更经济的方式,而不是自上而下的统一化。

较常见的,我们可以直接用MongoDB来存储键值对类型的数据,如:验证码、Session等;由于MongoDB的横向扩展能力,也可以用来存储数据规模会在未来变的非常巨大的数据,如:日志、评论等;由于MongoDB存储数据的弱类型,也可以用来存储一些多变json数据,如:与外系统交互时经常变化的JSON报文。而对于一些对数据有复杂的高事务性要求的操作,如:账户交易等就不适合使用MongoDB来存储。

什么是docker

Docker是一个轻量级的虚拟机更容易理解。另外一种解释是:Docker就是操作系统中的chroot。如果你不知道chroot是什么的话,后一种解释可能无法帮助你理解什么是Docker。

chroot是一种操作,能改变当前运行的进程和子进程的根目录。 程序运行在这样的一个被修改的环境中,它不能访问这个环境目录树之外的文件和命令,这个被修改的环境就是“chroot牢笼”。

— Arch Linux 的 wiki 中对 chroot 的解释

具体的docker相关事项参考:  Docker入门指南    和      win7下DOCKER详细安装教程    

mongodb集群

mongodb支持很多中的集群方式, 本文主要是 集群复制的一种方式, 另外一个非常有用的就是分片也就是分区, 我们后面会研究。

集群复制

主从复制虽然可以承受一定的负载压力,但这种方式仍然是一个单点,如果主库挂了,数据写入就成了风险。如果,当主库挂掉的时候,可以在访问ip不变的前提下,自动将从库作为主库使用,是不是就能避免这种风险?貌似这又涉及到Linux上的服务KeepAlive等等。

在Mongodb中,提供了一种优于主从模式的集群复制(ReplicateSet)。最理想的模式是,节点之间不分特定的主从。任何一个节点都可以是主节点primary,而其他节点都是secondary,甚至可以通过投票方式选出主节点。

一般的集群复制,可以是如下这个结构:

 

开始在docker下的mongodb的集群安装

本文参考http://dockone.io/article/181

本文介绍如何使用Docker部署一个MongoDB集群,具体如下:

2.6.5版本的MongoDB
有3个节点的副本集(Replica set)
身份验证
持久化数据到本地文件系统

1. 准备环境

这里的3台服务器采用3个vmware虚拟机进行,操作系统采用centos进行,

关于vmare和centos已经docker安装等参考:    虚拟机vmware新手使用教程       VMware下安装linux详细图解教程
docker的安装, 前面已经有了, 或者到baidu去搜索吧

采用xshell或者其他ssh工具 登录三台准备好的centos系统中, 依次在三台机器上执行下面命令

export node1=192.168.128.189   && export node2=192.168.128.133 && export node3=192.168.128.132
请注意上面的ip地址是我本地的ip地址, 您操作时请替换合适的ip地址

然后采用下面的命令检查是否 设置生效了  env | grep node

如下图:

docker中安装mongodb集群时配置环境变量
docker中安装mongodb集群时配置环境变量

 2. 创建证书及准备mongodb镜像

为每个节点创建密钥文件。在其中某一台服务器上面执行如下的命令,然后把密钥文件复制到其余两个服务器的同样的位置。

在这个教程中,我将把所有的东西都放在“/export/data/mongodb/conf”文件夹中。执行下面的命令

mkdir -p  /export/data/mongodb/conf   &&  cd /export/data/mongodb/conf && \
openssl rand -base64 741 > mongodb-keyfile && \
chmod 600 mongodb-keyfile  && \
sudo chown 999 mongodb-keyfile

结果如下:

docker方式中安装mongodb集群的证书配置过程
docker方式中安装mongodb集群的证书配置过程

这个密钥文件的所有者被设置成id为“999”的用户了,因为在MongoDB的Docker容器中,这个用户需要有操作密钥文件的权限

特别注意, 不要在三台机器上都执行, 仅仅在一台机器上执行, 然后复制到另外两台的相同目录中就好!!

然后运行下面命令:

docker run --name mongo \
-v /export/data/mongodb/data:/data/db \
-v /export/data/mongodb/conf:/opt/keyfile \
--hostname="node1.iigrowing.cn" \
-p 27017:27017 \
-d mongo:2.6.5 --smallfiles

由于第一次启动因此, 需要点时间进行下载

现在创建一个admin用户。我们可以连接到刚刚启动的mongoDB容器,并进入一个交互式的shell环境.

docker exec -it mongo /bin/bash
这时候,我们就进到MongoDB的Docker容器里面了,然后我们要打开一个mongo shell环境:

运行:  mongo 命令
上面的命令可以打开mongo shell环境。执行后你会看到这样的输出:

MongoDB shell version: 2.6.5
connecting to: test
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see

http://docs.mongodb.org/

Questions? Try the support group

http://groups.google.com/group/mongodb-user

>
切换到admin用户:
> use admin
switched to db admin

创建一个新的site admin 用户
> db.createUser( {
user: "siteUserAdmin",
pwd: "password",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
});

创建成功的话你会看到如下的成功信息:
Successfully added user: {
"user" : "siteUserAdmin",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]

}

创建一个root用户:

> db.createUser( {
user: "siteRootAdmin",
pwd: "password",
roles: [ { role: "root", db: "admin" } ]
});

你会看到如下的成功信息:
Successfully added user: {
"user" : "siteRootAdmin",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]

}

我们已经创建好了我们以后要使用的几个用户,现在我们不会退出交互式shell环境(mongo和Docker容器的环境)。
> exit
bye
root@node1:/# exit

停止第一个MongoDB实例:
root@node1:/# docker stop mongo

 2. 使用证书文件启动容器

删除前面使用过的docker容器,否则后面会重名冲突  docker rm mongo 这个命令进行删除操作

在执行前, 确保虚拟机和容器时间设置都是正确的, 需要做以下操作

先在虚拟机中运行 ntpdate us.pool.ntp.org 命令, 同步本地时间, 三台机器都要进行

然后采用 date -R  查看三台机器的时间是否都是正确的

另外在3台机器上分别执行 cd /export/data/mongodb/conf && chmod 600 mongodb-keyfile 命令

还得在3台机器上分别执行 chown 999 -R /export/data/mongodb/ 命令

运行下面的命令

docker run \
--name mongo \
-v /export/data/mongodb/data:/data/db \
-v /export/data/mongodb/conf:/opt/keyfile \
--hostname="node1.iigrowing.cn" \
--add-host node1.iigrowing.cn:${node1} \
--add-host node2.iigrowing.cn:${node2} \
--add-host node3.iigrowing.cn:${node3} \
-p 27017:27017 -d mongo:2.6.5 \
--smallfiles \
--keyFile /opt/keyfile/mongodb-keyfile \
--replSet "rs0" && docker logs -f mongo

注意:

--keyFile的路径是/opt/keyfile/mongodb-keyfile,这是正确的。这是密钥文件在Docker内部的地址,我们用-v选项将密钥文
件映射到容器内部的那个路径上(即:/opt/keyfile/mongodb-keyfile)。
--add-host把这些信息添加到Docker容器的/etc/hosts文件中,所以我们可以使用域名而不是IP地址了。在实际的生产环境中
这些信息都是DNS,这些参数都可以忽略。

 

连接到副本集上并且安装配置好它。这还是在node1上面进行的。我们要开启另外一个新的交互式shell环境进入mongo容器

,同时开启一个mongo shell环境:

root@node1:/# docker exec -it mongo /bin/bash
root@node1:/# mongo
MongoDB shell version: 2.6.5
>

因为我们已经设置了一个密码,所以这次我们不得不做身份验证。我们把密码设置为:password。

> db.auth("siteRootAdmin", "password");
1
现在我们可以开启副本集:

> rs.initiate()
{
"info2" : "no configuration explicitly specified -- making one",
"me" : "node1.example.com:27017",
"info" : "Config now saved locally.  Should come online in about a minute.",
"ok" : 1
}
>

验证已经初始化的副本集的配置:

>
rs0:PRIMARY> rs.conf()
{
"_id" : "rs0",
"version" : 1,r
"members" : [
{
"_id" : 0,
"host" : "node1.example.com:27017"
}
]

}

 

在其余的两个节点启动MongoDB。

在node2上面执行命令:
docker run \
--name mongo \
-v /export/data/mongodb/data:/data/db \
-v /export/data/mongodb/conf:/opt/keyfile \
--hostname="node2.iigrowing.cn" \
--add-host node1.iigrowing.cn:${node1} \
--add-host node2.iigrowing.cn:${node2} \
--add-host node3.iigrowing.cn:${node3} \
-p 27017:27017 -d mongo:2.6.5 \
--smallfiles \
--keyFile /opt/keyfile/mongodb-keyfile \
--replSet "rs0" && docker logs -f mongo

在node3上面执行命令:
docker run \
--name mongo \
-v /export/data/mongodb/data:/data/db \
-v /export/data/mongodb/conf:/opt/keyfile \
--hostname="node3.iigrowing.cn" \
--add-host node1.iigrowing.cn:${node1} \
--add-host node2.iigrowing.cn:${node2} \
--add-host node3.iigrowing.cn:${node3} \
-p 27017:27017 -d mongo:2.6.5 \
--smallfiles \
--keyFile /opt/keyfile/mongodb-keyfile \
--replSet "rs0" && docker logs -f mongo

请特别注意上面 命令在三台机器上是不同, 主要是主机名称不同

 

将那两个节点加到副本集上。

回到node1节点,如果你在这里按了几次回车键(enter)的话,你会看到下面的提示:“rs0:PRIMARY”。这是因为这个节点是副本

集“rso”的主节点。

注意要 分别在3台机器上 打开防火墙的限制, 如下firewall-cmd --permanent --add-port=27017/tcp
rs0:PRIMARY> rs.add("node2.iigrowing.cn")
rs0:PRIMARY> rs.add("node3.iigrowing.cn")

 

我们可以通过执行下面的命令来验证其它两个节点是否正确的加到这个副本集当中:

rs0:PRIMARY> rs.status()

输出如下:

{
"set" : "rs0",
"date" : ISODate("2017-06-27T11:04:14Z"),
"myState" : 1,
"members" : [
{
"_id" : 0,
"name" : "node1.iigrowing.cn:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1146,
"optime" : Timestamp(1498561432, 1),
"optimeDate" : ISODate("2017-06-27T11:03:52Z"),
"electionTime" : Timestamp(1498560531, 1),
"electionDate" : ISODate("2017-06-27T10:48:51Z"),
"self" : true
},
{
"_id" : 1,
"name" : "node2.iigrowing.cn:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 74,
"optime" : Timestamp(1498561432, 1),
"optimeDate" : ISODate("2017-06-27T11:03:52Z"),
"lastHeartbeat" : ISODate("2017-06-27T11:04:12Z"),
"lastHeartbeatRecv" : ISODate("2017-06-27T11:04:13Z"),
"pingMs" : 1,
"syncingTo" : "node1.iigrowing.cn:27017"
},
{
"_id" : 2,
"name" : "node3.iigrowing.cn:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 22,
"optime" : Timestamp(1498561432, 1),
"optimeDate" : ISODate("2017-06-27T11:03:52Z"),
"lastHeartbeat" : ISODate("2017-06-27T11:04:12Z"),
"lastHeartbeatRecv" : ISODate("2017-06-27T11:04:12Z"),
"pingMs" : 1,
"syncingTo" : "node1.iigrowing.cn:27017"
}
],
"ok" : 1
}

 

可能会花几分钟的时间来将node1上面的数据同步到其余的两个节点上面。你可以通过查看日志来观察每一个MongoDB的Docker容器

里面发生了什么。在任意一个服务器上面执行下面的命令就可以了:
结论
现在你拥有了一个MongoDB集群。你可以自由的在任何时刻添加节点到这个集群上。你甚至可以关闭其中的一个节点,包括主节点,

然后观察一个另外一个节点重新变成了主节点。由于这些数据都被写在了你的本机文件系统当中了,所以重启任何一个节点都不是什么大问题。

mongodb是个很好的程序, 参照原文搭建了一个采用docker的集群, 相对比较简单, 但是具体的 mongodb集群的具体事情, 我们还要参照更多的学习资料研究明白, 才好应用到实际环境中,  推荐 到百度搜索写 mongodb的资料, 也可以参考  配置mongodb分片群集(sharding cluster)

MongoDB备份与恢复

MongoDB基本操作指南

 

另外, 关于如何写入和读取这个 mongodb中的数据 可以参考: Spring Boot中使用MongoDB数据库

如何管理  mongodb  可以参考:   MongoDB 管理工具: Rockmongo

如何用docker的方法管理 mongodb的集群参考  采用docker镜像安装用浏览器访问mongodb副本集的方法

 

发表评论