MongoDB的Replica Set以及Auth的配置

http://blog.0x01.site/2017/01/13/MongoDB%E7%9A%84Replica-Set%E4%BB%A5%E5%8F%8AAuth%E7%9A%84%E9%85%8D%E7%BD%AE/

MongoDB事件出现后,公司要给MongoDB加Auth,因而我就调研了一番。
mongodb

如今MongoDB在生产中通常使用Replica Set的方式部署,若是一台宕机,另一台Secondary会变成Master继续服务,提升可用性。docker

使用docker搭个集群测试,首先建个network bridgeshell

1
docker network new mongo-network

而后就是运行MongoDB的容器,集群名为test-repbash

1
2
3
docker run --rm -it --name mongo1 --net=mongo-network mongo --replSet test-rep
docker run --rm -it --name mongo2 --net=mongo-network mongo --replSet test-rep
docker run --rm -it --name mongo3 --net=mongo-network mongo --replSet test-rep

而后再运行一个链接到上述三个MongoDB的容器服务器

1
docker run --rm -it --name mongo-client --net=mongo-network mongo /bin/bash

而后在容器中执行运维

1
mongo --host mongo1

发现链接上了,说明MongoDB的配置没有问题,而后是配置Replica Set。Replica Set要求配置的members中不能有localhost,而我配置为mongo2,mongo3这种一直都报相似的错误,我索性找出了几个容器的IP,配置上去post

1
docker network inspect mongo-network

能够看到几个容器的IP测试

而后就可使用IP地址配置了spa

1
2
config = {_id:"test-rep", version:1, members:[{_id:0, host:"172.19.0.5:27017", priority:5}, {_id:1, host:"172.19.0.3:27017", priority:2}, {_id:2, host:"172.19.0.4:27017", priority:3}]}
rs.initiate(config)

再去看mongod的log,发现集群同步成功code

把mongo1停掉,mongo2会成为primary


而后按照MongoDB的文档增长用户

1
2
3
4
5
6
7
db.createUser(
{
user: "admin",
pwd: "admin",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
}
)

重启mongod的进程,增长–auth参数,表示启用权限校验

1
2
3
docker run --rm -it --name mongo1 --net=mongo-network mongo --replSet test-rep --auth
docker run --rm -it --name mongo2 --net=mongo-network mongo --replSet test-rep --auth
docker run --rm -it --name mongo3 --net=mongo-network mongo --replSet test-rep --auth

发现一直报Error in heartbeat request to 172.19.0.5:27017; Unauthorized: not authorized on admin to execute command的错误,查了好久,发现Replica Set要使用keyFile的校验方式,让集群的member之间同步,也就是说,经过keyFile得到__system用户在local上的权限。local存放着Replica Set的配置和同步信息。
MongoDB官方推荐的keyFile的生产方式

1
2
openssl rand -base64 756 > <path-to-keyfile>
chmod 400 <path-to-keyfile>

先结束掉mongod的进程,由于要放入keyFile,因而我启动docker的时候,默认不启动mongod

1
docker run --rm -it --name mongo1 --net=mongo-network mongo /bin/bash

容器里没有装openssl,我偷懒使用了如下命令

1
2
echo 'I8au1RERvEQkIiIB7vhTMhfceA8oH/L0mT6xxeVgaJg/mYnnZe89dGWjMrQSXI7A' > /data/key_file
chmod 400 /data/key_file

而后启动mongod进程

1
mongod --replSet test-rep --auth --keyFile=/data/key_file

在mongo2,mongo3上按照上述命令,依次启动。发现漂亮的同步成功的标志

收工


生产上的MongoDB,切换到须要Auth,是否能够在不停机的情况下进行呢?

某同窗猜测,mongod不采用Auth的时候,客户端使用密码,可不能够呢?Python链接MongoDB的代码很简单

pymongo.MongoClient('mongodb://user:user1@mongo1:27017,mongo2:27017,mongo3:27017/mydb?authMechanism=SCRAM-SHA-1') 

访问mydb的时候,直接就抛Authentication failed错误了。若是我先添加了user呢?在mongo shell中执行

1
2
3
4
5
6
7
8
db.createUser(
{
user: "user",
pwd: "user1",
roles: [ { role: "readWrite", db: "mydb" },
{ role: "readWrite", db: "mydb2" } ]
}
)

刚刚的admin,只是访问admin库的用户名和密码,能够管理用户信息,user用户能够用来读写相应的库。此时,mongod依然没有使用--auth启动,所以是没有权限检查的,再次链接,一切正常。

所以配置步骤以下

  • 建立MongoDB用户
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
use admin
db.createUser(
{
user: "admin",
pwd: "admin",
roles: [ { role: "userAdminAnyDatabase", db: "admin" },
{ role: "clusterAdmin", db: "admin" },
]
}
)

use mydb
db.createUser(
{
user: "user",
pwd: "user1",
roles: [ { role: "dbOwner", db: "mydb" },
{ role: "dbOwner", db: "mydb2" } ]
}
)
  • 修改应用,更改MongoDB的URI
1
pymongo.MongoClient('mongodb://user:user1@mongo1:27017,mongo2:27017,mongo3:27017/mydb?authMechanism=SCRAM-SHA-1')
  • mongod增长keyFile
1
2
openssl rand -base64 756 > /data/key_file
chmod 400 /data/key_file
  • 把key_file上传到其余mongod服务器上,修改mongod配置,通常是/etc/mongodb.conf
1
2
3
security:
authorization: enabled
keyFile: /data/key_file
  • 而后同时重启三台mongod

这样只有重启的那一刹那不可用

相关文章
相关标签/搜索