Hướng dẫn cấu hình Replica Set Cluster trên Mongodb

MongoDB replica set dữ liệu sẽ được đồng bộ giữa  “Primary” và các “Secondary” mongodb server. “Primary”  member của replica set có thể đọc và ghi dữ liệu trong khi “Secondary” members chỉ có thể đọc dữ liệu. Khi “Primary” hang/down, “Secondarymongodb sẽ tự động chuyển thành “Primary” giúp hệ thống chịu lỗi và có tính sẵn sàng cao.

 

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 [email protected]:/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

Bài viết liên quan

One thought on “Hướng dẫn cấu hình Replica Set Cluster trên Mongodb

Leave a Reply

Your email address will not be published. Required fields are marked *