이 글은 “카프카, 데이터 플랫폼의 최강자” 책 내용을 정리한 글입니다.

만약 저작권 관련 문제가 있다면 “gunjuko92@gmail.com”로 메일을 보내주시면, 바로 삭제하도록 하겠습니다.

카프카, 데이터 플랫폼의 최강자 - 2장 카프카 설치

1. 카프카 관리를 위한 주키퍼

  • 주키퍼는 카프카와 직접 통신을 하면서, 카프카의 메타데이터 정보를 주키퍼에 저장하고, 카프카의 상태관리 등의 목적으로 주키퍼를 이용한다. 이렇게 카프카는 주키퍼와 긴밀하게 통신하기 때문에 주키퍼 사용이 필수 조건이다.
  • 분산 애플리케이션을 사용하게 되면, 분산 애플리케이션 관리를 위한 안정적인 코디네이션 애플리케이션이 추가로 필요하게 된다.
  • 주키퍼는 이미 안정적인 코디네이션 서비스로 검증되었다.

주피커는 원래 하둡의 서브 프로젝트 중 하나였다. 하둡은 중앙에서 분산 애플리케이션을 관리하는 코디네이션 애플리케이션이 필요했기 때문에 서브 프로젝트로서 주키퍼 개발 작업을 진행하고 있었다.

  • 카프카는 분산 애플리케이션의 한 종류로서 주키퍼를 코디네이션 로직으로 이용하고 있다.
  • 주키퍼는 분산 애플리케이션이 안정적인 서비스를 할 수 있도록 분산되어 있는 각 애플리케이션의 정보를 중앙에 집중하고 구성 관리, 그룹 관리 네이밍, 동기화 등의 서비스를 제공한다.
  • 주키퍼는 서버 여러 대를 클러스터로 구성하고, 분산 애플리케이션들이 각각 클라이언트가 되어 주키퍼 서버들과 커넥션을 맺은 후 상태 정보 등을 주고 받게 된다.
  • 상태 정보들은 주키퍼의 지노드라 불리는 곳에 키-값 형태로 저장하고, 지노드에 키-값이 저장된 것을 이용하여 분산 애플리케이션들은 서로 데이터를 주고 받게 된다.
  • 지노드는 일반적인 디렉토리와 비슷한 형태로서 자식노드를 가지고 있는 계층형 구조로 구성되어 있다.
  • 주키퍼의 각 지노드는 데이터 변경 등에 대한 유효성 검사 등을 위하 버전 번호를 관리하게 되며, 데이터가 변경될 때마다 지노드의 버전 번호가 증가한다.
  • 주키퍼에 저장되는 데이터는 모두 메모리에 저장되어 처리량이 매우 크고 속도 또한 빠르다.
  • 클러스트로 구성되어 있는 주키퍼는 과반수 방식에 따라 살아 있는 노드 수가 과반 수 이상 유지된다면, 지속적인 서비스가 가능하다.
    • 예를 들어, 클러스터를 3대로 구성했을 때 1대의 노드가 다운되더라도 서비스가 가능하다.

만약 IDC 내 주키퍼를 구성하는 경우 주키퍼 클러스터 서버들은 모두 하나의 랙에 배치하지 않는게 좋다. 그리고 스위치 또한 분산해 구성한다면 더 안정적으로 운영할 수 있다.

2. 카프카

  • 과반수 방식으로 운영되어 홀수로 서버를 구성해야 하는 주키퍼와는 다르게, 카프카 클러스터는 홀수 운영 구성을 하지 않아도 된다.
    • 카프카 클러스터를 3대로 구성했을 때 2대가 다운되어도 서비스를 할 수 있다.
  • 주키퍼가 코디네이션 역할을 하지 못하는 경우가 되면 카프카 클러스터에는 문제가 없더라도 주키퍼와 통신이 되지 않기 때문에 카프카 역시 장애 상황에 놓이게 된다.

주키퍼를 사용하는 자바 애플리케이션에서 주의해야 할 사항

  • 주키퍼로 노드를 관리하는 애플리케이션들은 임시 노드를 이용해 애플리케이션의 호스트를 등록하고, 애플리케이션과 통신이 끊어지면 임시 노드에서 해당 호스트를 삭제한다.
  • 애플리케이션의 주키퍼 세션 타임아웃 설정(zookeeper.session.timeout)을 너무 짧게 설정하면, GC 타임으로 인해 노드가 다운된 것으로 판단해 의도치 않은 동작을 하게 될 가능성이 높다.

카프카 환경 설정

  • 클러스터내 브로커들은 서로 다른 아이디를 가진다.
  • 카프카의 주키퍼 설정 정보 입력시 주키퍼 서버 전체 리스트를 입력한다.

주키퍼 클러스터 내의 서버들은 모두 동일한 정보를 가지고 있기 때문에 카프카의 환경 설정 파일에서 주키퍼 정보 입력시 클러스터 중 임의의 하나만 입력하더라도 된다. 하지만 그렇게 되면 해당 주키퍼 서버가 다운되는 경우 카프카 클러스터도 장애 상황에 빠지기 때문에 매우 위험하다. 따라서 항상 전체 주키퍼의 리스트를 모두 입력하는 것이 좋다.

  • 주키퍼의 최상위 경로를 사용하지 않고, 지노드를 구분해서 사용하면 하나의 주키퍼 클러스터를 여러 개의 애플리케이션에서 공용으로 사용할 수 있다.
  • 주키퍼의 지노드를 구분해서 사용하는 경우에는, 주키퍼 정보를 입력할 때 호스트 이름과 포트 정보를 입력한 후 마지막 부분에 사용할 지노드 이름을 추가 입력하면 된다.
    • 하나의 주키퍼 앙상블 세트를 두 개의 카프카 클러스터가 사용하기 위해서 각각의 카프카 클러스터 이름으로 지노드를 만들어 구분할 수 있다.
    • 브로커가 시작할 때 해당 지노드가 주키퍼에 없다면 자동으로 지노드를 생성한다.

카프카 브로커 서버들은 주키퍼 서버와 통신이 되어야 하므로, 방화벽으로 포트 접근이 제한된 환경에서는 주키퍼와 통신 이상 유무를 확인해야 한다. 이는 nc 명령어를 이용해 확인할 수 있다.

  • nc -v IP주소 PORT번호

카프카 주요 옵션

  • broker.id : 브로커 아이디
  • delete.topic.enable : 토픽 삭제 기능 on/off
  • default.replication.factor : 리플리케이션 팩터 옵션을 주지 않았을 경우의 기본값
  • min.insync.replicas : 최소 리플리케이션 팩터
  • auto.create.topics.enable : 존재하지 않는 토픽으로 퍼블리셔가 메시지를 보냈을 때 자동으로 토픽 생성
  • auto.leader.rebalance.enable : 자동 리더 리밸런싱을 사용할지 여부 백그라운드 스레드가 일정한 간격으로 체크하고, 필요하다면 리더 리밸런싱을 일으킨다.
  • background.threads : 다양한 백그라운드 작업을 처리하기 위한 스레드 수
  • leader.imbalance.check.interval.seconds : 얼마나 자주 리더 불균형 체크를 할 것인지
  • leader.imbalance.per.broker.percentage : 브로커당 최대 리더 불균형 비율
  • offsets.topic.num.partitions : 오프셋 토픽 파티션 수
  • offsets.topic.replication.factor : 오프셋 토픽의 리플리케이션 팩터
  • offsets.retention.minutes : 이 기간보다 더 오래된 오프셋은 버려진다.
  • replica.lag.time.max.ms : 팔로워가 이 시간동안 Fetch 요청을 보내지 않거나 또는 리더 로그의 마지막 오프셋까지 읽지 않으면 리더는 팔로워를 isr에서 제거한다.
  • compression.type : 토픽의 최종 압축 형태, gzip, snappy, lz4 등의 표준 압축 포맷 지원, uncompressed는 압축을 지원하지 않음.
  • log.dirs : 로그가 저장되는 위치
  • num.partitions : 파티션 수 옵션을 주지 않았을 경우의 기본값
  • log.retention.hours : 저장된 로그의 보관 주기
  • log.segment.bytes : 저장되는 로그 파일 하나의 크기
  • log.retention.check.interval.ms : 로그 보관주기 체크 주기
  • message.max.bytes : 카프카에서 허용되는 가장 큰 메시지 크기
  • zookeeper.connect : 주키퍼 접속 정보
  • zookeeper.session.timeout.ms : 브로커와 주키퍼 사이의 최대 연결 대기 시간. 해당 시간 동안 주키퍼와 연결이 되지 않으면 타임아웃 발생
  • unclean.leader.election.enable : ISR 그룹에 포함되지 않은 마지막 리플리카를 리더로 인정.
  • log.flush.interval.ms : 메시지가 디스크로 플러시되기 전 메모리에 유지하는 시간
  • log.flush.interval.messages : 메시지가 디스크로 플러시되기 전 누적 메시지 수
  • group.initial.rebalance.delay.ms : 코디네이터가 파티션 리밸런싱을 처음 수행할 때 더 많은 컨슈머들이 새로운 컨슈머 그룹에 조인할 때까지 대기하는 시간
  • log.cleaner.threads : 로그를 cleaning 하는데 사용되는 백그라운드 스레드 개수
  • num.replica.fetchers : 소스 브로커로부터 메시지를 복제하기 위해서 사용되는 Fetcher 스레드 개수

카프카 실행

  • 카프카에서 제공하는 명령어를 이용하면 된다. (bin 디렉토리에 위치)
    • kafka-server-start.sh : 카프카 실행 명령어로 카프카 환경 설정 파일을 옵션으로 주어 실행하면 된다.
    • kafka-server-stop.sh : 카프카 서비스를 중지

3. 카프카 상태 확인

TCP 포트 확인

  • 주키퍼 서버에서 TCP 2181 포트가 리스닝 상태인지를 확인한다.
    • netstat -ntlp | grep 2181
    • n은 이름이 아닌 숫자료 표시, t는 tcp, l은 리스닝 상태 표시, p는 pid와 프로그램 표시를 의미한다.

주키퍼 지노드를 이용한 카프카 정보 확인

  • 카프카와 주키퍼가 잘 연결되었는지를 주키퍼 CLI에 직접 접속해서 확인해보자
    • CLI 접속 : bin 디렉토리에 있는 zkCli.sh 명령어를 실행
  • 카프카 클러스터 서버 3대가 모두 잘 연결되었는지 주키퍼 지노드에서 확인할 수 있다. 카프카에서 사용하는 주키퍼의 지노드 중 브로커 정보들이 있는 지노드를 ls 명령어를 이용해 확인하면 된다. 그러면 카프카 환경 설정 파일에서 입력한 broker.id 번호 리스트를 확인할 수 있다.