Small Asteroid Blog

MSK 업그레이드 다운타임 피하기 RF 조절 본문

카테고리 없음

MSK 업그레이드 다운타임 피하기 RF 조절

작은소행성☄️ 2026. 6. 17. 20:58
728x90

prd에 있는 prd.msk.ingestion.* 토픽들이 전부 RF=1이었다. MSK 버전을 올리려면 브로커가 한 대씩 롤링 재시작되는데, RF=1이면 그동안 파티션이 통째로 오프라인 된다. 브로커가 2대라 RF를 브로커 수만큼, 즉 2로 올려서 업그레이드 중에도 다른 브로커로 리더십이 넘어가게 만들었다. 작업하면서 새로 알게 된 것들, 헷갈렸던 것들을 정리해둔다.

업그레이드 전에 뭘 봐야 하나

실제 화면이 아닌 재구성 이미지

msk 버전 업그레이드 하기 전 사전 점검

  1. 이 클러스터에 붙은 앱/컨슈머 그룹 목록 파악
  2. 각 앱이 쓰는 토픽의 RF/minISR 점검 (제일 중요)
  3. 모든 클라이언트 멀티 브로커 부트스트랩 + retry 설정 확인
  4. 위 "취약 앱" 리스트 추려두기

RF랑 minISR, 헷갈리지 말자

RF(Replication Factor)는 파티션 복사본을 몇 개 둘지다. RF=2면 같은 데이터가 브로커 두 대에 하나씩 있다는 뜻이고, 한 대가 죽어도 나머지 한 대에 복사본이 있으니 소비가 안 끊긴다.

minISR(min.insync.replicas)은 좀 다른 얘기다. acks=all로 쓸 때 최소 몇 개의 복제본이 동기화돼 있어야 쓰기가 성공하는지를 정하는 값이다.

  • minISR=1 → 동기화된 복제본 1개만 있어도 쓰기 성공
  • minISR=2 → 2개 다 동기화돼야 쓰기 성공

기본값/권장값도 정리하면:

  • 순정 Kafka 기본값: default.replication.factor=1 → 자동 생성 토픽은 RF=1로 깔림
  • 프로덕션 권장: RF=3, 최소 2 (내구성 확보용)
  • 제약: RF는 브로커 수를 못 넘음 → 브로커 2대면 최대 RF=2

왜 RF=1이 문제인가

실제 화면이 아닌 재구성 이미지

RF=1이면 파티션 복사본이 딱 한 브로커에만 있다. 그 브로커가 재시작되는 동안엔 백업이 없으니 리더가 될 다른 복제본 자체가 없어서 파티션이 그냥 통째로 죽는다. 

브로커 2대, 파티션 2개면 보통 파티션 0은 브로커1, 파티션 1은 브로커2에 나뉘어 있으니까 브로커1 재시작할 땐 파티션 0이, 브로커2 재시작할 땐 파티션 1이 죽는 식으로 업그레이드 내내 절반씩 번갈아가며 끊기게 된다.

그리고 이게 짧게 끝나는 것도 아니었다. dev에서 브로커당 재시작에 40분 정도 걸렸으니 prd도 비슷하게 잡으면, 파티션 하나가 40분간 오프라인 될 수 있다는 뜻이다. 블립 수준이 아니라 실질적인 outage.

  • 소비: 브로커 복귀하면 밀린 걸 따라잡으니 데이터 손실은 없음. 다만 그 40분 동안은 못 읽음.
  • 생산: 더 위험. 프로듀서 retry나 delivery.timeout.ms(기본 2분) 기준으로 보면 40분은 한참 넘는 시간이라, 그 사이 들어온 cart/order/impression 이벤트가 실패하거나 유실될 수 있음. 추천 파이프라인 입력에 40분짜리 구멍이 나는 셈.

요약: 업그레이드 중 RF=1 파티션이 40분씩 오프라인 → 생산 이벤트 유실 위험 → 사실상 다운타임 확정.

브로커가 2대일 때 조심할 점

브로커가 2대라는 게 은근 중요하다. 한 대가 내려가면 남는 건 딱 1대뿐이니까.

  • 소비 입장: RF=2면 양쪽 브로커에 다 데이터가 있어서, 내려간 브로커가 리더였어도 남은 브로커로 리더십이 넘어가서 소비는 계속된다.
  • 생산 입장: 여기가 함정이었는데, 한 대가 내려가 있는 동안엔 in-sync replica가 1개뿐이다. 이때 minISR이 2로 잡혀있으면 acks=all 쓰기가 그 구간 동안 전부 실패한다. AWS가 2-AZ 구성에서 minISR=1을 권장하는 이유가 이거였다.

그래서 결론은 단순했다. 업그레이드 전에 RF=2, minISR=1인지만 확인하면 된다. 소비만 확인하고 넘어가면 프로듀서 쪽이 막혀있는 걸 놓칠 수 있다는 게 함정이라, 둘 다 봐야 한다.

정리하면:

  • 버전 호환성 에러 확률은 낮음 (dev 성공 사례 있음) ✅
  • 그래도 재시작 블립은 생기니 소비 확인 필요 ✅
  • 진짜 챙길 건 RF=2 / minISR=1 확인 → 이거 하나면 소비/생산 둘 다 무사할 확률 높음

Kafka UI로 되는 것, 안 되는 것

잘 보이는 것

  • RF/ISR 확인이 제일 잘 맞는다. 토픽별로 들어가면 파티션마다 RF랑 ISR 개수가 바로 보여서, RF 낮은 토픽 골라내는 작업은 여기서 하는 게 제일 빠르다. Under-replicated 토픽도 바로 눈에 띈다.
  • 컨슈머 그룹/lag도 볼 수 있어서 어떤 앱이 뭘 소비하는지 인벤토리 잡기 좋고, 업그레이드 중 lag이 튀었다 돌아오는지도 여기서 추적했다.
  • 브로커 상태도 보여서 롤링 재시작 중 브로커가 내려갔다 올라오는 것도 확인 가능하다.

안 보이는 것

  • 프로듀서 쪽 에러율은 Kafka UI가 못 본다. 앱 로그나 CloudWatch, 앱 메트릭에서 따로 봐야 한다.
  • OfflinePartitionsCount, ActiveControllerCount 같은 클러스터 레벨 핵심 지표는 CloudWatch가 훨씬 깔끔하다. UI에서 파티션 뷰로 유추는 되지만 "0인지 아닌지"를 한눈에 보긴 CloudWatch가 낫다.

한 가지 주의할 점은, 업그레이드 중엔 Kafka UI 자신도 결국 브로커에 붙어있는 클라이언트라는 것. 단일 브로커로만 연결돼있으면 그 브로커가 재시작될 때 UI가 잠깐 끊기거나 stale해 보일 수 있다. UI가 이상해 보인다고 클러스터가 문제인 게 아닐 수 있으니, UI 자체 bootstrap 설정도 멀티 브로커로 되어있는지 미리 확인해두면 좋다.

RF 바꾸는 법

topic overview에서 Edit settings 들어가면 RF를 조정할 수 있다. Danger zone에 있는데, 여기서 파티션 수는 절대 건드리면 안 되고 RF 칸만 수정하면 된다.

실제 화면이 아닌 재구성 이미지

 

RF 올리면 생기는 일 / 안 생기는 일

생길 수 있는 것

  1. 디스크 사용량이 대략 두 배로 늘어난다. RF=2가 되면 데이터가 양쪽 브로커에 복제되니까 당연한 결과인데, retention이 3일이라 쌓인 양이 꽤 되니 변경 전에 CloudWatch에서 디스크 여유를 꼭 확인해야 한다. 안 그러면 디스크가 꽉 찰 수 있다.
  2. 기존 데이터를 한 번에 복사하는 작업이라 그 동안 네트워크/CPU/디스크 I/O가 정상 트래픽과 붙는다. 트래픽 몰릴 때 토픽 전체를 한꺼번에 바꾸면 지연이 생길 수 있어서, 트래픽 낮은 시간에 토픽 하나씩 나눠서 진행하는 게 안전하다.
  3. Danger Zone에서 파티션 수 칸을 실수로 건드리지 않게 조심. RF랑 파티션 수는 완전히 다른 얘기다 (아래 참고).

안 생기는 것

  • 데이터 손실 없음 — 기존 데이터는 그대로 두고 복제본만 추가되는 거라서.
  • 순서 안 바뀜 — RF 변경은 파티션 구조 자체를 안 건드린다.
  • 다운타임 없음 — minISR=1이면 복제 진행 중에도 읽기/쓰기 정상 동작한다.

즉 RF 변경 리스크는 결국 디스크랑 일시적인 부하, 이 두 가지로 좁혀진다.

그럼 파티션 수는 왜 늘리면 안 되나

이건 RF랑 완전히 다른 얘기라 따로 적어둔다.

프로듀서가 key를 넣어 보내면 Kafka는 hash(key) % 파티션수로 어느 파티션에 넣을지 정한다. 파티션 수가 바뀌면 같은 key라도 다른 파티션으로 가버린다. 예를 들어 cart 토픽에서 user/session을 key로 쓴다고 하면, 파티션을 늘리기 전엔 user123이 파티션 0으로 갔는데 늘린 후엔 파티션 3으로 가는 식이다.

이러면 문제가 몇 겹으로 생긴다.

  1. 순서 보장 깨짐 — Kafka는 같은 파티션 안에서만 순서를 보장하는데, 과거 이벤트는 파티션 0에 새 이벤트는 파티션 3에 있으면 순서 보장이 끝. cart/order처럼 순서 중요한 데이터면 바로 문제.
  2. key 단위 컨슈머 오동작 — "한 유저 이벤트는 한 파티션에 모인다"를 전제로 짜인 컨슈머(유저별 집계, 추천 파이프라인 등)의 가정이 깨짐. 같은 유저를 서로 다른 컨슈머 인스턴스가 나눠 처리하는 경우도 생김.
  3. 되돌릴 수 없음 — Kafka는 파티션 수를 늘릴 수만 있지 줄일 수는 없음.
  4. 기존 데이터는 재분배 안 됨 — 옛날 데이터는 옛날 분포 그대로, 새 데이터만 늘어난 파티션 수로 분산 → "옛 분포"와 "새 분포"가 영구히 어긋난 채로 남음.

그래서 이번 작업에선 RF만 건드리고 파티션 수는 손도 대지 않았다.

바꾸고 나서 빨간색 뜨는 거, 정상이다

실제 화면이 아닌 재구성 이미지

RF 바꾸면 UI에 빨간 텍스트가 뜨는데 처음 봤을 때는 뭔가 잘못된 줄 알았다. 근데 이건 새로 추가된 복제본이 기존 데이터를 따라잡는(catch-up replication) 중이라 그런 거였다.

예로 보던 토픽 하나는 메시지가 172만 건, 1GB가 넘게 쌓여있었다. RF를 2로 올리면 새 복제본이 이 데이터를 통째로 복사해와야 하니 그 복사가 끝나기 전까진 이렇게 표시된다.

  • URP: 2 (빨강) — Under-Replicated Partitions, 아직 완전히 복제 안 된 파티션이 2개라는 뜻
  • In Sync Replicas: 2 of 4 (빨강) — 전체 복제본 4개(파티션 2개 × RF 2) 중 동기화 끝난 게 2개뿐, 즉 원래 있던 리더 두 개만 동기화 완료 상태
  • 파티션별 Replicas 옆 빨간 숫자 — 그 브로커의 복제본이 아직 따라잡는 중이라는 표시
    • 파티션 0: 브로커2(초록, 리더/원본) — 브로커1(빨강, 새로 받는 중)
    • 파티션 1: 브로커1(초록, 리더/원본) — 브로커2(빨강, 새로 받는 중)

초록은 동기화 완료, 빨강은 아직 따라잡는 중이라는 뜻이니 이 상태 자체는 걱정할 게 아니고, 복사가 끝날 때까지 기다리면 된다.

 

728x90
반응형