راه اندازی replica set در دیتابیس mongo

سلام. در این قسمت میخوام راه اندازی 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 })

}