-
MongoDB ReplicaSet이 LB를 타지 않고 내부 포트로 붙던 문제카테고리 없음 2025. 10. 16. 00:47
1️⃣ 배경
K8s asis 클러스터에서 MongoDB Replica Set을 운영중이었다.
tobe 클러스터로 이관이 필요하였는데, 하필 신규 클러스터가 Mongo VM의 Tenant와 달라서 LB를 통해 접근이 필요했다.

2️⃣ 문제 발생
K8s tobe 클러스터에 LB 주소를 지정했는데 Time out을 리턴함
로그를 자세히 살펴보니 실제 연결이 LB가 아닌 몽고DB IP로 직접 붙으려는 현상을 발견함
커넥션 정보
# mongodb # 10.x.x.x는 LB 주소 mongodb.uri=mongodb://10.x.x.x:22720,10.x.x.x:22721,10.x.x.x:22722에러 로그
# LB가 클라이언트 뷰에 추가됨 Adding discovered server 10.x.x.x:22720 to client viw of cluster # Canonical address와 매칭되지 않는다고 삭제됨 # 172.x.x.x는 MongoDB IP Canonical address 172.x.x.x:27017 does not match server address. Removing 10.x.x.x:22720 from client view of cluster # 이후 계속 MongoDB IP로 접속을 시도함-> 어플리케이션에 LB 주소만 지정했는데도 뒷단의 MongoDB IP로 직접 붙으려고 함
-> 뒷단의 IP를 어떻게 알았는지도 의아함..;
3️⃣ 원인 분석
MongoDB에서 rs.conf() 명령어를 확인하니 하기와 같은 설정이 있음
{ _id: "rs0", members: [ { _id: 0, host: "172.x.x.1:27017" }, { _id: 1, host: "172.x.x.2:27017" }, { _id: 2, host: "172.x.x.3:27017" } ] }- ReplicaSet 구성을 확인해보니 host 값이 모두 MongoDB IP + 27017로 되어 있었음 (이미 Mongo 안에.. MongoDB 서버들이 나열되어 있었다.)
- 클라이언트가 LB로 접속하더라도, handshake 이후에 내부적으로 이 host 목록과 비교함
- 이 host 목록과 비교하여 일치하지 않으면 클라이언트 뷰에서 삭제 시키고, 이미 알고 있는 (canonical address)와만 통신을 시도한다.
- 기존 MongoDB IP와 통신을 시도하므로 (LB를 통하지 않으므로) 실패 함
- (저 목록은 왜 있어가지고 맘대로 host 비교하고 삭제시키나 찾아보니,
레플리카 셋은 서로의 주소를 알고 있어야 해서 필요하다고 한다. 소스:구글링)
- (저 목록은 왜 있어가지고 맘대로 host 비교하고 삭제시키나 찾아보니,
4️⃣ 해결 방법
ReplicaSet의 멤버 host를 LB 주소 기반으로 변경
rs.reconfig({ _id: "rs0", members: [ { _id: 0, host: "10.x.x.x:27720" }, { _id: 1, host: "10.x.x.x:27721" }, { _id: 2, host: "10.x.x.x:27722" } ] }): 사실 완전한 해결방법은 아니다.
이렇게 되면 asis 클러스터의 pod도 기존처럼 직접 접근이 아닌, LB를 통해서 접근되게 된다.
(왜냐하면 handshake 후에 '당신이 접속해야 할 곳은 LB주소입니다' 라고 알려주기 때문)
하지만 나는 이관을 위해 임시로 1. tobe에서는 LB를 통한 접근, 2. asis에서는 직접 접근이 동시에 가능해야했고,
asis app도 LB와 통신이 된다는 것을 확인하고 나서 모든 MongoDB로의 통신을 LB를 거치도록 바꾼 것이다.
5️⃣ 배운 점
- Mongo DB는 요청 주는대로 받는 수동적인 존재라고 생각했는데, 나름 자기가 알고 있는 정보도 있고 아무 요청이나 안받아주는 능동적인 존재라고는 상상도 못했다.
- Replica Set이 없던 개발계에서는 발생하지 않았는데, Replica Set이 있는 검증계에서만 발생한 일이어서 이 부분을 유심히 보았다. 문제에 근접하는 방식은 마음에 들었고 예전보다 나아진 것 같다.
- GPT와 씨름하고 있었다가 팀 방에 메아리쳤는데 관련 경험 있던 책임님이 소스를 알려주셨다. 역시 집단 지성이 최고
- 내부 주소(MongoDB IP)를 LB IP로 덮어쓸 생각을 못했다. 직접 접근도 되어야 하고 LB도 통해야하니까 6개가 필요한 것 아닌가? 생각했다. 그런데 GPT가 동일한 몽고 프로세스를 가리키는 호스트를 둘 씩 만드는 것에 대해서 기겁했다. 생각해보니 asis도 LB랑 통신이 되어서 LB 주소 3개로만 덮어써도 문제가 없는데... 그림을 그리며 더 명확해졌다. 앞으로도 그림을 많이 그리자! (그림 좋아하는 사심 약간 넣어봄)