[小ネタ] MongoDB レプリカセットノードを切り離しスタンドアローンで起動する
こんにちは、菊池です。
今回は小ネタです。以前、MongoDBのレプリカセットパターンを紹介しました。
MongoDBのレプリカセットでは、AZ障害などにより過半数のノードで障害が発生すると、残存ノードでプライマリへの昇格が不可能になるため、書き込みを受け付けられなくなります。
MongoDB Enterprise s0:SECONDARY> rs.status() { "set" : "s0", "date" : ISODate("2017-07-31T10:01:57.956Z"), "myState" : 2, "term" : NumberLong(13), "heartbeatIntervalMillis" : NumberLong(2000), "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "appliedOpTime" : { "ts" : Timestamp(1501495292, 1), "t" : NumberLong(13) }, "durableOpTime" : { "ts" : Timestamp(1501495292, 1), "t" : NumberLong(13) } }, "members" : [ { "_id" : 0, "name" : "mongo0:27017", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 128, "optime" : { "ts" : Timestamp(1501495292, 1), "t" : NumberLong(13) }, "optimeDate" : ISODate("2017-07-31T10:01:32Z"), "infoMessage" : "could not find member to sync from", "configVersion" : 7, "self" : true }, { "_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("2017-07-31T10:01:57.618Z"), "lastHeartbeatRecv" : ISODate("2017-07-31T10:01:27.077Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "Connection refused", "configVersion" : -1 }, { "_id" : 2, "name" : "mongo2: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("2017-07-31T10:01:57.642Z"), "lastHeartbeatRecv" : ISODate("2017-07-31T10:01:05.867Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "Connection refused", "configVersion" : -1 } ], "ok" : 1 }
ここの状況で書き込みを可能にするためには、残存ノードのうち1つをレプリカセットから切り離し、スタンドアローンで起動します。
設定ファイルのレプリカセットの部分をコメントアウトし、再起動します。
$ cat /etc/mongod.conf net: port: 27017 systemLog: destination: file logAppend: true path: /var/log/mongodb/mongod.log storage: dbPath: /data processManagement: fork: true pidFilePath: /var/run/mongodb/mongod.pid #replication: # replSetName: s0
$ sudo systemctl restart mongod
この状態では、書き込みが可能になります。
$ mongo MongoDB shell version v3.4.6 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.6 MongoDB Enterprise > db.user.insert({name:"hoge"}); WriteResult({ "nInserted" : 1 })
まとめ
以上です。
二重障害などでPrimary昇格が不能になった際に、緊急でサービスを復旧させる必要がある場合にはこのような手段もあります。ただし、分断された過半数側のノードでも書き込みが発生してしまうと、不整合な状態となりますので注意しましょう。