멀티클러스터가 필요한 이유와 4가지 아키텍처 패턴
Kafka: The Definitive Guide (O'Reilly, 2017, 1st Edition) — Neha Narkhede, Gwen Shapira, Todd Palino Chapter 8: Cross-Cluster Data Mirroring — Use Cases of Cross-Cluster Mirroring / Multicluster Architectures (pp.157-170)
클러스터를 여러 개 운영해야 하는 상황(지역·중앙 클러스터, 재해 복구, 클라우드 마이그레이션)과, 그 요구를 구현하는 네 가지 아키텍처 패턴을 다룬다. 크로스 데이터센터 통신은 높은 지연·제한된 대역폭·높은 비용이라는 제약을 갖고, Kafka 자체는 단일 데이터센터를 전제로 설계·튜닝되었다는 사실이 모든 패턴의 트레이드오프를 결정한다. Hub-and-Spokes, Active-Active, Active-Standby, Stretch Cluster를 각각의 이득과 한계로 비교한다.
replication과 mirroring — 용어부터 구분한다
대부분의 데이터베이스에서 서버 간에 데이터를 계속 복사하는 것을 replication이라고 부른다. 그런데 Kafka에서는 이미 '리플리케이션'이라는 말을 같은 클러스터에 속한 노드들 사이의 데이터 이동을 가리키는 데 쓰고 있다. 그래서 이 책은 클러스터와 클러스터 사이의 복사를 mirroring(미러링)이라고 부른다. Apache Kafka에 내장된 크로스 클러스터 복제 도구의 이름이 MirrorMaker인 것도 이 때문이다.
클러스터가 여러 개라고 해서 항상 미러링이 필요한 것은 아니다. 부서가 다르거나 유스케이스가 달라서 완전히 분리된 클러스터라면, 한쪽에서 다른 쪽으로 데이터를 복사할 이유가 없다. 서로 다른 SLA나 워크로드를 하나의 클러스터로 튜닝하기 어렵거나 보안 요구사항이 다른 경우가 여기 해당한다. 이런 경우는 어렵지 않다. 그냥 단일 클러스터 운영을 여러 번 하는 것과 같다.
문제는 클러스터들이 서로 의존적이어서 운영자가 클러스터 사이에서 데이터를 계속 복사해 줘야 하는 경우다. 이 장이 다루는 것이 바로 그 상황이다.
핵심 포인트
- 같은 클러스터 내 노드 간 데이터 이동 = replication, 클러스터 간 복사 = mirroring
- Apache Kafka 내장 크로스 클러스터 복제기의 이름은 MirrorMaker
- 서로 독립적인 여러 클러스터는 단일 클러스터 운영의 반복일 뿐, 이 장의 주제가 아니다
크로스 클러스터 미러링이 필요한 세 가지 상황
책은 미러링이 필요한 대표적인 유스케이스를 세 가지로 정리한다.
지역 클러스터와 중앙 클러스터(Regional and central clusters). 여러 지역·도시·대륙에 데이터센터가 있고 각 데이터센터가 자체 Kafka 클러스터를 갖는 경우다. 어떤 애플리케이션은 로컬 클러스터만 보면 되지만, 어떤 애플리케이션은 여러 데이터센터의 데이터가 함께 필요하다. 고전적인 예는 수요·공급에 따라 가격을 조정하는 회사다. 각 도시의 데이터센터가 지역의 수요·공급 정보를 모아 가격을 조정하고, 이 정보 전체를 중앙 클러스터로 미러링하면 비즈니스 분석가가 전사 매출 리포트를 돌릴 수 있다.
이중화(Redundancy, DR). 애플리케이션은 하나의 클러스터에서만 동작하고 다른 지역의 데이터가 필요하지도 않지만, 클러스터 전체가 통째로 사용 불가능해지는 상황이 걱정되는 경우다. 첫 번째 클러스터의 모든 데이터를 가진 두 번째 클러스터를 두고, 비상 시 애플리케이션을 그쪽으로 돌려 평소처럼 계속 운영하려는 것이다.
클라우드 마이그레이션(Cloud migrations). 온프레미스 데이터센터와 클라우드 제공자를 동시에 쓰는 회사가 많다. 이중화를 위해 여러 리전에서 돌리기도 하고, 여러 클라우드 제공자를 쓰기도 한다. 이 경우 온프레미스 데이터센터마다, 클라우드 리전마다 Kafka 클러스터를 두고 데이터센터 간 데이터를 효율적으로 옮기는 데 사용한다. 예를 들어 클라우드에 새 애플리케이션을 배포했는데 그 데이터가 온프레미스 DB에서 갱신된다면, Kafka Connect로 DB 변경을 로컬 Kafka 클러스터에 담고 그 변경분을 클라우드 클러스터로 미러링한다. 이렇게 하면 데이터센터 간 트래픽 비용을 통제하면서 트래픽의 거버넌스와 보안도 개선된다.
핵심 포인트
- 지역/중앙 클러스터: 각 지역에서 생산한 데이터를 중앙으로 모아 전사 분석
- 이중화(DR): 클러스터 전체 장애에 대비한 두 번째 클러스터
- 클라우드 마이그레이션: 온프레미스 ↔ 클라우드 리전 간 데이터 이동 비용·보안 통제
- DB 변경은 Kafka Connect로 로컬 클러스터에 담고, 그 뒤 미러링으로 옮기는 것이 전형적 패턴
크로스 데이터센터 통신의 현실과 3가지 설계 원칙
아키텍처를 보기 전에, 왜 이 해법들이 필요 이상으로 복잡해 보이는지 이해해야 한다. 이유는 특정한 네트워크 조건 아래에서의 트레이드오프이기 때문이다.
높은 지연(High latencies). 두 Kafka 클러스터 사이의 통신 지연은 거리와 네트워크 홉 수가 늘어날수록 커진다.
제한된 대역폭(Limited bandwidth). WAN은 보통 단일 데이터센터 내부보다 가용 대역폭이 훨씬 낮고, 그 가용 대역폭이 분 단위로 변동한다. 게다가 지연이 높으면 있는 대역폭조차 다 쓰기 어려워진다.
높은 비용(Higher costs). 온프레미스든 클라우드든 클러스터 간 통신은 비용이 더 든다. 대역폭이 제한적이고 추가 비용이 감당하기 힘들 정도로 비싸기도 하고, 데이터센터·리전·클라우드 간 전송에 벤더가 요금을 매기기 때문이기도 하다.
결정적으로, Apache Kafka의 브로커와 클라이언트는 모두 단일 데이터센터 안에서 설계·개발·테스트·튜닝되었다. 브로커와 클라이언트 사이의 지연이 낮고 대역폭이 높다고 가정한 것이다. 이 가정은 기본 타임아웃 값과 각종 버퍼 크기에 그대로 드러난다. 그래서 (뒤에 나올 특수한 경우를 빼면) 일부 브로커를 한 데이터센터에, 나머지를 다른 데이터센터에 두는 구성은 권장되지 않는다.
대부분의 경우 원격 데이터센터로 데이터를 '생산'하는 것은 피하는 편이 낫다. 꼭 해야 한다면 높은 지연과 더 잦은 네트워크 오류를 감안해야 한다. 오류는 프로듀서 재시도 횟수를 늘려 다루고, 높은 지연은 전송 시도 사이에 레코드를 담아 두는 버퍼 크기를 키워 다룬다.
브로커 간 통신도, 프로듀서-브로커 통신도 배제했다면 남는 것은 브로커-컨슈머 통신이다. 이것이 실제로 크로스 클러스터 통신 중 가장 안전한 형태다. 네트워크 파티션이 생겨 컨슈머가 데이터를 읽지 못하더라도, 레코드는 Kafka 브로커 안에 안전하게 남아 있다가 통신이 복구되면 컨슈머가 읽어 갈 수 있기 때문이다. 네트워크 파티션 때문에 데이터가 유실될 위험이 없다. 다만 대역폭이 제한적이므로, 한 데이터센터의 여러 애플리케이션이 다른 데이터센터의 브로커에서 각각 읽게 하기보다는 데이터센터마다 클러스터를 두고 필요한 데이터를 한 번만 미러링하는 편이 낫다.
이 논의에서 세 가지 원칙이 나온다.
1. 데이터센터마다 최소 하나의 클러스터를 둔다. 2. 데이터센터 쌍 사이에서 각 이벤트는 (오류로 인한 재시도를 제외하면) 정확히 한 번만 복제한다. 3. 가능하다면 원격 데이터센터로 생산하지 말고, 원격 데이터센터에서 소비한다.
핵심 포인트
- 크로스 DC의 제약: 높은 지연, 제한되고 변동하는 대역폭, 높은 비용
- Kafka 브로커·클라이언트는 단일 DC 가정으로 설계되었고 기본 타임아웃·버퍼 크기에 그 가정이 반영되어 있다
- 브로커를 여러 데이터센터에 나눠 설치하는 것은 (Stretch cluster 제외) 권장되지 않는다
- 브로커-컨슈머 통신이 가장 안전하다 — 네트워크 파티션이 나도 데이터는 소스 브로커에 남는다
- 설계 3원칙: DC당 최소 1클러스터 / DC 쌍 사이 이벤트는 정확히 한 번 복제 / 원격 생산 대신 원격 소비
Hub-and-Spokes — 단순하지만 지역 간 조회가 안 된다
여러 개의 로컬 Kafka 클러스터와 하나의 중앙 Kafka 클러스터가 있는 구성이다. 클러스터가 둘뿐인(리더 하나, 팔로워 하나) 더 단순한 변형도 있다.
이 아키텍처는 데이터가 여러 데이터센터에서 생산되고 일부 컨슈머가 전체 데이터셋에 접근해야 할 때 쓴다. 각 데이터센터의 애플리케이션이 그 데이터센터의 로컬 데이터만 처리하는 것도 가능하다. 다만 각 데이터센터에서 전체 데이터셋에 접근할 수는 없다.
주된 이점은 데이터가 항상 로컬 데이터센터로 생산되고, 각 데이터센터의 이벤트가 중앙 데이터센터로 딱 한 번만 미러링된다는 점이다. 단일 데이터센터의 데이터를 처리하는 애플리케이션은 그 데이터센터에 두고, 여러 데이터센터의 데이터가 필요한 애플리케이션은 모든 이벤트가 모이는 중앙 데이터센터에 둔다. 복제가 항상 한 방향이고 각 컨슈머가 항상 같은 클러스터에서 읽기 때문에, 배포·설정·모니터링이 단순하다.
단점은 이 단순함의 직접적인 결과다. 한 지역 데이터센터의 처리기는 다른 지역의 데이터에 접근할 수 없다. 책의 예를 보자. 여러 도시에 지점을 둔 대형 은행이 도시마다 Kafka 클러스터에 사용자 프로필과 계좌 이력을 저장하고, 이 정보 전체를 중앙 클러스터로 복제해 비즈니스 분석에 쓴다. 사용자가 은행 웹사이트에 접속하거나 지역 지점을 방문하면 로컬 클러스터로 이벤트를 보내고 같은 로컬 클러스터에서 읽는다. 그런데 사용자가 다른 도시의 지점을 방문하면 어떻게 될까? 그 도시에는 이 사용자 정보가 없으므로, 지점은 원격 클러스터와 통신하거나(권장되지 않음) 사용자 정보에 아예 접근하지 못하게 된다(정말 난감하다). 이 때문에 이 패턴은 보통 지역별로 완전히 분리 가능한 데이터셋에만 제한적으로 쓴다.
구현할 때는 지역 데이터센터마다 최소 하나의 미러링 프로세스를 중앙 데이터센터에 둔다. 이 프로세스가 각 원격 지역 클러스터에서 소비해 중앙 클러스터로 생산한다. 같은 토픽이 여러 데이터센터에 존재한다면, 모든 이벤트를 중앙 클러스터의 동일한 이름의 토픽 하나에 쓸 수도 있고, 데이터센터별로 별도 토픽에 쓸 수도 있다.
핵심 포인트
- 여러 로컬 클러스터 → 하나의 중앙 클러스터, 복제는 항상 단방향
- 장점: 로컬 생산, 이벤트당 1회 미러링, 배포·설정·모니터링이 단순
- 단점: 지역 데이터센터끼리는 서로의 데이터에 접근할 수 없다
- 미러링 프로세스는 중앙 데이터센터에 두고, 지역 클러스터에서 소비해 중앙으로 생산한다
Active-Active — 가장 강력하지만 충돌을 반드시 다뤄야 한다
둘 이상의 데이터센터가 데이터의 일부 또는 전부를 공유하고, 각 데이터센터가 생산과 소비를 모두 할 수 있는 구성이다.
주된 이점은 사용자를 가까운 데이터센터에서 서비스할 수 있다는 점이다. 성능상 이득이 있으면서도, Hub-and-Spokes에서 봤던 '데이터가 없어서 기능을 못 하는' 문제가 없다. 부차적인 이점은 이중화와 회복력이다. 모든 데이터센터가 모든 기능을 갖고 있으므로, 한 데이터센터가 사용 불가능해지면 사용자를 남은 데이터센터로 보내면 된다. 이 유형의 페일오버는 사용자 네트워크 리다이렉트만으로 되므로 가장 쉽고 투명하다.
주된 단점은 여러 위치에서 데이터를 비동기로 읽고 갱신할 때 충돌을 피하기 어렵다는 것이다. 기술적으로는 '같은 이벤트가 양쪽을 무한히 오가지 않게 하는 방법'이 문제이고, 더 중요하게는 두 데이터센터 사이의 데이터 일관성 유지가 어렵다.
첫 번째 어려움은 읽기와 쓰기의 데이터센터가 다를 때다. 사용자가 한쪽에 이벤트를 쓰고 다른 쪽에서 읽으면, 방금 쓴 이벤트가 아직 도착하지 않았을 수 있다. 사용자 입장에서는 위시리스트에 책을 담고 위시리스트를 열었는데 책이 없는 것으로 보인다. 그래서 이 아키텍처를 쓸 때는 보통 각 사용자를 특정 데이터센터에 '고정(sticky)'시켜 대부분의 시간 동안 같은 클러스터를 쓰게 만든다(원격에서 접속하거나 그 데이터센터가 죽은 경우 제외).
두 번째 어려움은 진짜 충돌이다. 거의 같은 시각에 한쪽 데이터센터에서는 '사용자가 책 A를 주문했다', 다른 쪽에서는 '같은 사용자가 책 B를 주문했다'는 이벤트가 생겼다고 하자. 미러링이 끝나면 양쪽 데이터센터가 서로 모순되는 두 이벤트를 모두 갖게 된다. 양쪽 애플리케이션이 이 상황을 다룰 줄 알아야 한다. 하나를 '정답'으로 고를 것인가? 그렇다면 양쪽이 같은 결론에 도달하도록 일관된 규칙이 필요하다. 아니면 둘 다 참으로 보고 책 두 권을 보낸 뒤 반품은 다른 부서가 처리하게 할 것인가? 아마존이 예전에 그렇게 충돌을 해결했지만, 주식 거래를 다루는 조직은 그럴 수 없다. 충돌을 최소화하고 발생 시 처리하는 구체적 방법은 유스케이스마다 다르다. 중요한 것은 이 아키텍처를 쓰면 충돌이 반드시 생기고 반드시 다뤄야 한다는 사실이다.
또 하나의 부담은 미러링 프로세스의 개수다. 데이터센터 쌍마다, 그리고 방향마다 미러링 프로세스가 필요하다. 데이터센터가 5개면 최소 20개의 미러링 프로세스를 유지해야 하고, 각 프로세스에 고가용성을 위한 이중화까지 두면 40개에 가까워진다.
무한 미러링 루프를 막는 방법은 '논리 토픽'마다 데이터센터별 토픽을 따로 두고, 원격 데이터센터에서 출발한 토픽은 복제하지 않는 것이다. 예를 들어 논리 토픽 users는 한쪽에서 SF.users, 다른 쪽에서 NYC.users가 된다. 미러링 프로세스는 SF.users를 SF→NYC로, NYC.users를 NYC→SF로 미러링한다. 그 결과 각 이벤트는 한 번만 미러링되지만, 각 데이터센터는 SF.users와 NYC.users를 모두 갖게 되어 전체 사용자 정보를 보유한다. 모든 사용자 이벤트를 소비하려는 컨슈머는 정규식(*.users)으로 두 토픽을 함께 구독하면 된다. 데이터센터마다 별도의 네임스페이스를 두는 구성이라고 이해해도 된다.
책은 가까운 미래에 Kafka가 레코드 헤더를 추가할 것이라고 적고 있다(실제로 0.11에서 추가되었다). 헤더가 있으면 이벤트에 출발 데이터센터를 태깅해 무한 루프를 막고 데이터센터별로 이벤트를 따로 처리할 수 있다. 헤더가 없던 시점에는 값 자체를 Avro 같은 구조화 포맷으로 만들어 태그를 넣는 방식으로 흉내낼 수 있지만, 기존 미러링 도구가 그 커스텀 헤더 포맷을 이해하지 못하므로 추가 작업이 필요했다.
핵심 포인트
- 모든 데이터센터가 생산·소비 모두 수행 — 가장 확장성 있고 회복력 있고 비용 효율적
- 사용자를 특정 데이터센터에 sticky하게 붙여 read-your-writes 문제를 완화한다
- 충돌은 반드시 발생하며, 양쪽 애플리케이션이 일관된 규칙으로 해소해야 한다
- DC N개면 방향별 미러링 프로세스가 N*(N-1)개 — 5개 DC면 최소 20개
- 무한 루프 방지: 논리 토픽을 SF.users / NYC.users처럼 DC 네임스페이스로 분리하고 원격 출발 토픽은 재복제하지 않는다
Active-Standby — 설정은 단순하지만 페일오버가 어렵다
여러 클러스터가 필요한 유일한 이유가 재해 대비인 경우다. 같은 데이터센터 안에 두 클러스터를 두고 하나만 쓰거나, 캘리포니아 데이터센터에서 전 비즈니스를 돌리면서 지진에 대비해 텍사스에 두 번째 데이터센터를 두는 식이다. 텍사스 데이터센터에는 모든 애플리케이션의 비활성(cold) 복사본이 있고, 비상 시 관리자가 이를 기동해 두 번째 클러스터를 쓴다. 이것은 비즈니스가 실제로 계획하는 일이라기보다 법적 요구사항인 경우가 많지만, 그래도 준비는 되어 있어야 한다.
장점은 설정이 단순하고 거의 모든 유스케이스에 쓸 수 있다는 것이다. 두 번째 클러스터를 설치하고 한쪽에서 다른 쪽으로 모든 이벤트를 흘려보내는 미러링 프로세스만 두면 된다. 데이터 접근이나 충돌 처리 같은 아키텍처적 복잡함을 걱정할 필요가 없다.
단점은 멀쩡한 클러스터 하나를 놀린다는 것과, Kafka 클러스터 간 페일오버가 보기보다 훨씬 어렵다는 것이다. 결론부터 말하면, 현재 Kafka에서는 데이터를 잃거나 이벤트가 중복되지 않고 클러스터 페일오버를 수행하는 것이 불가능하다. 대개는 둘 다 발생한다. 최소화할 수는 있어도 완전히 없앨 수는 없다.
재해만 기다리며 아무 일도 하지 않는 클러스터가 자원 낭비인 것은 분명하다. 어떤 조직은 DR 클러스터를 프로덕션보다 훨씬 작게 만들어 이 문제를 피하려 하지만, 이는 위험한 결정이다. 최소 사이즈의 클러스터가 비상 시 버텨 줄지 확신할 수 없기 때문이다. 다른 조직은 읽기 전용 워크로드 일부를 DR 클러스터로 옮겨 쓸모 있게 만든다. 이는 사실상 스포크가 하나인 작은 Hub-and-Spokes를 돌리는 셈이다.
어떤 페일오버 방법을 고르든, SRE 팀이 정기적으로 연습해야 한다는 점은 강조할 필요가 있다. 오늘 되는 계획이 업그레이드 후에 안 될 수 있고, 새 유스케이스가 기존 도구를 무용지물로 만들 수도 있다. 분기에 한 번이 통상 최소한이고, 강한 SRE 팀은 훨씬 자주 연습한다. 무작위로 장애를 일으키는 넷플릭스의 Chaos Monkey가 극단적인 예로, 어느 날이든 페일오버 연습일이 될 수 있게 만든다.
핵심 포인트
- DR 전용 대기 클러스터 — 설정이 단순하고 어떤 유스케이스에도 적용 가능
- Kafka에서 데이터 유실도 중복도 없는 클러스터 페일오버는 현재 불가능하다
- DR 클러스터를 축소해 두는 것은 비상 시 버틸지 알 수 없어 위험하다
- 읽기 전용 워크로드를 DR로 옮기면 사실상 스포크 1개짜리 Hub-and-Spokes가 된다
- 페일오버는 최소 분기 1회 이상 정기적으로 연습해야 한다
Stretch Cluster — 동기 복제, 그러나 3개 데이터센터가 필요하다
Active-Standby가 '클러스터 장애'로부터 비즈니스를 보호하는 것이라면, Stretch Cluster는 '데이터센터 전체 장애'로부터 Kafka 클러스터 자체를 보호한다. 방법은 하나의 Kafka 클러스터를 여러 데이터센터에 걸쳐 설치하는 것이다.
Stretch Cluster는 다른 멀티 데이터센터 시나리오와 근본적으로 다르다. 애초에 멀티클러스터가 아니라 단일 클러스터다. 따라서 두 클러스터를 동기화할 미러링 프로세스가 필요 없고, Kafka의 평소 리플리케이션 메커니즘이 클러스터 내 모든 브로커를 동기화한다.
이 구성에는 동기 복제를 넣을 수 있다. 평소 프로듀서는 메시지가 Kafka에 성공적으로 기록된 뒤 브로커에게서 확인을 받는다. Stretch Cluster에서는 메시지가 '두 데이터센터의' Kafka 브로커에 성공적으로 기록된 뒤에 확인이 가도록 구성할 수 있다. 이를 위해 rack 정의를 사용해 각 파티션의 복제본이 여러 데이터센터에 놓이게 하고, min.isr과 acks=all로 모든 쓰기가 최소 두 데이터센터에서 확인되게 한다.
장점은 바로 이 동기 복제다. 어떤 업종은 DR 사이트가 항상 프라이머리와 100% 동기화되어 있을 것을 요구한다. 이는 종종 법적 요구사항이며 회사의 모든 데이터스토어에 적용된다. 또 하나의 장점은 두 데이터센터와 클러스터의 모든 브로커가 실제로 사용된다는 점이다. Active-Standby에서 봤던 낭비가 없다.
한계도 뚜렷하다. 이 아키텍처는 데이터센터 장애만 막아 줄 뿐, 애플리케이션 장애나 Kafka 자체의 장애는 막지 못한다. 운영 복잡도도 제한적이며, 모든 회사가 제공할 수 있는 물리적 인프라를 요구하지도 않는다.
실행 가능 조건은 명확하다. 대역폭이 높고 지연이 낮은 데이터센터가 최소 3곳 있어야 Kafka와 Zookeeper를 설치할 수 있다. 같은 거리에 건물 세 채를 소유한 회사이거나, 더 흔하게는 클라우드 제공자의 한 리전 안의 가용 영역 3개를 쓰는 경우다.
왜 3개인가? Zookeeper는 클러스터 노드 수가 홀수여야 하고 노드의 과반이 살아 있어야 가용하기 때문이다. 데이터센터가 2개이고 노드 수가 홀수라면 한쪽 데이터센터가 항상 과반을 갖게 된다. 즉 그 데이터센터가 죽으면 Zookeeper가 죽고, 따라서 Kafka도 죽는다. 데이터센터가 3개면 어느 한 데이터센터도 과반을 갖지 않도록 노드를 배치할 수 있다. 한 데이터센터가 죽어도 나머지 둘에 과반이 남아 Zookeeper가, 따라서 Kafka도 계속 가용하다. 두 데이터센터에서 수동 페일오버를 허용하는 Zookeeper 그룹 설정으로 운영하는 것도 가능하지만 흔치 않은 구성이다.
핵심 포인트
- Stretch Cluster는 멀티클러스터가 아니라 여러 DC에 걸친 단일 클러스터 — 미러링 프로세스가 없다
- rack 정의 + min.isr + acks=all로 두 데이터센터 확인 후 ack하는 동기 복제 구성이 가능하다
- 장점: 동기 복제(법적 요구 충족), 모든 브로커가 실제로 사용됨
- 한계: 데이터센터 장애만 막고 애플리케이션·Kafka 자체 장애는 막지 못한다
- Zookeeper 과반 요건 때문에 데이터센터가 최소 3곳 필요하다 (2곳이면 한쪽이 과반을 독점)
이 모듈과 연관된 문항 5개가 문제 은행에 있습니다.
이 내용으로 문제 풀어보기