if kakao 2024 컨퍼런스에서 재밌거나 나에게 유용하다고 생각하는 세션들을 정리하는 포스팅입니다. 원래는 세션들을 하나의 포스트에 정리하려고 했었는데 영상 하나의 길이가 30분이 넘어가고 다 중요하다고 생각해서 하나하나 정리하다보니 막상 생각보다 너무 길어지게 되어 세션별로 글을 나누게 되었습니다.
시작하기전에
발표배경
카카오에서 2022년 if 카카오에 카프카 운용후기를 발표했는데 당시 Kfrat모드를 적용할 예정이었던 것을 소개한 적 있음
2022년 발표당시 3.3.1버전이었고 현재 3.8.0을 사용하고 있음
버전이 올라가면서 여러 패치와 성능 개선이 있었음 발맞춰서 Kraft 모드로 변경함
주키퍼 없는 카프카
기존 주키퍼의 문제점
리더 파티션 변경이 이루어졌을 때 주키퍼와 카프카 컨트롤러 그리고 다른 브로커들에게 전달하는 과정이 많아서 특정 브로커가 중간에 문제가 생겼을 때 이전 정보와 변경된 정보의 혼합으로 인해 각자 다른 파티션을 리더로 인식하는 문제가 발생
주키퍼에서 컨트롤러로 정보를 전달할 때 통신이 지연되는 일이 종종 발생함 그 사이에 브로커는 잘못된 정보를 가지고 있음
이후 카프카는 점진적으로 주키퍼와의 의존성을 끊으려는 노력을 했고 3.3.1버전부터는 KRaft 모드를 제공해서 완전히 주키퍼와의 의존성을 덜어내려고함
KRaft Mode의 소개
Kafka Raft를 줄여서 Kraft로 표현
변경 사항을 모든 노드가 동일하게 가질 수 있게하는 Raft 알고리즘을 사용함
Raft는 Reliable, Replicated, Rebundant And Fault-Tolerant의 줄임말
KRaft Mode의 구성
컨트롤러와 브로커로 역할이 나누어지고 노드라는 이름로 통칭함
리더가 죽더라도 즉각 리더를 변경하여 메타데이터를 신속하게 갱신이 가능
컨트롤러와 브로커 역할을 동시에 할 수도 있음 이를 컴바인 모드라고 하는데 production환경에서는 이를 권장하지는 않음
KRaft Mode의 용어
Leader와 Follower는 흔히 알지만 Kraft 모드로 오면서 새로운 용어들이 많이 추가됐다.
Voter: Leader와 Candidate로 전환할 수 있는 복제본을 말함→ 컨트롤러
Candidate: Leader가 Heartbeat에 응답하지 않아 만료될 때, Voter들이 자기 자신을 후보자로 등록하여 선거를 진행함
Observer: 클러스터에는 속해 있으나 쿼럼으로 구성되어있지 않은 노드들→ 브로커
Epoch: Raft 알고리즘에서는 Terms라고 하며 선거할 때마다 올라가는 수치
Kraft Mode의 장점
주키퍼의 단점을 보완함→처리량 및 대기 시간(딜레이) 감소
안정성 및 소프트웨어 간소화
모니터링 및 관리가 쉬워짐
신속한 컨트롤러 장애 조치
신속한 컨트롤러 장애 조치
벤치마크 결과 장애시 복구 시간이 약 93% 단축 되었으며 이는 스냅샷이라는 존재때문임
메타데이터 캐시에 지속적으로 쌓이는 로그들을 일정 주기로 체크포인트로 쌓이고 이 체크포인트를 이용하여 빠른 복구가 가능→ 증분분만큼만 빠르게 복구 가능
구성과정
카카오에서는 Dev→ CBT→ Prod 순으로 23년 1월을 시작으로 1년이상의 서비스 과정을 거쳐 현재의 Prod 환경까지 실서비스 중
주키퍼 기반 설정때는 broder.id를 고유번호로 사용하며 zookeeper.connect를 통해 주키퍼와 이어주었지만 Kraft 설정에서는 노드별로 어떤 임수를 수행할지 결정해줄 수 있음
주키퍼에서 알아서 지정해주었기 때문에 이전에는 Cluster ID에 대해서 크게 신경 쓰지 않았지만 KRaft 모드를 사용하게 되면 자체적으로 생성 및 저장이 필요함
Dev를 1년 이상 유지한 이유
KIP-996 티켓에서 네트워크 파티션 발생시 선출이 무한히 진행되어 쿼럼이 붕괴되는 문제가 있어서 아직도 이 문제는 해결되지 않았고 이 증상을 막기 위해 컨트롤러를 꼭 3대로 구성되어야함을 권장함
스플릿 브레인 문제가 있었고 3.7.0버전 이상에서 해결됨
벤치마크 및 모니터링툴
벤치마크 워크로드 툴 trogdor
카프카 바이너리 내부에 있는 툴 커맨드, API 등을 통해 task 실행 가능
카프카 모니터링 jmx_exporter
시스템 모니터링 node_exporter
안정성 테스트
Trogdor를 통해서 초당 2M 이상 레코드, 초당 2.5GB 이상의 데이터를 인입시켜 스플릿 브레인 문제가 발생하는지, 네트워크와 파워 제거시 Epoch의 증가추세와 브로커에서 복구 시간도 함께 살펴보고자 했음
강한 부하 환경에도 스플릿 브레인 문제는 발생하지 않았고 파워플러그 제거때는 epoch가 소폭 증가, 네트워크 단절에서는 epoch가 대폭 증가함
리플리카, 쓰레드, 압축과 관련된 설정을 중점적으로 확인함
num.replica.fetchers값과 log.cleaner.threads값에서 병목 지점을 발견했고 벤치마크 테스트를 통해서 적당한 값을 찾아 처리량 향상을 할 수 있었음
partitioner.adaptive.partitioning.enable=ture
고의적인 지연을 발생시켜 테스트했을 때 부하 불균형 상태에서 SUSP는 다른 파티셔너(RRP, USP)에 비해서 몇배 크게는 몇천배까지 차이가 났으므로 해당 옵션을 true로 해서 사용하기를 권고함
향후 계획
단기계획: 기존의 KRaft 쿼럼 구성 정보는 정적 설정 파일로만 지정이 가능해서 구성 정보를 변경하려면 모든 컨트롤러를 다시 재시작해야하는 문제가 있음 이를 재시작하지 않아도 동적으로 쿼럼 구성 정보를 변경할 수 있는 API를 추가하고자함
헬름으로 사용할때도 이전 주키퍼를 사용할 때와 다르게 Cluster ID가 업그레이드시 꼭 필요했음
kafka-ui는 사용하고있지만 Lag 모니터링을 위해 kminion을 따로 사용하고 있고 kminion이라는 것도 처음 알게됨
압축 벤치마크가 인상깊었음 그냥 기본값으로 사용하고있었는데 기본값은 cpu나 초당 데이터 인입 등 시스템 전반적으로 악영향이 있다고 하니 압축을 사용하는 것이 더 비용효율이 높을 것 같다→ 브로커와 파로듀서의 압축 타입을 일치 시켜줘야하므로 디비지움에서도 zstd로 압축을 해줘야함. debezium은 2.0버전부터 binlog 데이터를 zstd로 압축을 지원함
개인적으로 주키퍼때문에 많이 힘들었는데 Kraft로 도전적으로 올렸음에도 불구하고 production에서 안정적으로 구동하고 있음 규모가 크지않아 컨트롤러가 3개인데 그 이상은 브레인스플릿 문제가 생길 수 있다는 사실도 이 세션을 통해서 처음 알게됨