MongoDB Replica set 설정

이 글은 CentOS 7.x 이상, MongoDB v4.4.x 버전 사용을 전제로 합니다

시작하기 앞서


이 글의 목표는 원래 정상적으로 구동하던 기존 DB (이하 Primary Node)에 새로운 복제본 (이하 Secondary Node)을 추가하여 동기화를 최종적인 목적으로 합니다.

두 개의 복제본을 생성하여 복제본 상호간의 데이터와 Heartbeat를 공유해 안정적인 서비스를 지향하는 P-S-S 구성 또는 Heartbeat는 공유하지만 실질적으로는 데이터를 저장하지 않아 비교적 가볍게 운용이 가능한 Arbiter Node를 두번째 복제본 대신 사용하는 P-S-A 구성으로 진행할 수도 있습니다.

P-S-S 구성

P-S-S 구성

P-S-A 구성

P-S-A 구성

Secondary Node와 Arbiter Node는 Primary Node가 사용불가 상태인 경우 투표를 통해 새로운 Primary Node를 선출해 사용하게 됩니다. 이 때 Arbiter Node는 데이터를 저장하지 않는 Node이므로 실질적으로는 투표만 하는 Node입니다

투표는 과반수 이상이 참여해야하므로 가능한 한 홀수로 구성하는 것이 좋습니다

준비물


  • 각각의 MongoDB 서버

    각각의 노드는 주 버전이 같아야 합니다

  • 네트워크 확인

    라우터, 스위치 등에서 각각의 노드간 연결을 할 수 있도록 포트를 열어두어야 합니다 (예: MongoDB 기본 포트인 27017 포트)

주의사항


  • 시스템 서비스를 이용한 MongoDB 서버 구동을 사용하지 않습니다

      # MongoDB Deamon 종료
      systemctl stop mongod
    
      # MongoDB 시스템 서비스 비활성화
      systemctl disable mongod
  • 가급적이면 도메인을 사용하는 것이 좋습니다

      ...
    
      # hosts 내용은 서버마다 다를 수 있습니다
    
      #Primary Node가 속한 서버
      127.0.0.1 mongo-primary mongo-secondary mongo-arbiter
    
      # 외부 서버 주소
      10.0.0.1 external-secondary 
      10.0.0.2 external-arbiter

작업 시작


하나의 서버에서 P-S-A 구성을 사용하는 경우

  1. 필요한 파일과 디렉토리를 생성합니다

     cd ~
    
     # DB 디렉토리 생성
     mkdir .db
     cd .db
    
     # 각 노드별 데이터가 저장될 디렉토리 생성
     mkdir ./primary
     mkdir ./secondary
     mkdir ./arbiter
    
     # 로그가 저장될 디렉토리 생성
     mkdir ./logs
     touch ./logs/primary.log
     touch ./logs/secondary.log
     touch ./logs/arbiter.log
    
     # 원본 config 파일을 DB 디렉토리로 복제
     cp /etc/mongod.conf ./primary.conf
     cp /etc/mongod.conf ./secondary.conf
     cp /etc/mongod.conf ./arbiter.conf
  2. 각 Node에서 사용할 인증키를 생성합니다

     openssl rand -base64 756 > ~/.db/.key
     chmod 400 ~/.db/.key
  3. 모든 .conf 파일을 수정합니다 (primary.conf, secondary.conf, arbiter.conf)

     ...
     systemLog:
       destination: file
       logAppend: true
       # Node에 맞게 수정 (예: /root/.db/logs/primary.log) 
       path: /var/log/mongodb/mongod.log
    
     storage:
       # Node에 맞게 수정 (예:/root/.db/primary)
       dbPath: /var/lib/mongo
       journal:
         enabled: true
    
     # network interfaces
     net:
       # 포트 입력  (예: Primary = 27017, Secondary = 27018, Arbiter = 27019)
       port: 27017
       # 접근 가능한 IP 입력 (상황에 따라 다르게 적용해야할 수 있습니다)
       bindIp: 0.0.0.0
    
     security:
       # 인증 활성화
       authorization: enabled 
    
       # 키 파일로 인증 활성화
       clusterAuthMode: keyFile 
       # 키 파일 경로 입력
       keyFile: /root/.db/.key
    
     #operationProfiling:
    
     replication:
       # 복제본 세트명 입력 (모든 Node의 replSetName은 같아야 합니다)
       replSetName: "rs0"
    
     ...
  4. 모든 MongoDB Node를 구동합니다

     mongod --config ./primary.conf --fork
     mongod --config ./secondary.conf --fork
     mongod --config ./arbiter.conf --fork
  5. MongoDB Shell를 이용해 Primary Node에 접근하여 로그인한 후 복제본 세트를 초기화합니다

     # MongoDB Shell을 이용, Primary Node에 접근
     mongo --port 27017
     // 복제본 세트 설정값
     cfg = {
       _id: "rs0",
       version: 1,
       members: [
           { _id: 0, host: "mongo-primary:27017", priority: 2},
             { _id: 1, host: "mongo-secondary:27018" },
             { _id: 2, host: "mongo-arbiter:27019", arbiterOnly: true },
         ]
     }
    
     # replica set 초기화
     rs.initiate(cfg)
    • 도메인 네임 설정의 경우 /etc/hosts 파일을 열고 아래와 같이 추가합니다

        ...
      
        # for MongoDB replica set
        # 'mongo'와 같이 사용해도 무방하나 추후 확장 가능성을 고려해 작성
        127.0.0.1 mongo-primary mongo-secondary mongo-arbiter
  1. MongoDB Shell에서 모든 Node가 잘 연결되었는지 확인합니다

     rs.status()

두개의 서버에서 P-S-A 구성을 사용하는 경우


  1. 필요한 파일과 디렉토리를 생성합니다

    • 메인 서버 (Primary Node)

        cd ~
      
        # DB 디렉토리 생성
        mkdir .db
        cd .db
      
        # 각 노드별 데이터가 저장될 디렉토리 생성
        mkdir ./primary
      
        # 로그가 저장될 디렉토리 생성
        mkdir ./logs
        touch ./logs/primary.log
      
        # 원본 config 파일을 DB 디렉토리로 복제
        cp /etc/mongod.conf ./primary.conf
    • 외부 서버 (Secondary Node, Arbiter Node)

        cd ~
      
        # DB 디렉토리 생성
        mkdir .db
        cd .db
      
        # 각 노드별 데이터가 저장될 디렉토리 생성
        mkdir ./secondary
        mkdir ./arbiter
      
        # 로그가 저장될 디렉토리 생성
        mkdir ./logs
        touch ./logs/secondary.log
        touch ./logs/arbiter.log
      
        # 원본 config 파일을 DB 디렉토리로 복제
        cp /etc/mongod.conf ./secondary.conf
        cp /etc/mongod.conf ./arbiter.conf
  2. 메인 서버에서 각 Node에서 사용할 인증키를 생성합니다

     openssl rand -base64 756 > ~/.db/.key
     chmod 400 ~/.db/.key
  3. rsync 등을 이용하여 외부 서버로 복사합니다

     rsync -avh {계정명}@{메인 서버 주소}:{메인 서버내 인증 키 파일 경로} {로컬 경로}
  4. 모든 .conf 파일을 수정합니다 (primary.conf, secondary.conf, arbiter.conf)

     ...
     systemLog:
       destination: file
       logAppend: true
         # Node에 맞게 수정 (예: /root/.db/logs/primary.log) 
       path: /var/log/mongodb/mongod.log
    
     storage:
       # Node에 맞게 수정 (예:/root/.db/primary)
       dbPath: /var/lib/mongo
       journal:
         enabled: true
    
     # network interfaces
     net:
       # 포트 입력  (예: Primary = 27017, Secondary = 27018, Arbiter = 27019)#
       port: 27017
       # 접근 가능한 IP 입력 (상황에 따라 다르게 적용해야할 수 있습니다)
       bindIp: 0.0.0.0
    
     security:
       # 인증 활성화
       authorization: enabled 
    
       # 키 파일로 인증 활성화
       clusterAuthMode: keyFile 
       # 키 파일 경로 입력
       keyFile: /root/.db/.key
    
     #operationProfiling:
    
     replication:
       # 복제본 세트명 입력 (모든 Node의 replSetName은 같아야 합니다)
       replSetName: "rs0"
    
     ...
  5. 모든 MongoDB Node를 구동합니다

    • 메인 서버

        mongod --config ./primary.conf --fork
    • 외부 서버

        mongod --config ./secondary.conf --fork
        mongod --config ./arbiter.conf --fork
  1. MongoDB Shell를 이용해 Primary Node에 접근하여 로그인한 후 복제본 세트를 초기화합니다

     # MongoDB Shell을 이용, Primary Node에 접근
     mongo --port 27017
     // 복제본 세트 설정값
     cfg = {
       _id: "rs0",
       version: 1,
       members: [
           { _id: 0, host: "mongo-primary:27017", priority: 2},
             { _id: 1, host: "mongo-secondary:27018" },
             { _id: 2, host: "mongo-arbiter:27019", arbiterOnly: true },
         ]
     }
    
     # replica set 초기화
     rs.initiate(cfg)
    • 도메인 네임 설정의 경우 /etc/hosts 파일을 열고 아래와 같이 추가합니다

        ...
      
        # for MongoDB replica set
        127.0.0.1 mongo-primary
        {외부 서버 주소} mongo-secondary mongo-arbiter
  2. MongoDB Shell에서 모든 Node가 잘 연결되었는지 확인합니다

    rs.status()

명령어


  • rs.add()

    Secondary Node 추가

  • rs.conf()

    현재 replica set의 설정값 확인

  • rs.status()

    현재 replica set의 상태 확인

오류 해결


rs.initiate() 실행 중 발생하는 오류

{
        "ok" : 0,
        "errmsg" : "No host described in new configuration with {version: 1, term: 0} for replica set rs0 maps to this node",
        "code" : 93,
        "codeName" : "InvalidReplicaSetConfig"
}
  • hostname이 없는 경우

      # /etc/hosts 파일을 수정한다
    
      127.0.0.1    localhost localhost.localdomain ... [hostname 입력]