Mô hình: Replica Set Cluster trên Mongodb
Chuẩn bị
– Hệ điều hành CentOS 7, MongoDB version 3.6, SELinux=disabled, Stop Firewalld service.
Máy 1: 10.128.0.2 mongo1
Máy 2: 10.128.0.3 mongo2
Máy 3: 10.128.0.4 mongo3
ln -sf /usr/share/zoneinfo/Asia/Ho_Chi_Minh /etc/localtime sed -i 's/^SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config
Bước 1. Cài đặt mongodb và tạo thư mục chứa dữ liệu và log MongoDB
+ Thực hiện trên cả 3 mongodb server .Tham khảo bài viết trước
vi /etc/yum.repos.d/mongodb-org-3.6.repo
[mongodb-org-3.6] name=MongoDB Repository baseurl=https://repo.mongodb.org/yum/redhat/6/mongodb-org/3.6/x86_64/ gpgcheck=1 enabled=1 gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc
sudo yum install -y mongodb-org mkdir -p /opt/mongo & cd /opt/mongo
mkdir db; mkdir log; chown mongod:mongod log db
+ Cấu hình map tĩnh ip address và hostname trên 3 mongodb server
vi /etc/hosts //Add thêm 3 dòng sau
10.128.0.2 mongo1 10.128.0.3 mongo2 10.128.0.4 mongo3
Bước 2: Cấu hình file mongod.conf
+ Trên server mongodb1
[root@mongo1 ~]# vi /etc/mongod.conf
# mongod.conf # where to write logging data.systemLog: destination: file logAppend: true path: /opt/mongo/log/mongod.log # Where and how to store data.storage: dbPath: /opt/mongo/db journal: enabled: true # how the process runsprocessManagement: fork: true # fork and run in background pidFilePath: /var/run/mongodb/mongod.pid # location of pidfile # network interfaces net: port: 27017 bindIp: 0.0.0.0 #replication: replication: oplogSizeMB: 1 replSetName: "mongo_rs"
Trên server mongo2 :
vi /etc/mongod.conf
# where to write logging data.systemLog: destination: file logAppend: true path: /opt/mongo/log/mongod.log # Where and how to store data.storage: dbPath: /opt/mongo/db journal: enabled: true # how the process runsprocessManagement: fork: true # fork and run in background pidFilePath: /var/run/mongodb/mongod.pid # location of pidfile # network interfaces net: port: 27017 bindIp: 0.0.0.0 #replication: replication: oplogSizeMB: 1 replSetName: "mongo_rs"
+ Trên Server mongo3 :
vi /etc/mongod.conf
# where to write logging data.systemLog: destination: file logAppend: true path: /opt/mongo/log/mongod.log # Where and how to store data.storage: dbPath: /opt/mongo/db journal: enabled: true # how the process runsprocessManagement: fork: true # fork and run in background pidFilePath: /var/run/mongodb/mongod.pid # location of pidfile # network interfaces net: port: 27017 bindIp: 0.0.0.0 #replication: replication: oplogSizeMB: 1 replSetName: "mongo_rs"
Bước 3.Khởi tạo mongodb replica set cluster
+ Khởi động lại dịch vụ mongod trên cả 3 servers
# systemctl enable mongod
# systemctl restart mongod
+ Khởi tạo mongodb replica set trên mongodb1 server ( primary)
[root@mongo1 ~]# mongo
MongoDB shell version: 3.6 connecting to: test>rs.initiate({_id: "mongo_rs", members:[{_id:1, host: "mongo1:27017", priority:3},{_id:2, host: "mongo2:27017", priority:2}, {_id:3, host: "mongo3:27017", priority: 1}]})mongo_rs:PRIMARY> rs.status(){ "set" : "mongo_rs", "date" : ISODate("2018-09-23T13:58:12.068Z"), "myState" : 1, "term" : NumberLong(3), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "heartbeatIntervalMillis" : NumberLong(2000), "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1537711084, 1), "t" : NumberLong(3) }, "readConcernMajorityOpTime" : { "ts" : Timestamp(1537711084, 1), "t" : NumberLong(3) }, "appliedOpTime" : { "ts" : Timestamp(1537711084, 1), "t" : NumberLong(3) }, "durableOpTime" : { "ts" : Timestamp(1537711084, 1), "t" : NumberLong(3) } }, "members" : [ { "_id" : 1, "name" : "mongo1:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 1543, "optime" : { "ts" : Timestamp(1537711084, 1), "t" : NumberLong(3) }, "optimeDate" : ISODate("2018-09-23T13:58:04Z"), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "infoMessage" : "", "electionTime" : Timestamp(1537709562, 1), "electionDate" : ISODate("2018-09-23T13:32:42Z"), "configVersion" : 1, "self" : true, "lastHeartbeatMessage" : "" }, { "_id" : 2, "name" : "mongo2:27017", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 1540, "optime" : { "ts" : Timestamp(1537711084, 1), "t" : NumberLong(3) }, "optimeDurable" : { "ts" : Timestamp(1537711084, 1), "t" : NumberLong(3) }, "optimeDate" : ISODate("2018-09-23T13:58:04Z"), "optimeDurableDate" : ISODate("2018-09-23T13:58:04Z"), "lastHeartbeat" : ISODate("2018-09-23T13:58:11.068Z"), "lastHeartbeatRecv" : ISODate("2018-09-23T13:58:11.664Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "", "syncingTo" : "mongo1:27017", "syncSourceHost" : "mongo1:27017", "syncSourceId" : 1, "infoMessage" : "", "configVersion" : 1 }, { "_id" : 3, "name" : "mongo3:27017", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 1540, "optime" : { "ts" : Timestamp(1537711084, 1), "t" : NumberLong(3) }, "optimeDurable" : { "ts" : Timestamp(1537711084, 1), "t" : NumberLong(3) }, "optimeDate" : ISODate("2018-09-23T13:58:04Z"), "optimeDurableDate" : ISODate("2018-09-23T13:58:04Z"), "lastHeartbeat" : ISODate("2018-09-23T13:58:11.068Z"), "lastHeartbeatRecv" : ISODate("2018-09-23T13:58:10.303Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "", "syncingTo" : "mongo2:27017", "syncSourceHost" : "mongo2:27017", "syncSourceId" : 2, "infoMessage" : "", "configVersion" : 1 } ], "ok" : 1, "operationTime" : Timestamp(1537711084, 1), "$clusterTime" : { "clusterTime" : Timestamp(1537711084, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }} mongo_rs:PRIMARY>
+ Tạo database “people” và collection “employees” trên mongodb1 (primary)
mongo_rs:PRIMARY> use people
switched to db people
mongo_rs:PRIMARY> db.createCollection('people')
mongo_rs:PRIMARY> db.getCollection("people").insert({ "firstName": "test", "lastName": "tech", "started": NumberInt("2020")})
+ Kiểm tra đồng bộ dữ liệu trên mongodb2 & mongodb3 ( secondary )
[root@mongo2 ~]# mongo
MongoDB shell version: 3.6 connecting to: testmongo_rs:SECONDARY> rs.slaveOk() mongo_rs:SECONDARY> show dbs local 0.000GB people 0.000GB mongo_rs:SECONDARY> use people switched to db people mongo_rs:SECONDARY> show collections employees people mongo_rs:SECONDARY>db.people.find()
{ "_id" :ObjectId("5ba7909733eebb6ed2fa4d1c"), "firstName" : "Sam", "lastName" : "Sales", "started" : 1998 } { "_id" : ObjectId("5ba7917a2f847018dc6e9c9a"), "firstName" : "kien", "lastName" : "tech", "started" : 1991 } { "_id" : ObjectId("5ba79272019fdc1bc4c0601f"), "firstName" : "le", "lastName" : "tech", "started" : 2018 } { "_id" : ObjectId("5ba792e92f847018dc6e9c9b"), "firstName" : "nam", "lastName" : "tech", "started" : 1991 } { "_id" : ObjectId("5ba792fb2f847018dc6e9c9c"), "firstName" : "Ly", "lastName" : "tech", "started" : 1991 } { "_id" : ObjectId("5ba7933a2f847018dc6e9c9d"), "firstName" : "hcm", "lastName" : "tech", "started" : 1991 } { "_id" : ObjectId("5ba795432f847018dc6e9c9e"), "firstName" : "st", "lastName" : "tech", "started" : 2018 } { "_id" : ObjectId("5ba795532f847018dc6e9c9f"), "firstName" : "st2", "lastName" : "tech", "started" : 2019 } { "_id" : ObjectId("5ba7955c2f847018dc6e9ca0"), "firstName" : "st3", "lastName" : "tech", "started" : 2020 }
+ Kiểm tra khả năng chịu lỗi bằng cách kill -9 process_mongodb_id trên primary (mongodb1) và kiểm tra khả năng replica set trên mongodb2 & mongodb3
+ Kiểm tra khả năng failover trên mongodb2. Khi mongodb1 down, lúc này mongodb2 với priority: 2 sẽ tự động chuyển từ secondary thành primary có khả năng đọc+ghi dữ liệu
[root@mongo2 ~]# mongo
mongo_rs:PRIMARY> rs.status() {"set" : "mongo_rs", "date" : ISODate("2018-09-23T14:10:55.024Z"), "myState" : 1, "term" : NumberLong(4), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "heartbeatIntervalMillis" : NumberLong(2000), "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1537711852, 1), "t" : NumberLong(4) }, "readConcernMajorityOpTime" : { "ts" : Timestamp(1537711852, 1), "t" : NumberLong(4) }, "appliedOpTime" : { "ts" : Timestamp(1537711852, 1), "t" : NumberLong(4) }, "durableOpTime" : { "ts" : Timestamp(1537711852, 1), "t" : NumberLong(4) } }, "members" : [ { "_id" : 1, "name" : "mongo1:27017", "health" : 0, "state" : 8, "stateStr" : "(not reachable/healthy)", "uptime" : 0, "optime" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "optimeDurable" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "optimeDate" : ISODate("1970-01-01T00:00:00Z"), "optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"), "lastHeartbeat" : ISODate("2018-09-23T14:10:48.551Z"), "lastHeartbeatRecv" : ISODate("2018-09-23T14:08:51.384Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "Couldn't get a connection within the time limit", "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "infoMessage" : "", "configVersion" : -1 }, { "_id" : 2, "name" : "mongo2:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 5175, "optime" : { "ts" : Timestamp(1537711852, 1), "t" : NumberLong(4) }, "optimeDate" : ISODate("2018-09-23T14:10:52Z"), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "infoMessage" : "could not find member to sync from", "electionTime" : Timestamp(1537711740, 1), "electionDate" : ISODate("2018-09-23T14:09:00Z"), "configVersion" : 1, "self" : true, "lastHeartbeatMessage" : "" }, { "_id" : 3, "name" : "mongo3:27017", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 4141, "optime" : { "ts" : Timestamp(1537711852, 1), "t" : NumberLong(4) }, "optimeDurable" : { "ts" : Timestamp(1537711852, 1), "t" : NumberLong(4) }, "optimeDate" : ISODate("2018-09-23T14:10:52Z"), "optimeDurableDate" : ISODate("2018-09-23T14:10:52Z"), "lastHeartbeat" : ISODate("2018-09-23T14:10:54.599Z"), "lastHeartbeatRecv" : ISODate("2018-09-23T14:10:53.474Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "", "syncingTo" : "mongo2:27017", "syncSourceHost" : "mongo2:27017", "syncSourceId" : 2, "infoMessage" : "", "configVersion" : 1 } ], "ok" : 1, "operationTime" : Timestamp(1537711852, 1), "$clusterTime" : { "clusterTime" : Timestamp(1537711852, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }mongo_rs:PRIMARY>
+ Khi mongo1 up lại với priority = 3, lớn nhất trong 3 mongo server sẽ tự động đảm nhiệm vai trò “Primary” từ mongo2
Bước 4: Cấu hình enable Security Authentication trong mongodb replica set
+ Khi enable authentication trong replica set hoặc sharded cluster, các members trong replica set hoặc sharded clusters phải cung cấp keyfile chứa chứng thực. Chúng ta phải enable authentication trên mỗi member server. Sau đây chúng ta sẽ sử dụng keyfile để authentication trên members của MongoDB replica set.
+ Bước 4.1: Creating the users “admin” trên database “admin” có role: userAdminAnyDatabase có quyền quản lý tạo, xóa, sửa các users khác
mongo_rs:PRIMARY> use admin
switched to db admin
mongo_rs:PRIMARY> db.createUser({ user: "admin", pwd: "adminpassword", roles: [{ role: "userAdminAnyDatabase", db: "admin" }] })Successfully added user: { "user" : "admin", "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ]}
– Kiểm tra xem user được tạo có thể authen chưa
mongo_rs:PRIMARY> db.auth("admin","adminpassword")
mongo_rs:PRIMARY> exit
– Enable authentication trong file mongod.conf
[root@mongo1 ~]# vim /etc/mongod.conf //Thêm 2 dòng bên dưới
security: authorization: enabledkeyFile: /opt/mongo/mongodb-keyfile
+ Bước 4.2: Tạo keyfile trên primary server và copy keyfile sang toàn bộ secondary server
[root@mongo1 ~]# openssl rand -base64 741 > /opt/mongo/mongodb-keyfile
[root@mongodb1 ~]# chmod 600 /opt/mongo/mongodb-keyfile
[root@mongodb1 ~]# scp /opt/mongo/mongodb-keyfile root@10.128.0.2:/opt/mongo
[root@mongodb1 ~]# scp /opt/mongo/mongodb-keyfile root@10/128.0.4:/opt/mongo
+ Bước 4.3: Enable authentication và replication trên mỗi member của replica set hoặc sharded cluster
vim /etc/mongodb.conf //add thêm dòng sau
security: authorization: enabled keyFile: /opt/mongo/mongodb-keyfile
+ Bước 4.4: Khởi động mongod service trên cả 3 server
service mongod restart
+ Bước 4.5: Tạo các user khác có quyền quản lý trên từng database của mình
– Chứng thực bằng user “admin” tạo bên trên
[root@mongo1 ~]# mongo --port 27017 -u "admin" -p "adminpassword" --authenticationDatabase "admin"
MongoDB shell version: 3.6 connecting to: 127.0.0.1:27017/test mongo_rs:PRIMARY> use admin switched to db admin mongo_rs:PRIMARY> db.auth("admin","adminpassword")
1
– Tạo các users với role “dbOwner” trên từng database
use yourdatabasedb.createUser({ user: "youruser", pwd: "yourpassword", roles: [{ role: "dbOwner", db: "yourdatabase" }] })
Ví dụ: Tạo user “people” có role “dbOwner” trên “people” DB
mongo_rs:PRIMARY> use student
mongo_rs:PRIMARY> db.createUser({ user: "student", pwd: "adminpassword", roles: [{ role: "dbOwner", db: "student" }] })
Successfully added user: { "user" : "student", "roles" : [ { "role" : "dbOwner", "db" : "student" } ]}
– Kiểm tra lại các account vừa tạo
mongo_rs:PRIMARY> use admin
switched to db admin
mongo_rs:PRIMARY> db.system.users.find({})
{ "_id" : "admin.admin", "user" : "admin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "IIN42/+mHKUDzKNuei7gIw==", "storedKey" : "fgEx9jCMsLkZkjt3awJQMQanwTI=", "serverKey" : "KgaZuKvQIKhD2GhCkO4rLD1bHEE=" } }, "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }{ "_id" : "student.student", "user" : "student", "db" : "student", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "bhfnfBsKv4KPCuK9TDfp2Q==", "storedKey" : "xvb9NT/oG1NkYdHRWLQYGPheDlM=", "serverKey" : "cqyxdZ+jb0etaLFvLvd5pE05QvM=" } }, "roles" : [ { "role" : "dbOwner", "db" : "student" } ] }
– Kết nối tới database “people” bằng account “people” vừa tạo ở trên
[root@mongo1 ~]# mongo --port 27017 -u "student" -p "adminpassword" --authenticationDatabase "student"
MongoDB shell version: 3.6 connecting to: 127.0.0.1:27017/test
mongo_rs:PRIMARY> db //hiển thị current db
Kiểm tra
mongo_rs:PRIMARY> use student
switched to db student
mongo_rs:PRIMARY> show collections;
mongo_rs:PRIMARY> db.course.insert({Name: "Networking", Teacher: "Mr Hoang"})
WriteResult({ "nInserted" : 1 }) mongo_rs:PRIMARY> db.course.find() { "_id" : ObjectId("59373cfb8657a0583b03207d"), "Name" : "Networking", "Teacher" : "Mr Hoang" }
– Tạo superuser có full permission
mongo_rs:PRIMARY> use admin
switched to db admin
mongo_rs:PRIMARY> db.createUser({ user: "superadmin", pwd: "superpassword", roles: ["root"] })
Successfully added user: { "user" : "superadmin", "roles" : [ "root" ] }
– Kiểm tra account superuser
[root@mongo1 ~]# mongo --port 27017 -u "superadmin" -p "superpassword" --authenticationDatabase "admin"
MongoDB shell version: 3.6connecting to: 127.0.0.1:27017/test
mongo_rs:PRIMARY> rs.status()
Như vậy, qua bài lab này mình đã hướng dẫn các bạn xây dựng được một hệ thống Master slave trong Mongo.
Chúc các bạn thành công!
Tham khảo: How to install a mongo cluster with 3 replica set
Cảm ơn bạn đã trả lời.