搭建一個分布式MongoDB鑒權集群


  今天休假在家,測試並搭建了一個replica set shard MongoDB鑒權集群。replica set shard 鑒權集群中文資料比較少,本文是個人筆記,同時也希望對后來者有所幫助。本文僅是搭建步驟和Q&A,用於實際工作中的使用查閱,閱讀者需要有分布式集群的理論基礎。

  關鍵字:Replica-Set Shard 副本 分片 鑒權 KeyFile auth

  MongoDB根據部署的不同,有兩種添加鑒權的方式,分別是單實例的鑒權方式KeyFile的鑒權方式。兩種方式的共同點都是,先在沒有鑒權的情況下創建超級用戶,然后再以鑒權的方式重啟實例。下面分別介紹這兩種方式。

1 單實例的鑒權部署

  這種方式比較簡單,步驟如下:

1.1 啟動MongoDB

   mongod --logpath ./test.log -dbpath ./data --port 8765 --fork

1.2 添加超級用戶

  use admin

  db.createUser({user:"cswuyg",pwd:"abc123",roles:[{role:"userAdminAnyDatabase",db:"admin"}]})

1.3 以auth參數重啟MongoDB

  mongod --logpath ./test.log -dbpath ./data --port 8765 --auth --fork

1.4 mongodb shell 登陸

#方式1:
mongo --port 8765 -u 'cswuyg' -p 'abc123' --authenticationDatabase 'admin'
#或者
#方式2:
mongo --port 8765
#然后在mongo shell下執行:
use admin
db.auth('cswuyg', 'abc123')

1.5 創建普通用戶

MongoDB的賬號跟隨DB,創建舉例:

#以超級用戶登陸之后,執行以下mongodb shell命令
use cswuyg
db.createUser({'user':'cswuyg', pwd:'cswuyg', roles:['readWrite', 'dbAdmin']})

2 分布式的鑒權集群部署

  我要搭建的集群含有兩個shard;shard由replica set組成,replica set含有3個實例;mongodb config含有3個實例。如圖所示:

下面介紹搭建步驟,兩個副本中的六個mongodb實例的搭建雷同,三個配置實例的搭建也雷同,下面僅介紹不重復的內容:

2.1 安裝openssl,使用openssl生成keyfile

openssl rand -base64 755 > mongodb-keyfile

2.2 搭建MongoDB副本

首先以無權限方式啟動replica set,然后為replica set設置賬號密碼。

replica set A 需要啟動三個MongoDB實例,下面的mongodb 配置文件以其中一個實例為例。

無鑒權啟動配置config(set_one_mongod_17018.conf):

storage:
    dbPath: "/home/ssd2/mongo_data/set_one_mongo17018"
systemLog:
    destination: file
    path: "/home/ssd2/mongo_data/set_one_mongo17018.log"
    logAppend: true
replication:
    oplogSizeMB: 2048 
    replSetName: "set_one"
net:
    port: 17018
processManagement:
    fork: true
setParameter:
    cursorTimeoutMillis: 20000

啟動命令(start.sh):

/home/ssd2/mongo-3.2.8-release/bin/mongod -f /home/ssd2/set_one_mongod_17018.conf
#/home/ssd2/mongo-3.2.8-release/bin/mongod -f /home/ssd2//set_one_mongod_17018_auth.conf

以同樣的方式再啟動另外兩個實例,然后配置副本集群:進入某個實例的mongo shell執行初始化:

rs.initiate({"_id" : "set_one", "members" : [{_id : 1, host: "host1:17018"}, {"_id": 2, "host": "host2:17018"}, {"_id": 3, "host" : "host3:17018"}]})

接着,mongo shell下創建超級用戶:

db.createUser({user: 'cswuyg', pwd: cswuyg@home', roles:[{role:'root', db:'admin'}]})
db.createUser({user: "wuyg", pwd: "wuyg@home", roles: [{role:"userAdminAnyDatabase", db:"admin"}]})

至此 replica set A(副本A)處理完成。

再以同樣的方式創建replica set B(副本B)

2.3 搭建config server

我沒有使用replica set的方式搭建配置服務,所以各個單實例要獨立設置賬號密碼。

 無鑒權的啟動配置config(config_27019.conf):

storage:
    dbPath: "/home/work/mongo_data/config27019"
systemLog:
    destination: file
    path: "/home/work/mongo_data/mongo27019.log"
    logAppend: true
sharding:
    clusterRole: "configsvr"
net:
    port: 27019
setParameter:
    cursorTimeoutMillis: 20000
processManagement:
    fork: true

啟動命令(start.sh):

#/home/work/mongo/bin/mongod -f /home/work/config_27019_auth.conf
/home/work/mongo/bin/mongod -f /home/work/config_27019.conf

啟動之后,創建超級用戶,在mongo shell下執行:

db.createUser({user: 'cswuyg', pwd: cswuyg@home', roles:[{role:'root', db:'admin'}]})
db.createUser({user: "wuyg", pwd: "wuyg@home", roles: [{role:"userAdminAnyDatabase", db:"admin"}]})

接着以同樣的方式搭建另外兩個config server。

2.4 搭建mongos

無鑒權啟動配置config(mongos_27032.conf):

sharding:
    configDB: "host1:27019,host2:27019,host3:27019"
systemLog:
    destination: file
    path: "/home/work/mongo_data/mongos27032.log"
net:
    port: 27032
processManagement:
    fork: true

啟動命令(start.sh):

#/home/work/mongo/bin/mongod -f /home/work/config_27019_auth.conf
/home/work/mongo/bin/mongod -f /home/work/config_27019.conf

在mongos下創建超級用戶,mongo shell下執行:

db.createUser({user: 'cswuyg', pwd: cswuyg@home', roles:[{role:'root', db:'admin'}]})
db.createUser({user: "wuyg", pwd: "wuyg@home", roles: [{role:"userAdminAnyDatabase", db:"admin"}]})

如有多個APP,可以繼續以同樣的方式創建多個mongos服務。

2.5 所有mongod、mongos都以鑒權方式重啟

注:必要的時候在mongod啟動時,加上numactl --interleave=all 參數

下面列舉下有鑒權的mongodb副本實例、mongodb配置服務實例、mongos實例的啟動配置:

副本實例配置舉例:

storage:
    dbPath: "/home/ssd2/mongo_data/set_one_mongo17018"
systemLog:
    destination: file
    path: "/home/ssd2/mongo_data/set_one_mongo17018.log"
    logAppend: true
replication:
    oplogSizeMB: 2048
    replSetName: "set_one"
net:
    port: 17018
security:
    keyFile: "/home/ssd2/mongodb-keyfile"
    authorization: "enabled"
processManagement:
    fork: true
setParameter:
    cursorTimeoutMillis: 20000

config server配置舉例:

storage:
    dbPath: "/home/work/mongo_data/config27019"
systemLog:
    destination: file
    path: "/home/work/mongo_data/mongo27019.log"
    logAppend: true
sharding:
    clusterRole: "configsvr"
net:
    port: 27019
setParameter:
    cursorTimeoutMillis: 20000
security:
    keyFile: "/home/work/mongodb-keyfile"
    authorization: "enabled"
processManagement:
    fork: true

mongos 配置舉例:

sharding:
    configDB: "host1:27019,host2:27019,host3:27019"
systemLog:
    destination: file
    path: "/home/work/mongo_data/mongos27032.log"
net:
    port: 27032
processManagement:
    fork: true
security:
    keyFile: "/home/work/mongodb-keyfile"
    authorization: "enabled"

啟動shell,參見上面的start.sh.

2.6 檢查鑒權集群效果

#使用超級權限登陸
mongo --port 27031 -u zhangsan -p zhangsan_password

#新建一個collection & 寫入數據 & 設置分布式collection
use cswuyg
db.cswuyg.save({'a':'a'})
use admin
db.runCommand({"enablesharding":"cswuyg"})
db.runCommand({"shardcollection":"cswuyg.cswuyg","key":{"_id":1}})

#新建用戶
#使用超級用戶權限登陸,然后
use cswuyg
db.createUser({'user':'zhangsan', pwd:'zhangsan_password', roles:['readWrite', 'dbAdmin']})

#測試新用戶的使用:
mongo --port 27031 -u zhangsan -p zhangsan_password 

#測試讀寫
db.coll.find()
db.coll.save({'a':'1'})

3 Q&A

3.1 為什么副本實例、配置實例也要單獨創建賬號密碼?

答:因為副本實例、配置實例設置的賬號密碼只是自己的賬號密碼,存儲在本地,而從mongos設置的集群的賬號密碼存儲在config server。如果直接從mongos上設置賬號密碼,那么副本實例、配置實例將會因為沒有賬號而無法做任何運維操作。

3.2 權限最大的超級用戶是哪個?

答:root,創建方式:db.createUser({user: 'cswuyg', pwd: cswuyg@home', roles:[{role:'root', db:'admin'}]})

3.3 如果config server忘記單獨添加權限,怎么辦?

答:我們有三個config server,要逐個處理;首先停掉第一個config server,然后使用它的磁盤文件,以非鑒權方式啟動,接着創建超級用戶,最后再以鑒權方式重啟;其它兩個config server也以同樣的方式逐一處理。另外,如果是 replica set 忘記單獨添加權限,可以首先新加一個有單獨權限的replica set,然后再把舊的replica set刪除掉,在刪除過程中可能需要移動DB的Primary所在:db.runCommand( { movePrimary : "monitor_check", to : "set_one" } );然后,再去掉舊的副本 db.runCommand( { removeShard : "old" } )。

4 參考資料

參考資料1,單實例鑒權:https://docs.mongodb.com/manual/tutorial/enable-authentication/

參考資料2,集群鑒權:https://docs.mongodb.com/v3.2/tutorial/enforce-keyfile-access-control-in-existing-replica-set/

搭建無鑒權的replica set shard集群參見:http://www.cnblogs.com/cswuyg/p/4356637.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM