MongoDB репликациясы және Ubuntu жүйесінде жаңарту
Бұл мақалада Ubuntu 18.04 жүйесінде MongoDB-ді қалай репликациялау және жаңарту керектігін қарастырамыз.
Replicaset — бұл бірдей деректер жиынын қамтитын, ақаулардан қорғанысты және деректердің жоғары қолжетімділігін қамтамасыз ететін бірнеше сервер. MongoDB Replicaset ішінде жазу мен оқу үшін бір primary түйіні және primary түйінімен синхрондалған әрі жүктемені азайту үшін деректерді оқу мүмкіндігін беретін бір немесе бірнеше secondary түйіндері болады. Primary түйіні істен шыққан жағдайда, secondary түйіндерінің бірі автоматты түрде primary түйіні болып тағайындалады. Жаңа primary түйінін таңдауды жеделдету үшін деректерді қамтымайтын арбитр түйіні арналған. Сонымен қатар, Replicaset артықшылықтарының бірі — кластердің жұмысын тоқтатпай жаңарту мүмкіндігі.
- Барлық үш серверде 27017 порты ашық екеніне көз жеткізіңіз.
- Әр хосттың атауы (
mongo1.testdomain.com,mongo2.testdomain.com,mongoar.testdomain.com) әр серверде белгілі екеніне көз жеткізіңіз. Егер атаулар DNS ішінде көрсетілмесе, әр серверде оларды/еtc/hostsфайлына жазыңыз. Біздің жағдайда:
10.0.0.2 mongo1 mongo1.testdomain.com10.0.0.3 mongo2 mongo2.testdomain.com10.0.0.4 mongoar mongoar.testdomain.com
/etc/mongod.confконфигурациялық файлыныңreplicationсекциясына келесіні қосыңыз:
replication:replSetName: "rs0"security:authorization: enabledclusterAuthMode: x509clusterIpSourceWhitelist:- 10.0.0.2- 10.0.0.3- 10.0.0.4- 127.0.0.1
mongodқызметін қайта іске қосыңыз:
root@mongo1:~# systemctl restart mongod.service
mongoконсоліне кіріп, команданы орындаңыз:
\> rs.initiate(){"info2" : "no configuration specified. Using a default configuration for the set","me" : "mongo1:27017","ok" : 1}rs0:SECONDARY>rs0:PRIMARY>
Replicaset инициализацияланды, түйін primary күйінде тұр.
- Конфигурациялық файлдағы
hostайнымалысындаmongo1:27017мәнінің орнына сертификаттың CommonName мәнін көрсетіңіз:
rs0:PRIMARY> cfg.members[0].host = "mongo1.testdomain.com:27017"mongo1.testdomain.com:27017rs0:PRIMARY> rs.reconfig(cfg){"ok" : 1,"operationTime" : Timestamp(1577365311, 1),"$clusterTime" : {"clusterTime" : Timestamp(1577365311, 1),"signature" : {"hash" : BinData(0,"4b6xDb/6y5tuq9jDjEDjbscYmGk="),"keyId" : NumberLong("6774685910094053378")}}}rs0:PRIMARY>
mongo2серверінде авторизациядан өтіңіз, MongoDB репозиторийінің кілтін импорттаңыз, MongoDB репозиторийін қосыңыз және MongoDB-ді орнатыңыз (мұны қалай жасау керектігін Ubuntu жүйесінде MongoDB орнату және баптау мақаласынан оқыңыз).- Егер
/etc/hostsфайлынmongo1серверінде өзгерткен болсаңыз, ағымдағы серверде де соны қайталаңыз. mongo1серверінен/etc/mongod.confконфигурациялық файлын ағымдағы серверге көшіріңіз, файлдаPEMKeyFile:кілтінің атауын/etc/ssl/mongo1.pemмәніненPEMKeyFile: /etc/ssl/mongo2.pemмәніне ауыстырыңыз.- Ағымдағы серверге
/etc/ssl/mongoCA.pemкілтін көшіріңіз. mongo1серверіндегідей сервер сертификатын шығарыңыз, бұл ретте CommonName ретіндеmongo2.testdomain.comқолданыңыз:
root@mongo2:~# openssl genrsa -out /tmp/mongo2.key 4096root@mongo2:~# openssl req -new -key /tmp/mongo2.key -out /tmp/mongo2.csr...Common Name (e.g. server FQDN or YOUR name) []:mongo2.testdomain.com...root@mongo2:~# openssl x509 -req -in /tmp/mongo2.csr -CA /etc/ssl/mongoCA.pem -CAcreateserial -out /tmp/mongo2.crt -days 10000root@mongo2:~# cat /tmp/mongo2.key /tmp/mongo2.crt > /etc/ssl/mongo2.pemroot@mongo2:~# rm /tmp/mongo2.key /tmp/mongo2.crt /tmp/mongo2.csr
- Егер
var/lib/mongodbдиректориясы бос болмаса, оның ішіндегі барлық файлдарды жойыңыз. mongodсерверін қайта іске қосыңыз және оны автоматты түрде жүктелетін қолданбалар тізіміне қосыңыз.mongo1серверіне кіріп, mongo консоліне өтіңіз.mongo2серверінreplicasetқұрамына қосыңыз:
root@mongo1:~# mongo --ssl --sslPEMKeyFile /etc/ssl/client.pem --sslCAFile /etc/ssl/mongoCA.pem --host mongo1.testdomain.com -u adminMongoDB shell version v4.0.14Enter password:connecting to: mongodb://mongo1.testdomain.com:27017/?gssapiServiceName=mongodbImplicit session: session { "id" : UUID("7a4087c2-470c-48ce-8c8d-af10fb4aa9a7") }MongoDB server version: 4.0.14rs0:PRIMARY> rs.add({ host: "mongo2.testdomain.com:27017" }){"ok" : 1,"operationTime" : Timestamp(1577364817, 1),"$clusterTime" : {"clusterTime" : Timestamp(1577364817, 1),"signature" : {"hash" : BinData(0,"t5nfdP1DMgNaAcUsvYXy2luwNvg="),"keyId" : NumberLong("6774685910094053378")}}}rs0:PRIMARY>
replicasetкүйін тексеріңіз:
rs0:PRIMARY> rs.status(){"set" : "rs0","date" : ISODate("2019-12-26T13:06:09.455Z"),"myState" : 1,"term" : NumberLong(5),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"heartbeatIntervalMillis" : NumberLong(2000),"optimes" : {"lastCommittedOpTime" : {"ts" : Timestamp(1577365562, 1),"t" : NumberLong(5)},"readConcernMajorityOpTime" : {"ts" : Timestamp(1577365562, 1),"t" : NumberLong(5)},"appliedOpTime" : {"ts" : Timestamp(1577365562, 1),"t" : NumberLong(5)},"durableOpTime" : {"ts" : Timestamp(1577365562, 1),"t" : NumberLong(5)}},"lastStableCheckpointTimestamp" : Timestamp(1577365562, 1),"electionCandidateMetrics" : {"lastElectionReason" : "electionTimeout","lastElectionDate" : ISODate("2019-12-26T12:30:20.224Z"),"electionTerm" : NumberLong(5),"lastCommittedOpTimeAtElection" : {"ts" : Timestamp(0, 0),"t" : NumberLong(-1)},"lastSeenOpTimeAtElection" : {"ts" : Timestamp(1577363413, 1),"t" : NumberLong(4)},"numVotesNeeded" : 1,"priorityAtElection" : 1,"electionTimeoutMillis" : NumberLong(10000),"newTermStartDate" : ISODate("2019-12-26T12:30:22.224Z"),"wMajorityWriteAvailabilityDate" : ISODate("2019-12-26T12:30:22.358Z")},"members" : [{"_id" : 0,"name" : "mongo1.testdomain.com:27017","health" : 1,"state" : 1,"stateStr" : "PRIMARY","uptime" : 2154,"optime" : {"ts" : Timestamp(1577365562, 1),"t" : NumberLong(5)},"optimeDate" : ISODate("2019-12-26T13:06:02Z"),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "","electionTime" : Timestamp(1577363420, 1),"electionDate" : ISODate("2019-12-26T12:30:20Z"),"configVersion" : 70500,"self" : true,"lastHeartbeatMessage" : ""},{"_id" : 1,"name" : "mongo2.testdomain.com:27017","health" : 1,"state" : 2,"stateStr" : "SECONDARY","uptime" : 26,"optime" : {"ts" : Timestamp(1577365562, 1),"t" : NumberLong(5)},"optimeDurable" : {"ts" : Timestamp(1577365562, 1),"t" : NumberLong(5)},"optimeDate" : ISODate("2019-12-26T13:06:02Z"),"optimeDurableDate" : ISODate("2019-12-26T13:06:02Z"),"lastHeartbeat" : ISODate("2019-12-26T13:06:08.795Z"),"lastHeartbeatRecv" : ISODate("2019-12-26T13:06:09.139Z"),"pingMs" : NumberLong(1),"lastHeartbeatMessage" : "","syncingTo" : "mongo1.testdomain.com:27017","syncSourceHost" : "mongo1.testdomain.com:27017","syncSourceId" : 0,"infoMessage" : "","configVersion" : 70500}],"ok" : 1,"operationTime" : Timestamp(1577365562, 1),"$clusterTime" : {"clusterTime" : Timestamp(1577365562, 1),"signature" : {"hash" : BinData(0,"9Y9LWPudizuTGUP0+M2wMihAFO8="),"keyId" : NumberLong("6774685910094053378")}}}rs0:PRIMARY>
Көріп тұрғанымыздай, _id=1 болатын екінші түйін Repliset құрамына secondary күйінде қабылданды.
Түйінді replicaset құрамына қосқанда primary түйінінен синхрондау жүреді. Синхрондау аяқталғанша, екінші түйін STARTUP күйінде болады. Негізгі түйінге деректер жазу синхрондауды баяулатады, дегенмен бұл мүмкін сценарий (мысалы, көлемі шамамен 350 ГБ болатын базаға жазу кезінде синхрондау шамамен 14 сағатқа созылды).
Синхрондау аяқталғаннан кейін үшінші серверде (mongoar) екінші сервердегідей (mongo2) әрекеттерді орындаңыз, тек серверді repliset құрамына қосу қадамын қоспағанда:
rs0:PRIMARY> rs.addArb("mongoar.testdomain.com:27017"){"ok" : 1,"operationTime" : Timestamp(1577366355, 1),"$clusterTime" : {"clusterTime" : Timestamp(1577366355, 1),"signature" : {"hash" : BinData(0,"pA6zLoq8JmYCFM2HZVAhr4pvK1A="),"keyId" : NumberLong("6774685910094053378")}}}rs0:PRIMARY>
Repliset күйін тексеріңіз (қысқалық үшін шығыстан елеусіз бөлігі алынып тасталды):
rs0:PRIMARY> rs.status(){"set" : "rs0","date" : ISODate("2019-12-26T13:21:20.710Z"),"myState" : 1,"members" : [{"_id" : 0,"name" : "mongo1.testdomain.com:27017","health" : 1,"state" : 1,"stateStr" : "PRIMARY","uptime" : 3065,},{"_id" : 1,"name" : "mongo2.testdomain.com:27017","health" : 1,"state" : 2,"stateStr" : "SECONDARY","uptime" : 937,},{"_id" : 2,"name" : "mongoar.testdomain.com:27017","health" : 1,"state" : 7,"stateStr" : "ARBITER","uptime" : 125,}}
Нәтижесінде біз primary түйінін, secondary түйінін және arbiter түйінін алдық. Repliset синхрондалған және жұмысқа қабілетті күйде тұр.
Жаңартуды 4.0 нұсқасынан 4.2 нұсқасына көшу мысалында қарастырайық. Ағымдағы деректер сызбасын жұмыс істемейтін күйге әкелуі мүмкін өзгерістерді түсіну үшін құжатпен танысыңыз.
- Ағымдағы деректер жиынымен қолдануға болатын MongoDB нұсқасын шектейтін
feature compatibility versionпараметрін өзгертіңіз. 4.0 нұсқасынан 4.2 нұсқасына жаңарту үшін оны 4.0 мәніне орнатыңыз:
rs0:PRIMARY> db.adminCommand( { setFeatureCompatibilityVersion: "4.0" } ){"ok" : 1,"operationTime" : Timestamp(1577429084, 1),"$clusterTime" : {"clusterTime" : Timestamp(1577429084, 1),"signature" : {"hash" : BinData(0,"mL6lecQQeLB8QkjNqrJIGA+ICiY="),"keyId" : NumberLong("6774685910094053378")}}}
- Нәтижені тексеріңіз:
rs0:PRIMARY> db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } ){"featureCompatibilityVersion" : {"version" : "4.0"},"ok" : 1,"operationTime" : Timestamp(1577429094, 1),"$clusterTime" : {"clusterTime" : Timestamp(1577429094, 1),"signature" : {"hash" : BinData(0,"Mo5HB7K+IVwAivtJ4ZCC4GMKOAk="),"keyId" : NumberLong("6774685910094053378")}}
- Барлық үш серверде MongoDB-дің жаңа нұсқасы бар репозиторийді қосыңыз (бірінші серверге арналған мысал):
root@mongo1:~# wget -qO - https://www.mongodb.org/static/pgp/server-4.2.asc | sudo apt-key add -OKroot@mongo1:~# echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.2.listdeb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.2 multiverseroot@mongo1:~# apt-get update
- Құжаттамаға сәйкес /etc/mongod.conf конфигурациялық файлына
enableMajorityReadConcern: falseопциясын қосыңыз жәнеnet:sslпараметрінnet:tlsпараметріне ауыстырыңыз (арбитрге арналған мысал):
net:port: 27017bindIp: 0.0.0.0tls:mode: requireTLScertificateKeyFile: /etc/ssl/mongoar.pemCAFile: /etc/ssl/mongoCA.pemreplication:replSetName: "rs0"enableMajorityReadConcern: false
- Арбитр түйінін жаңартыңыз:
root@mongoar:~# systemctl stop mongod.serviceroot@mongoar:~# apt-get install -y mongodb-org mongodb-org-mongos mongodb-org-server mongodb-org-shell mongodb-org-toolsroot@mongoar:~# systemctl start mongod.service
rs.status()күйін тексеріңіз. Арбитрдің жұмыс істеп тұрғанына көз жеткізіңіз және қалған екі түйіннің қайсысыsecondaryекенін қараңыз (команда шығысы қысқартылған):
rs0:PRIMARY> rs.status(){"set" : "rs0","date" : ISODate("2019-12-27T06:54:13.228Z"),"myState" : 1,"term" : NumberLong(6),"members" : [{"_id" : 0,"name" : "mongo1.testdomain.com:27017","health" : 1,"state" : 1,"stateStr" : "PRIMARY",},{"_id" : 1,"name" : "mongo2.testdomain.com:27017","health" : 1,"state" : 2,"stateStr" : "SECONDARY",},{"_id" : 2,"name" : "mongoar.testdomain.com:27017","health" : 1,"state" : 7,"stateStr" : "ARBITER",}
- Қазіргі сәтте
mongo2серверіsecondaryболып тұр, онда MongoDB-ді жаңартыңыз:
root@mongo2:~# systemctl stop mongod.serviceroot@mongo2:~# apt-get install -y mongodb-orgThe following packages will be upgraded:mongodb-orgPreparing to unpack .../mongodb-org_4.2.2_amd64.deb ...Unpacking mongodb-org (4.2.2) over (4.0.14) ...Setting up mongodb-org (4.2.2) ...root@mongo2:~# systemctl start mongod.service
rs.status()командасын қарап, түйіннің жұмыс істеп тұрғанына көз жеткізіңіз:
rs0:PRIMARY> rs.status(){"set" : "rs0","date" : ISODate("2019-12-27T07:08:22.025Z"),"myState" : 1,"members" : [{"_id" : 0,"name" : "mongo1.testdomain.com:27017","health" : 1,"state" : 1,"stateStr" : "PRIMARY",},{"_id" : 1,"name" : "mongo2.testdomain.com:27017","health" : 1,"state" : 2,"stateStr" : "SECONDARY",},{"_id" : 2,"name" : "mongoar.testdomain.com:27017","health" : 1,"state" : 7,"stateStr" : "ARBITER",}}
primaryтүйінін күшпен бұрыннан жаңартылған түйінге ауыстырыңыз (біздің жағдайда —mongo2):
rs0:PRIMARY> rs.stepDown()2019-12-27T12:25:10.922+0000 I NETWORK [js] DBClientConnection failed to receive message from mongo1.testdomain.com:27017 - SocketException: stream truncated2019-12-27T12:25:10.923+0000 E QUERY [js] Error: error doing query: failed: network error while attempting to run command 'replSetStepDown' on host 'mongo1.testdomain.com:27017' :DB.prototype.runCommand@src/mongo/shell/db.js:168:1DB.prototype.adminCommand@src/mongo/shell/db.js:186:16rs.stepDown@src/mongo/shell/utils.js:1489:12@(shell):1:12019-12-27T12:25:10.924+0000 I NETWORK [js] trying reconnect to mongo1.testdomain.com:27017 failed2019-12-27T12:25:10.941+0000 I NETWORK [js] reconnect mongo1.testdomain.com:27017 okrs0:SECONDARY>
- Енді mongo1 түйіні
secondaryболды, оны алдыңғысына ұқсас жаңартыңыз. - Жаңартудан кейін
replicasetкүйін тексеріңіз (шығыс қысқартылған):
rs0:SECONDARY> rs.status(){"set" : "rs0","date" : ISODate("2019-12-27T12:30:03.888Z"),"myState" : 2,"term" : NumberLong(6),"syncingTo" : "mongo2.testdomain.com:27017","syncSourceHost" : "mongo2.testdomain.com:27017","syncSourceId" : 1,"heartbeatIntervalMillis" : NumberLong(2000),"majorityVoteCount" : 2,"writeMajorityCount" : 2,"members" : [{"_id" : 0,"name" : "mongo1.testdomain.com:27017","ip" : "89.208.223.162","health" : 1,"state" : 2,"stateStr" : "SECONDARY",},{"_id" : 1,"name" : "mongo2.testdomain.com:27017","ip" : "95.163.212.165","health" : 1,"state" : 1,"stateStr" : "PRIMARY",},{"_id" : 2,"name" : "mongoar.testdomain.com:27017","ip" : "95.163.215.118","health" : 1,"state" : 7,"stateStr" : "ARBITER",}],"ok" : 1,"$clusterTime" : {"clusterTime" : Timestamp(1577449801, 1),"signature" : {"hash" : BinData(0,"cC03fOHq3hLJX5oorqgTGlDuick="),"keyId" : NumberLong("6775081949028417537")}},"operationTime" : Timestamp(1577449801, 1)}rs0:SECONDARY>
Барлығы сәтті орындалды. Егер жаңартуға дейінгі түйіндер ретін сақтау қажет болса, ағымдағы primary түйінінің (mongo2) консоліне кіріп, команданы орындаңыз:
rs.stepDown()
Түйін secondary күйіне өтеді, ал primary түйіні жаңартуға дейінгідей mongo1 болады.
Біз жаңартуды кластерді жұмыстан шығармай, яғни жіксіз орындадық.
Жалғыз MongoDB серверін жаңартқан жағдайда feature compatibility version параметрін жаңартыңыз, mongodb жаңа нұсқасы бар репозиторийді қосыңыз, сервердің конфигурациялық файлын түзетіңіз және жоғарыда сипатталғандай mongodb серверін жаңа нұсқаға жаңартыңыз. Бұл жағдайда серверді тоқтату қажет болады.