سلام. در این قسمت میخوام راه اندازی replica set در mongo رو با هم بررسی کنیم. تا حالا همیشه از virtualbox برای شبیه سازی استفاده می کردم. اما در این مورد به مشکلی برخوردم که از نسخه 4 به بعد mongo امکان راه اندازی mongo رو نداشتم. مشکل مربوط به موردی در cpu میشد که بصورت زیر در راه اندازی سرویس mongo خودش رو نشون میداد:
Process: 1170 ExecStart=/usr/bin/mongod $OPTIONS (code=dumped, signal=ILL)
وقتی جستجو کردم متوجه شدم مربوطه به خصوصیتی در cpu با نام Advanced Vector Extensions یا به اختصار avx هست که یا هنوز نشده یا من موفق نشدم که در virtualbox حلش کنم. بنابراین مهاجرت کردم به vmware . برای اطلاعات بیشتر در این مورد میتونید به https://en.wikipedia.org/wiki/Advanced_Vector_Extensions مراجعه کنید.
سه ماشین مجازی نصب کردم (https://vahiddb.com/fa/os/os-infra/install-oracle-linux-8-9) و به هر کدام دو کارت شبکه اختصاص دادم. یکی از کارت شبکه ها رو nat کردم و دیگری رو hostonly قرار دادم . اولی برای اتصال به اینترنت و دومی برای اتصال از ماشین local و بین خودشون.
اگر از ایران اینکار رو انجام میدید، می تونید از سایت https://shecan.ir/ برای رفع مشکلات اتصال استفاده کنید.
برای تنظیمات شبکه در vmware اینکار رو انجام بدید. virtual network editor رو بصورت run as administrator اجرا کنید.
و برای کارت شبکه nat هم بصورت زیر:
و در تنظمیات ماشینها هم کارت شبکه ها رو در قسمت custom ، کارتهای مربوطه رو انتخاب کنید.
در داخل ماشین می تونید با استفاده از لینک زیر کارت شبکه host-only رو با استفاده از لینک زیر آدرس دهی کنید. حواسمون باشه که در رنج آدرسهای 192.168.188.0 می تونید آدرس دهی کنید.
https://vahiddb.com/fa/os/os-infra/set-ip-via-nmcli-on-just-one-network-card-fa
حالا می رویم برای کانفیگ repository ها. یک پوشه به اسم /cdrom می سازیم و بعد از اینکه دوباره iso را در نرم افزار vmware به ماشین کانکت کردیم، آنرا در سیستم عامل با دستور زیر mount می کنیم.
mount /dev/cdrom /cdrom/
سپس هر آن چیزی که در حال حاضر در مسیر etc/yum.repos.d هست را به پوشه backup انتقال می دهیم و repository های زیر را می سازیم:
[root@mongo1 yum.repos.d]# ls
backup media.repo mongodb-enterprise-7.0.repo
[root@mongo1 yum.repos.d]# cat media.repo
[dvd-BaseOS]
name=DVD for RHEL - BaseOS
baseurl=file:///cdrom/BaseOS
enabled=1
gpgcheck=0
[dvd-AppStream]
name=DVD for RHEL - AppStream
baseurl=file:///cdrom/AppStream
enabled=1
gpgcheck=0
[root@mongo1 yum.repos.d]# cat mongodb-enterprise-7.0.repo
[mongodb-enterprise-7.0]
name=MongoDB Enterprise Repository
baseurl=https://repo.mongodb.com/yum/redhat/8/mongodb-enterprise/7.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-7.0.asc
در تنظیمات هر سه سرور در سیستم عامل پورت مربوط به mongo رو وارد میکنیم.
firewall-cmd --add-port=27017/tcp --permanent
firewall-cmd --reload
همچنین selinux رو با تنظیمات زیر بصورت موقت و بعد با تغییر فایل بصورت دائم غیر فعال می کنیم.
setenforce 0
برای تغییر دائمی، فایل /etc/selinux/config
را ویرایش کنید:
SELINUX=permissive
و حالا می توانیم نصب را انجام دهیم.
dnf install -y mongodb-enterprise
تمام اینکار ها رو روی هر سه ماشین انجام می دهیم.
در صورتی که در زمانی که سیستم عامل رو نصب می کردید، پوشه جدا گانه ای برای داده در نظر گرفته باشید، می تونید با تغییر زیر در تنظیمات /etc/mongod.conf اون رو اعمال کنید:
storage:
dbPath: /data
دقت کنید که با هر تغییری در فایل کانفیگ دستور زیر رو بزنید که مطمئن بشید که مشکلی نداشته باشه
mongosh --eval 'db.adminCommand({ getCmdLineOpts: 1 })'
حالا تنظیم bindip جایی که هر کدام از node ها رو میخواهیم تنظیم کنیم که روی چه آدرسی سرویس دهی کنند:
برای mongo1
:
net:
port: 27017
bindIp: 192.168.188.11
برای mongo2
:
net:
port: 27017
bindIp: 192.168.188.12
برای mongo3
:
net:
port: 27017
bindIp: 192.168.188.13
حالا باید یک فایل keyfile برای احراز هویت بین نودها ایجاد کنیم و در هر سه سرو کپی کنیم.
openssl rand -base64 756 > /etc/mongo-keyfile
chmod 400 /etc/mongo-keyfile
chown mongod:mongod /etc/mongo-keyfile
scp /etc/mongo-keyfile mongo2:/etc/
scp /etc/mongo-keyfile mongo3:/etc/
بعد از انتقال دستور زیر را در هر کدام از سرورهای 2و 3 می زنیم تا مالکیت فایلها به mongo انتقال یابد.
chmod 400 /etc/mongo-keyfile
chown mongod:mongod /etc/mongo-keyfile
تنظیمات زیر را در /etc/mongod.conf برای فعال سازی authentication وارد میکنیم.
security:
authorization: "enabled"
keyFile: /etc/mongo-keyfile
همینطور در فایل کانفیگ نام replicaset را بصورت زیر وارد می کنیم:
replication:
replSetName: rs0
برای افزایش امنیت کاربر ادمین بصورت زیر ایجاد می کنیم. با mongosh متصل می شویم:
use admin;
db.createUser({
user: "root",
pwd: "mySecurePass",
roles: [
{ role: "userAdminAnyDatabase", db: "admin" },
{ role: "readWriteAnyDatabase", db: "admin" },
{ role: "dbAdminAnyDatabase", db: "admin" },
{ role: "clusterAdmin", db: "admin" }
]
});
سرویس مونگودیبی را روی هر سرور راهاندازی کنید:
systemctl start mongod
بعد از این قسمت حتما دستور زیر رو اجرا کنید که ببینید درست بالا اومدن یا نه
systemctl status mongod
اگر این قسمت failed نشون داد حتماً لاگ رو چک کنید و مشکل رو برطرف کنید.
/var/log/mongodb/mongod.log
با نام کاربری و پسوردی که تعریف کردیم وصل میشیم.
mongosh --host 192.168.188.11 --port 27017 -u "root" -p "mySecurePass" --authenticationDatabase "admin"
بعد از اینکه وصل شدیم، دستور زیر را می زنیم:
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "192.168.188.11:27017" },
{ _id: 1, host: "192.168.188.12:27017" },
{ _id: 2, host: "192.168.188.13:27017" }
]
});
مشکلاتی که در حین نصب باهاش مواجه شدم اینها بود:
مشکل 1: خطای SocketException
راهحل: اطمینان حاصل کنید که آدرسهای IP در تنظیمات bindIp
موجود و صحیح هستند.
مشکل 2: خطای احراز هویت SCRAM authentication failed
راهحل: بررسی کنید که فایل keyFile
در هر سرور یکسان و با دسترسی مناسب باشد.
حالا برای اینکه ببینیم همه چی درست هست یا نه دوباره به یکی از نودها وصل می شویم و دستور زیر را می زنیم:
[root@mongo2 ~]# mongosh --host 192.168.188.11 --port 27017 -u "root" -p "shahrtech" --authenticationDatabase "admin"
Current Mongosh Log ID: 67344f62a2965befb2c1c18b
Connecting to: mongodb://<credentials>@192.168.188.11:27017/?directConnection=true&authSource=admin&appName=mongosh+2.3.3
Using MongoDB: 7.0.15
Using Mongosh: 2.3.3
For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/
------
The server generated these startup warnings when booting
2024-11-13T01:24:11.603-05:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. We suggest setting it to 'never' in this binary version
2024-11-13T01:24:11.603-05:00: vm.max_map_count is too low
------
Enterprise rs0 [direct: secondary] test> rs.status()
{
set: 'rs0',
date: ISODate('2024-11-13T07:04:08.314Z'),
myState: 2,
term: Long('7'),
syncSourceHost: 'mongo2:27017',
syncSourceId: 1,
heartbeatIntervalMillis: Long('2000'),
majorityVoteCount: 2,
writeMajorityCount: 2,
votingMembersCount: 3,
writableVotingMembersCount: 3,
optimes: {
lastCommittedOpTime: { ts: Timestamp({ t: 1731481444, i: 1 }), t: Long('7') },
lastCommittedWallTime: ISODate('2024-11-13T07:04:04.512Z'),
readConcernMajorityOpTime: { ts: Timestamp({ t: 1731481444, i: 1 }), t: Long('7') },
appliedOpTime: { ts: Timestamp({ t: 1731481444, i: 1 }), t: Long('7') },
durableOpTime: { ts: Timestamp({ t: 1731481444, i: 1 }), t: Long('7') },
lastAppliedWallTime: ISODate('2024-11-13T07:04:04.512Z'),
lastDurableWallTime: ISODate('2024-11-13T07:04:04.512Z')
},
lastStableRecoveryTimestamp: Timestamp({ t: 1731417971, i: 1 }),
members: [
{
_id: 0,
name: 'mongo1:27017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
uptime: 2400,
optime: { ts: Timestamp({ t: 1731481444, i: 1 }), t: Long('7') },
optimeDate: ISODate('2024-11-13T07:04:04.000Z'),
lastAppliedWallTime: ISODate('2024-11-13T07:04:04.512Z'),
lastDurableWallTime: ISODate('2024-11-13T07:04:04.512Z'),
syncSourceHost: 'mongo2:27017',
syncSourceId: 1,
infoMessage: '',
configVersion: 1,
configTerm: 7,
self: true,
lastHeartbeatMessage: ''
},
{
_id: 1,
name: 'mongo2:27017',
health: 1,
state: 1,
stateStr: 'PRIMARY',
uptime: 14,
optime: { ts: Timestamp({ t: 1731481444, i: 1 }), t: Long('7') },
optimeDurable: { ts: Timestamp({ t: 1731481444, i: 1 }), t: Long('7') },
optimeDate: ISODate('2024-11-13T07:04:04.000Z'),
optimeDurableDate: ISODate('2024-11-13T07:04:04.000Z'),
lastAppliedWallTime: ISODate('2024-11-13T07:04:04.512Z'),
lastDurableWallTime: ISODate('2024-11-13T07:04:04.512Z'),
lastHeartbeat: ISODate('2024-11-13T07:04:07.531Z'),
lastHeartbeatRecv: ISODate('2024-11-13T07:04:07.046Z'),
pingMs: Long('0'),
lastHeartbeatMessage: '',
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
electionTime: Timestamp({ t: 1731481434, i: 1 }),
electionDate: ISODate('2024-11-13T07:03:54.000Z'),
configVersion: 1,
configTerm: 7
},
{
_id: 2,
name: 'mongo3:27017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
uptime: 14,
optime: { ts: Timestamp({ t: 1731481444, i: 1 }), t: Long('7') },
optimeDurable: { ts: Timestamp({ t: 1731481444, i: 1 }), t: Long('7') },
optimeDate: ISODate('2024-11-13T07:04:04.000Z'),
optimeDurableDate: ISODate('2024-11-13T07:04:04.000Z'),
lastAppliedWallTime: ISODate('2024-11-13T07:04:04.512Z'),
lastDurableWallTime: ISODate('2024-11-13T07:04:04.512Z'),
lastHeartbeat: ISODate('2024-11-13T07:04:07.531Z'),
lastHeartbeatRecv: ISODate('2024-11-13T07:04:07.531Z'),
pingMs: Long('0'),
lastHeartbeatMessage: '',
syncSourceHost: 'mongo2:27017',
syncSourceId: 1,
infoMessage: '',
configVersion: 1,
configTerm: 7
}
],
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1731481444, i: 1 }),
signature: {
hash: Binary.createFromBase64('5fdxvqSMElKHHKp0X7c8WYFLfO8=', 0),
keyId: Long('7436308128641056774')
}
},
operationTime: Timestamp({ t: 1731481444, i: 1 })
}