• 저희 회사에서 가장 많이 사용하는 구성이라 기존에 직접 설치 메뉴얼 만든 것을 바탕으로 재 구성 해 보았습니다.
  • 현재 대부분 3.4 버전을 많이 사용하고 있으며, 현재 구성하는 것들은 4.2 버전을 사용하고 있습니다.
  • 로그성 DB 위주로 사용하다 보니, 변경을 하더라도 문제 없이 동작을 하였기에 4.2 로 올리고 있는 중입니다.'
    1. Replica Set 이란?
      • 2초마다 Heartbeat하여  Primary와 Secondary 서로 서버 상태를 체크
      • Primary
      • Secondary
        • Readonly - Read 에 대한 분산
        • Primary Server의 데이터를 복제하며, HA 용도
      • Primary 선출 방식
        • 남은 Secondary 노드 들이 vote 투표를 통해 Primary 선출을 진행
        • 선출 방식 중 우선 순위에 의한 선출 방식의 경우 데이터의 동기화 수준 상관없이 우선 순위(priority)에 의해서 선출되는 방식
          • priority 값이 높을 수록 Primary 로 선출이 된다.
        • Arbiter 선출 방식은 데이터를 가지고 있지 않지만, 투표에 참여가 가능한 Arbiter를 이용하여, 선출 시에만 사용되는 서버 (비용 절감 효과)
          • DBA 관리 측면에서 어떤 서버가 Primary가 되는지 알기 쉬움
          • 실제로 구성 시  rs.initiate 명령어(하단 구성에서 찾을 수 있음) 에서 각 node 들에 대해 우선 순위-가중치-priority 에 값을 적용
      • Oplog복제 방식
        • DML 내용들은 모두 OpLog에 가장 먼저 작성
        • Primary 에 먼저 데이터를 적용 후 Oplog에 저장
        • Secondary (각 member들) 에서는 Oplog를 가져와 자신의 DB에 저장
        • oplogSizeMB 옵션으로 크기를 지정할 수 있으며, 복제 중에는 replSetResizeOplog 명령(재시작 필요 없음)을 사용하여 크기를 변경 가능
        • 기존 oplog 구성된 최대 크기에 도달했을 경우 생성이 되지만, v4.4 이후 부터는 시간을 지정 가능하여, 구성 시간이 오래되었을 경우 별도 파일로 생성 가능
        • Slow Oplog  Application
          • v4.2 (4.0.6) 부터 Replica 에서 Oplog를 적용하는 시간이 slow log 시간(slowOpSampleRate) 보다 큰 경우 oplog 항목을 기록 가능
    2. 구성
      • AWS EC2를 사용하기 때문에 그에 맞춰져 있습니다.
      • 구성은 P-S-A 로 진행 하였습니다. (맨 하단에 위치)
      • 인증은 내부 인증을 사용하기 위해, key 파일을 생성하여 진행 하였습니다. (Update Replica Set to Keyfile Authentication 참고)
    3. 레플리카 셋 배포
      1. 추가
        • rs.add({host:"아비터host:port", priority:1, arbiterOnly:true})
        • rs.add({host:"192.168.0.2:27017", priority:1, arbiterOnly:true})
      2. Secondary 추가
        • rs.add({host:"SecondaryHost:port", priority:1})
        • rs.add({host:"192.168.0.2:27017", priority:1})
      3. 확인하는 방법
        • rs.conf()
        • rs.status()
      4. 하나의 서버에 여러개 아비터 띄우는 방법
        1. 아비터 서버에 해당 port / data /log 만 바꿔서 하나씩 mongodb 띄우기
        2. Primary에서 위의 add 명령어 사용해서 추가
        3. 확인

 

 

 


P-S-A 구성하는 방법

  1. Download 및 기본 셋팅  (Primary, Secondary 모두 동일하게 구성)
#mongodb 를 다운 및 압축 풀고 지정 경로에 저장
#필요 시 OS 유저 생성 (user add mongod)
$sudo groupadd mongod
$sudo useradd -g mongod mongod

$ wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-amazon2-4.2.6.tgz
$ tar -xvf mongodb-linux-x86_64-amazon2-4.2.6.tgz
$ mkdir /usr/local/mongodb
$ mv ./mongodb-linux-x86_64-amazon2-4.2.6/* /usr/local/mongodb
$ chown -R mongod:mongod /usr/local/mongodb

# data & log path 생성
$ mkdir -p /data/mongo/data
$ mkdir -p /data/mongo/log
$ chown -R mongod:mongod /data

#mongod 유저로 변경해서 아래내용 모두 진행
# add path
$ vi ~/.bash_profile

    # .bash_profile 
    # path에 아래 내용 추가 수정 진행, 저장

    mongodb=/usr/local/mongodb/bin
    PATH=$PATH:$HOME/.local/bin:$HOME/bin:$mongodb
 
# profile 적용
$  . ~/.bash_profile

# 존재 한다면 config 파일 백업
$ cp /etc/mongod.conf ~/mongod.conf.bak

 

  1. 공통 config 파일 설정 및 key 파일 생성 (Primary, Secondary 모두 동일하게 구성)
#Primary 내용

#key 파일 생성 (mongodb 간 접속을 진행 할 때 필요)

# 해당 key파일은 Secondary에 복사



$ sudo openssl rand -base64 756 > /usr/local/mongodb/mongo_repl.key

$ sudo chown mongod.mongod /usr/local/mongodb/mongo_repl.key

$ sudo chmod 600 /usr/local/mongodb/mongo_repl.key



# 아래 내용 복사

$ cat /usr/local/mongodb/mongo_repl.key

$ chmod 400 /usr/local/mongodb/mongo_repl.key
# Secondary DB 에서 위의 Primary DB에서 생성한 mongo_repl.key 의 내용을 복사 해서 동일한 위치에 붙여 넣고 저장 진행

# Secondary OS

# 복사한 Primary의 key 내용을 붙여 넣기 후 저장

$ vi /usr/local/mongodb/mongo_repl.key

$ chmod 400 /usr/local/mongodb/mongo_repl.key

 

  • Config 설정
# /etc/mongod.conf 수정 

$ sudo touch /etc/mongod.conf

$ sudo chown mongod.mongod /etc/mongod.conf

$ vi /etc/mongod.conf



#기존 내용 삭제 및 해당 내용으로 대체



systemLog:

   destination: file

   path: /data/mongo/log/mongo.log

   logAppend: true

   logRotate: rename



storage:

   engine: wiredTiger

   directoryPerDB: true

   wiredTiger:

      engineConfig:

         journalCompressor: snappy

      collectionConfig:

         blockCompressor: snappy

      indexConfig:

         prefixCompression: true

   dbPath: /data/mongo/data

   journal:

      enabled: true



processManagement:

   fork: true



#replication:

#   replSetName: "replSet"

  

net:

   bindIp: 0.0.0.0

   port: 27017



#아래 내용은 replica 구성이 완료 되면 아래 주석을 풀어주도록 하자

#replication:

#   replSetName: "replSet"

#security:

#  authorization: enabled

#  keyFile: /usr/local/mongodb/mongo_repl.key

 참고로 systemlog 의 quiet 는 권장하지 않는다.

문제 발생 시 에러 내역 트랙킹 하기 힘들기 때문. 

 

systemLog.quiet

Type: boolean

Run mongos or mongod in a quiet mode that attempts to limit the amount of output.

systemLog.quiet is not recommended for production systems as it may make tracking problems during particular connections much more difficult.

 

failIndexKeyTooLong : Index Key중 너무 큰게 있으면 저장되는 것을 fail 시켜라고 하는 파라미터

 

옵션 정리

http://blog.naver.com/PostView.nhn?blogId=theswice&logNo=220763046938&redirect=Dlog&widgetTypeCall=true

 

  1. Primary, Secondary  DB Startup 진행 & User 생성
#Primary, Secondary  모두 진행

#서비스 등록

$ sudo vi /etc/systemd/system/mongodb.service



[Service]

User=mongod

ExecStart=/usr/local/mongodb/bin/mongod --config /etc/mongod.conf



# sudo에 mongod 유저 등록

$ visudo -f /etc/sudoers



#아래 내용 찾아 하단에 추가

## Allow root to run any commands anywhere

root    ALL=(ALL)       ALL

mongod  ALL=(ALL)       ALL

 

  • MongoDB Startup
# Primary, Secondary , Arbiter 모두 진행

# Arbiter의 경우 이미 실행되어 있을 수 있으므로 mongodb가 Start가 되어있는지만 확인

# MongoDB 시작

$ sudo systemctl start mongodb



# MongoDB 상태 확인

$ ps -ef | grep mongod

 

  • MongoDB User 생성
# User 생성

# Primary에서만 진행 



$ mongo



// 인증 DB가 admin

// root 계정 생성 및 게임서버 유저, bi 등에서 생성되는 유저 생성 진행

mongo> use admin

mongo> db.createUser(

    {    

        user: "LKadmin",

        pwd: "test!23",

        roles:[

            { role: "root", db: "admin" }

        ]

    }

)

 

 

  • Replica DB 구성
# Primary 에서만 진행

# ------------------------------------------------------------------------------------------------------

replica 설정 초기화, IP 및 Port 확인 필요!!

# ------------------------------------------------------------------------------------------------------

# replica 설정 초기화



> rs.initiate(

   {

      _id: "replSet",

      version: 1,

      members: [

         { _id: 0, host : "10.95.171.77:27017", priority:3 },

         { _id: 1, host : "10.95.171.78:27017", priority:2 },

         { _id: 2, host : "10.95.171.79:27017", priority:1, arbiterOnly:true }

      ]

   }

)

> rs.status() # stateStr 값이 primary 여야 함

> rs.conf()

> exit

# Primary, Secondary Config 에서 아래 주석내용 풀어준 후 리스타트 진행

# vi /etc/mongod.conf



replication:

   replSetName: "replSet"



security:

  authorization: enabled

  keyFile: /usr/local/mongodb/mongo_repl.key



$  sudo systemctl restart mongodb



# Primary 접속하여 아래와 같이 나오는지 체크

# Primary 접속하여 아래와 같이 나오지 않는다면, replica 설정 초기화를 다시 진행해도 된다.(굳이 mongodb 리스타트 또는 config 주석을 변경 하지 않아도 된다.)



$ mongo admin -u LKadmin -p  

replSet:PRIMARY>



# secondary 접속 테스트

$ mongo admin -u LKadmin -p  



#아래와 같이 나오는지 체크

replSet:SECONDARY>

replSet:SECONDARY> rs.slaveOk()

replSet:SECONDARY> rs.status()

{

        "set" : "replSet",

        "date" : ISODate("2020-05-27T06:05:42.413Z"),

        "myState" : 2,

        "term" : NumberLong(1),

        "syncingTo" : "10.95.171.77:27017",

        "syncSourceHost" : "10.95.171.77:27017",

        "syncSourceId" : 0,

        "heartbeatIntervalMillis" : NumberLong(2000),

        "majorityVoteCount" : 2,

        "writeMajorityCount" : 2,

        "optimes" : {

                "lastCommittedOpTime" : {

                        "ts" : Timestamp(1590559533, 1),

                        "t" : NumberLong(1)

                },

                "lastCommittedWallTime" : ISODate("2020-05-27T06:05:33.008Z"),

                "readConcernMajorityOpTime" : {

                        "ts" : Timestamp(1590559533, 1),

                        "t" : NumberLong(1)

                },

                "readConcernMajorityWallTime" : ISODate("2020-05-27T06:05:33.008Z"),

                "appliedOpTime" : {

                        "ts" : Timestamp(1590559533, 1),

                        "t" : NumberLong(1)

                },

                "durableOpTime" : {

                        "ts" : Timestamp(1590559533, 1),

                        "t" : NumberLong(1)

                },

                "lastAppliedWallTime" : ISODate("2020-05-27T06:05:33.008Z"),

                "lastDurableWallTime" : ISODate("2020-05-27T06:05:33.008Z")

        },

        "lastStableRecoveryTimestamp" : Timestamp(1590559493, 1),

        "lastStableCheckpointTimestamp" : Timestamp(1590559493, 1),

        "members" : [

                {

                        "_id" : 0,

                        "name" : "10.95.171.77:27017",

                        "health" : 1,

                        "state" : 1,

                        "stateStr" : "PRIMARY",

                        "uptime" : 16200,

                        "optime" : {

                                "ts" : Timestamp(1590559533, 1),

                                "t" : NumberLong(1)

                        },

                        "optimeDurable" : {

                                "ts" : Timestamp(1590559533, 1),

                                "t" : NumberLong(1)

                        },

                        "optimeDate" : ISODate("2020-05-27T06:05:33Z"),

                        "optimeDurableDate" : ISODate("2020-05-27T06:05:33Z"),

                        "lastHeartbeat" : ISODate("2020-05-27T06:05:41.267Z"),

                        "lastHeartbeatRecv" : ISODate("2020-05-27T06:05:40.496Z"),

                        "pingMs" : NumberLong(0),

                        "lastHeartbeatMessage" : "",

                        "syncingTo" : "",

                        "syncSourceHost" : "",

                        "syncSourceId" : -1,

                        "infoMessage" : "",

                        "electionTime" : Timestamp(1590543352, 1),

                        "electionDate" : ISODate("2020-05-27T01:35:52Z"),

                        "configVersion" : 1

                },

                {

                        "_id" : 1,

                        "name" : "10.95.171.78:27017",

                        "health" : 1,

                        "state" : 2,

                        "stateStr" : "SECONDARY",

                        "uptime" : 17820,

                        "optime" : {

                                "ts" : Timestamp(1590559533, 1),

                                "t" : NumberLong(1)

                        },

                        "optimeDate" : ISODate("2020-05-27T06:05:33Z"),

                        "syncingTo" : "10.95.171.77:27017",

                        "syncSourceHost" : "10.95.171.77:27017",

                        "syncSourceId" : 0,

                        "infoMessage" : "",

                        "configVersion" : 1,

                        "self" : true,

                        "lastHeartbeatMessage" : ""

                },

                {

                        "_id" : 2,

                        "name" : "10.95.171.79:27017",

                        "health" : 1,

                        "state" : 7,

                        "stateStr" : "ARBITER",

                        "uptime" : 16200,

                        "lastHeartbeat" : ISODate("2020-05-27T06:05:41.266Z"),

                        "lastHeartbeatRecv" : ISODate("2020-05-27T06:05:42.157Z"),

                        "pingMs" : NumberLong(0),

                        "lastHeartbeatMessage" : "",

                        "syncingTo" : "",

                        "syncSourceHost" : "",

                        "syncSourceId" : -1,

                        "infoMessage" : "",

                        "configVersion" : 1

                }

        ],

        "ok" : 1,

        "$clusterTime" : {

                "clusterTime" : Timestamp(1590559533, 1),

                "signature" : {

                        "hash" : BinData(0,"W5JmQNO1ECoqd0kldQ26bHHzspk="),

                        "keyId" : NumberLong("6831331679710216195")

                }

        },

        "operationTime" : Timestamp(1590559533, 1)

}

 

 

완료 한 번씩 로그 체크는 진행

반응형

+ Recent posts