고가용성(HA)은 한 클러스터 안에서 브로커 한두 대가 죽어도 서비스가 이어지게 하는 것이다. 재해복구(DR)는 데이터센터나 리전 전체가 사라졌을 때 다른 클러스터로 넘어가는 것이다. 요구 사항과 수단이 다르므로 섞어 설계하면 둘 다 어정쩡해진다.
복제가 전부다. 파티션마다 복제본을 여러 브로커에 두고, 리더가 죽으면 ISR 안의 복제본이 리더를 이어받는다.
| 설정 | 권장 | 이유 |
|---|---|---|
replication.factor |
3 | 한 대가 죽어도 두 벌이 남는다 |
min.insync.replicas |
2 | 복제본 두 벌에 기록돼야 쓰기를 인정한다 |
프로듀서 acks |
all |
위 조건과 짝을 이룬다 |
unclean.leader.election.enable |
false |
뒤처진 복제본을 리더로 뽑지 않는다. 유실 방지 |
broker.rack |
랙·AZ 이름 | 복제본을 서로 다른 장애 도메인에 배치한다 |
min.insync.replicas 를 복제 계수와 같게 두면(3/3) 한 대만 빠져도 쓰기가 멈춘다. 반드시 복제 계수보다 작게 둔다.
broker.rack 을 설정하면 새 토픽을 만들 때 복제본이 랙에 흩어지게 배치된다. 이미 만들어진 토픽에는 소급되지 않으므로 재배치가 필요하다.
컨트롤러 쿼럼도 홀수로 둔다. KRaft 컨트롤러는 3 대 또는 5 대가 표준이며, 과반이 살아 있어야 메타데이터 쓰기가 가능하다.
한 클러스터를 여러 데이터센터에 걸쳐 늘리는 방식(stretch cluster)은 구간 지연이 매우 낮을 때만 성립한다. 지연이 수 밀리초를 넘으면 복제 지연과 컨트롤러 선출이 불안정해진다. 일반적인 원격지 구성에는 맞지 않는다.
별도 클러스터를 두고 토픽을 복제한다. 아파치 배포본에 포함된 도구는 MirrorMaker 2 이며 Kafka Connect 위에서 동작한다.
MirrorMaker 2 는 토픽 데이터뿐 아니라 토픽 설정, ACL, 컨슈머 그룹 오프셋까지 옮길 수 있다. 다만 두 클러스터의 오프셋 값 자체는 같지 않으므로, 넘어간 뒤 어디서부터 읽을지는 오프셋 변환 정보(checkpoints)를 이용해 정한다.
복제 방향과 이름 규칙을 먼저 정한다. 기본 정책은 원본 클러스터 이름을 접두사로 붙여(dc1.order-events) 순환 복제를 막는다. 이름을 그대로 유지하는 정책도 쓸 수 있으나 양방향 구성에서는 위험하다.
| 구성 | 성격 |
|---|---|
| 능동-수동 | 평소에는 한쪽만 쓰고 다른 쪽은 받기만 한다. 전환 시 컨슈머를 옮긴다 |
| 능동-능동 | 양쪽에서 쓰고 서로 복제한다. 접두사 정책과 중복 처리 설계가 필요하다 |
복제는 비동기이므로 전환 시점의 유실을 0 으로 만들 수 없다. 얼마까지 감수할지(RPO)를 먼저 정하고, 복제 지연을 그 기준으로 감시한다.
Confluent 의 Cluster Linking 처럼 오프셋까지 보존하는 상용 기능도 있으나 아파치 배포본에는 없다.
BS=broker01.example.com:9092
kafka-topics.sh --bootstrap-server $BS --describe --under-replicated-partitions
kafka-topics.sh --bootstrap-server $BS --describe --unavailable-partitions
kafka-configs.sh --bootstrap-server $BS --entity-type brokers --entity-default --describe
kafka-metadata-quorum.sh --bootstrap-server $BS describe --status
평시에 under-replicated 파티션이 0 이어야 한다. 0 이 아닌 상태를 방치하면 실제 장애 때 복제본이 모자라 유실로 이어진다.
재해복구 구성은 평시 지연 지표와 정기 전환 훈련이 있어야 의미가 있다. 구성만 해 두고 훈련하지 않으면 전환 순간에 절차를 몰라 시간을 잃는다.