ReplicaSet은 MongoDB의 고가용성 시스템으로 동일한 데이터를 갖는 mongod
프로세스들의 그룹으로 구성됩니다. 이는 1개의 Primary 멤버와 데이터 복사본을 갖는 다수의 Secondary 멤버들로 이루어집니다.
최근 공인 IP로 운영 중인 ReplicaSet을 사설 IP로 변경하는 업무를 진행했습니다. MongoDB를 Standalone하게 운영할 경우에는 문제가되지 않지만, ReplicaSet으로 운영할 경우에는 아래의 방법 중 하나로 ReplicaSet의 호스트명을 마이그레이션해야 합니다.
1번은 서비스 중단 없이 호스트명을 변경하는 것이 가능하지만, 시간이 오래 걸리고 애플리케이션에서 다운 타임이 발생할 수 있습니다. 2번은 서비스 다운 타임이 발생하지만 빠르게 작업을 진행할 수 있습니다. 운영하는 환경에 적합한 방법을 사용하면 됩니다. 저는 2번에 전체 호스트명을 동시에 변경하는 방법으로 진행했습니다.
호스트명 변경은 local
데이터 베이스의 system.replset
컬렉션을 읽어서 업데이트한 후 ReplicaSet을 재시작하는 방법으로 진행됩니다. 왜 ReplicaSet을 중지한 상태로 진행해야하는지 까지는 정확히 알지 못했는데요, 아마도 ReplicaSet을 운영 중인 상태에서 호스트명을 변경할 경우 ReplicaSet 네트워크가 정상적으로 동작하지 않는 상황에 놓이는 것이 아닌가하고 추측하고 있습니다.
$ mongo > use admin > db.shutdownServer({force:true}) > exit
호스트명을 변경하기 위해서 각 멤버를 재시작합니다. 이때 사용하는 포트번호를 ReplicaSet을 운영하는 포트와 다르게하여 ReplicaSet 멤버가 아닌 Standalone하게 실행을 합니다. 이렇게 하면 클라이언트가 접속을 할 수 없어서 ReplicaSet의 데이터 변경을 막을 수 있습니다.
$ mongod --dbpath <데이터경로> --port 37017 --bind_ip localhost
모든 멤버에 접속하여 system.replset
컬렉션에 저장된 ReplicaSet 설정을 조회합니다. 조회 결과에서 호스트 정보를 수정한 후 다시 system.replset
컬렉션에 업데이트 합니다. 호스트명을 수정하면 mongod
를 종료합니다.
$ mongo --port 37017 > use local > cfg = db.system.replset.findOne( { "_id": "ReplicaSet이름" } ) > cfg.members[0].host = "newhost01:27017" > cfg.members[1].host = "newhost02:27017" > cfg.members[2].host = "newhost03:27017" > db.system.replset.update( { "_id": "ReplicaSet이름" } , cfg ) > use admin > db.shutdownServer({force:true}) > exit
호스트명을 변경했으므로 다시 ReplicaSet을 실행해주면 작업이 완료됩니다.
$ mongod --dbpath <데이터경로> --port 27017 --replSet <ReplicaSet이름> --bind_ip 0.0.0.0 $ mongo --port 27017 > rs.status() { "_id" : "ReplicaSet이름", "version" : 4, "protocolVersion" : NumberLong(1), "writeConcernMajorityJournalDefault" : true, "members" : [ { "_id" : 0, "host" : "newhost01:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 1, "host" : "newhost02:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 2, "host" : "newhost01:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 } ], "settings" : { "chainingAllowed" : true, "heartbeatIntervalMillis" : 2000, "heartbeatTimeoutSecs" : 10, "electionTimeoutMillis" : 10000, "catchUpTimeoutMillis" : -1, "catchUpTakeoverDelayMillis" : 30000, "getLastErrorModes" : { }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 }, "replicaSetId" : ObjectId("5c9c22975a50fc8eed83f2fa") } }
참고자료 : https://docs.mongodb.com/manual/tutorial/change-hostnames-in-a-replica-set/