Kafka 브로커 장애 해결 및 복구 전략

이 포괄적인 가이드는 하드웨어 문제부터 잘못된 구성까지 Kafka 브로커 장애의 일반적인 원인을 탐구합니다. 로그 분석, 리소스 모니터링 및 JVM 진단을 포함한 체계적인 문제 해결 단계를 배워 근본 원인을 신속하게 식별할 수 있습니다. 브로커 재시작, 데이터 손상 처리 및 용량 계획과 같은 효과적인 복구 전략을 발견하세요. 이 문서는 또한 더 탄력적인 Kafka 클러스터를 구축하고, 가동 중단 시간을 최소화하며, 분산 이벤트 스트리밍 플랫폼에서 데이터 무결성을 보장하기 위한 중요한 예방 조치와 모범 사례를 강조합니다.

Kafka 브로커 장애 해결 및 복구 전략

Kafka 브로커가 실패하면 일반적으로 다른 곳에서 먼저 시끄러운 증상이 나타납니다: 소비자가 뒤처지고, 프로듀서가 타임아웃되며, 대시보드에 복제 부족 파티션이 표시되고, 이벤트가 도착하지 않아 배포 파이프라인이 차단됩니다. 브로커 자체는 한 가지 명백한 사실만 보여줄 수 있습니다: 프로세스가 사라졌거나, 시작 중에 멈췄거나, 실행 중이지만 너무 느려서 유용하지 않습니다.

Kafka 브로커 장애를 해결하는 유용한 방법은 세 가지 질문을 신속하게 분리하는 것입니다. 브로커 프로세스가 충돌했습니까? 노드나 디스크로 인해 브로커가 비정상 상태가 되었습니까? 아니면 브로커가 실행 중이지만 클러스터에 올바르게 참여할 수 없습니까? 이러한 경로는 서로 다른 수정으로 이어지며, 이를 혼동하면 작은 중단이 긴 중단으로 이어질 수 있습니다.

Kafka 브로커 장애 이해

Kafka 브로커는 하드웨어 문제부터 소프트웨어 잘못된 구성까지 다양한 이유로 실패할 수 있습니다. 근본 원인을 식별하는 것이 효과적인 복구를 위한 첫 번째 단계입니다. 가장 일반적인 원인은 다음과 같습니다:

1. 하드웨어 및 인프라 문제

  • 디스크 장애: 로그에 IOException 또는 LogSegmentCorruptedException이 자주 발생합니다. 브로커는 메시지의 영구 저장을 위해 디스크 I/O에 크게 의존합니다.
  • 메모리 고갈(OOM): RAM이 부족하면 JVM이 충돌하거나 운영 체제가 Kafka 프로세스를 종료할 수 있습니다. 증상으로는 로그의 OutOfMemoryError 또는 시스템 수준 OOM 킬러 메시지가 있습니다.
  • CPU 과부하: CPU 사용률이 높으면 브로커 속도가 크게 느려져 시간 초과 및 응답 불가 상태가 발생할 수 있습니다.
  • 정전: 특히 fsync 설정이 최적이 아닌 경우 제어되지 않은 종료로 인해 로그 세그먼트 또는 Zookeeper 데이터가 손상될 수 있습니다.

2. 네트워크 문제

  • 연결 문제: 브로커가 다른 브로커, Zookeeper 또는 클라이언트에 대한 연결을 잃을 수 있습니다. 이는 NetworkException, SocketTimeoutException 또는 Zookeeper 세션 만료로 나타날 수 있습니다.
  • 높은 지연 시간/패킷 손실: 네트워크 성능 저하로 인해 복제 지연, 소비자 그룹 리밸런스 및 브로커 선출 실패가 발생할 수 있습니다.

3. JVM 및 OS 구성

  • 잘못된 JVM 힙 설정: 힙이 너무 작으면 OutOfMemoryError가 발생합니다. 너무 크면 과도한 가비지 컬렉션(GC) 일시 중지로 인해 브로커가 응답하지 않는 것처럼 보일 수 있습니다.
  • 파일 디스크립터 제한: Kafka는 많은 파일(로그 세그먼트, 네트워크 연결)을 엽니다. 파일 디스크립터에 대한 OS ulimit를 초과하면 Too many open files 오류가 발생할 수 있습니다.
  • 스와핑: OS가 메모리를 디스크로 스와핑하기 시작하면 성능이 심각하게 저하됩니다. Kafka 노드는 이상적으로 스와핑을 비활성화해야 합니다.

4. 디스크 I/O 및 스토리지

  • 디스크 처리량 부족: 디스크가 쓰기 요청을 따라잡을 수 없으면 I/O 대기 시간이 길어지고 메시지가 누적되어 결국 브로커가 응답하지 않게 될 수 있습니다.
  • 디스크 가득 참: 디스크가 가득 차면 Kafka가 새 메시지를 쓰지 못하게 되어 IOException: No space left on device 및 브로커 중단이 발생합니다.
  • 로그 손상: 드물게, 특히 부적절한 종료 후에 로그 세그먼트가 손상되어 브로커가 시작되거나 데이터를 제공하지 못할 수 있습니다.

5. 메타데이터 쿼럼 또는 Zookeeper 문제

  • Zookeeper 사용 불가: 여전히 Zookeeper를 사용하는 Kafka 클러스터는 컨트롤러 선출 및 토픽 메타데이터를 포함한 메타데이터 관리를 위해 Zookeeper에 의존합니다. Zookeeper가 다운되거나 느리면 브로커에 세션 만료, 컨트롤러 변경 또는 메타데이터 동기화 문제가 나타날 수 있습니다.
  • KRaft 컨트롤러 문제: 최신 Kafka 배포는 Zookeeper 대신 KRaft 모드를 사용할 수 있습니다. 이러한 클러스터에서는 컨트롤러 쿼럼 상태가 중요합니다. 컨트롤러 선출 불안정, 쿼럼 연결 문제 및 메타데이터 로그 복제를 언급하는 브로커 로그를 찾으십시오.

6. 소프트웨어 버그 및 구성 오류

  • Kafka 소프트웨어 버그: 안정적인 릴리스에서는 덜 일반적이지만, 특히 최신 버전이나 특정 에지 케이스에서 가능합니다.
  • 잘못된 구성: server.properties 설정(예: listeners, advertised.listeners, log.dirs, replication.factor 영향)이 잘못되면 브로커가 클러스터에 가입하거나 올바르게 작동하지 못할 수 있습니다.

체계적인 문제 해결 단계

Kafka 브로커가 실패하면 문제를 신속하게 식별하고 해결하기 위해 체계적인 접근 방식이 중요합니다.

1. 초기 평가: 기본 상태 확인

  • Kafka 프로세스가 실행 중인지 확인:
    systemctl status kafka # systemd 서비스의 경우
    # 또는
    ps aux | grep -i kafka | grep -v grep
    
  • 다른 브로커/클라이언트에서 브로커 연결 확인:
    netstat -tulnp | grep <kafka_port>
    # 또는 nc를 사용하여 다른 머신에서 포트 테스트
    nc -zv <broker_ip> <kafka_port>
    

2. 시스템 리소스 모니터링

top, htop, free -h, iostat, df -hvmstat와 같은 도구를 사용하여 다음을 확인하십시오:

  • CPU 사용량: 지속적으로 높습니까? I/O 대기 주기가 많습니까?
  • 메모리 사용량: 시스템이 OOM에 가깝습니까? 과도한 스와핑이 있습니까?
  • 디스크 I/O: 높은 쓰기/읽기 지연 시간 또는 처리량 포화? iostat -x 1을 사용하여 디스크 병목 현상을 식별하십시오.
  • 디스크 공간: log.dirs 파티션이 가득 찼습니까? df -h <kafka_log_directory>
  • 네트워크 활동: 트래픽에 비정상적인 급증 또는 하락이 있습니까? 높은 오류율?

3. Kafka 브로커 로그 분석

Kafka 로그(기본적으로 kafka-logs/server.log)는 가장 중요한 진단 도구입니다. 다음을 찾으십시오:

  • 오류 메시지: 장애 직전의 ERROR, WARN 수준 메시지.
  • 예외: OutOfMemoryError, IOException, SocketTimeoutException, LogSegmentCorruptedException.
  • GC 활동: 긴 GC 일시 중지(활성화된 경우 GC 로그의 INFO 메시지로 표시됨).
  • Zookeeper 연결 문제: 세션 만료 또는 재설정에 대한 INFO 메시지.
  • 컨트롤러 선출: Kafka 컨트롤러 및 선출 프로세스와 관련된 메시지.

: 프로덕션에서 더 나은 사후 분석을 위해 로그 보존 기간을 늘리고 GC 로깅을 활성화하십시오.

4. JVM 진단

메모리 또는 CPU가 문제인 것으로 보이면 JVM 관련 도구를 사용하십시오:

  • jstat -gc <pid> 1000: 가비지 컬렉션 통계를 모니터링합니다. 높은 FGC(Full GC) 횟수 또는 긴 FGCT(Full GC 시간)를 찾으십시오.
  • jstack <pid>: JVM이 무엇을 하고 있는지 확인하기 위해 스레드 덤프를 가져옵니다. 교착 상태 또는 장기 실행 작업을 식별하는 데 유용합니다.
  • jmap -heap <pid>: 힙 메모리 사용량을 표시합니다.
  • jcmd <pid> GC.heap_dump <file>: Eclipse MAT와 같은 도구로 자세한 메모리 분석을 위해 힙 덤프를 생성합니다.

5. 메타데이터 계층 상태 확인

클러스터가 실제로 사용하는 메타데이터 시스템을 확인하십시오.

Zookeeper 기반 클러스터의 경우:

  • Zookeeper 서비스 상태 확인:
    systemctl status zookeeper
    
  • Zookeeper 로그 파일 확인: Kafka의 연결 문제, Zookeeper 앙상블 내 선출 문제를 찾으십시오.
  • zkCli.sh를 사용하여 Zookeeper에 연결하고 Kafka 관련 znodes 나열: ls /brokers/ids, ls /controller.

KRaft 기반 클러스터의 경우 컨트롤러와 브로커 로그를 함께 검사하십시오. 브로커가 OS 수준에서 정상이지만 메타데이터를 등록하거나 가져올 수 없는 경우 컨트롤러 쿼럼이 다음으로 확인할 곳입니다.

6. 구성 검토

실패한 브로커의 server.properties를 작동 중인 브로커와 비교하십시오. 특히 log.dirs, listeners, advertised.listeners, broker.idzookeeper.connect에서 미묘한 차이점이나 최근 변경 사항을 찾으십시오.

효과적인 복구 전략

문제를 식별한 후에는 적절한 복구 전략을 구현하십시오.

1. 재시작이 실제로 안전한지 결정

재시작은 필요한 증거(최근 브로커 로그, 시스템 로그, 디스크 상태, 복제 부족 또는 오프라인 파티션 목록)를 확보한 후에 합리적입니다. 너무 일찍 재시작하면 유용한 프로세스 상태가 지워지고 반복되는 충돌이 5개의 관련 없는 사건처럼 보일 수 있습니다.

# Kafka 중지
systemctl stop kafka
# 정상 종료 메시지 확인
# Kafka 시작
systemctl start kafka
# 시작 문제 모니터링

브로커가 반복적으로 충돌하는 경우 재시작을 수정으로 취급하지 마십시오. 그 시점에서는 테스트일 뿐입니다. 시작 로그를 첫 줄부터 관찰하십시오. Kafka는 일반적으로 로그 복구, 리스너 바인딩, 스토리지 액세스, 메타데이터 등록 또는 JVM 시작 중 어디에서 멈췄는지 알려주기 때문입니다.

2. 실패한 하드웨어/VM 교체

영구적인 하드웨어 장애(디스크, 메모리, CPU)의 경우 결함이 있는 머신이나 VM을 교체하는 것이 해결책입니다. 새 인스턴스에 동일한 호스트 이름/IP(정적인 경우), 마운트 지점 및 Kafka 구성이 있는지 확인하십시오. 데이터 디렉터리가 손실된 경우 replication.factor > 1이라고 가정하면 Kafka는 클러스터에 다시 합류할 때 다른 브로커에서 데이터를 복제합니다.

교체를 도입하기 전에 배포에 대한 브로커 ID 규칙을 확인하십시오. 잘못된 로그 디렉터리로 브로커 ID를 재사용하면 혼동을 일으킬 수 있습니다. 클러스터가 여전히 이전 ID를 예상할 때 새 ID로 브로커를 시작하면 더 이상 존재하지 않는 브로커에 복제본이 할당될 수 있습니다. 계획된 교체에서는 클러스터가 모호한 상태를 정리하도록 하는 대신 의도적으로 복제본 할당을 업데이트하십시오.

3. 데이터 복구 및 로그 손상

로그 세그먼트가 손상된 경우(예: LogSegmentCorruptedException) 브로커가 시작되지 않을 수 있습니다.

  • 옵션 A: 손상된 로그 삭제(복제 팩터가 허용하는 경우): 영향을 받는 토픽의 replication.factor가 1보다 크고 정상 복제본이 있는 경우 실패한 브로커에서 문제가 되는 파티션의 손상된 로그 디렉터리를 삭제할 수 있습니다. 그러면 Kafka가 데이터를 다시 복제합니다.

    1. Kafka 브로커를 중지합니다.
    2. 로그에서 손상된 log.dirs 항목을 식별합니다.
    3. log.dirs 내에서 문제를 일으키는 파티션 디렉터리를 수동으로 삭제합니다(예: rm -rf /kafka-logs/topic-0).
    4. 브로커를 다시 시작합니다.
  • 옵션 B: kafka-log-dirs.sh 도구 사용: 이 도구는 복제본을 재할당하거나 로그 디렉터리를 이동하는 데 사용할 수 있습니다. 로그 손상의 경우 더 적극적인 접근 방식이 필요할 수 있습니다. Kafka 버전에는 특정 복구 시나리오를 위한 내부 도구가 있는 경우가 많지만, 다른 곳에 복제본이 있는 경우 실제로 손상된 세그먼트에 대해서는 수동 삭제가 일반적입니다.

4. 파티션 복제(손실된 경우)

브로커가 실패하고 해당 데이터가 영구적으로 손실된 경우(예: replication.factor=1인 디스크 충돌 또는 복제 팩터를 초과하는 여러 장애) 일부 데이터는 복구 불가능할 수 있습니다. 그러나 replication.factor > 1인 경우 Kafka는 자동으로 새 리더를 선출하고 데이터를 복구합니다. 실패한 브로커가 영구적으로 작동 불능 상태인 경우 kafka-reassign-partitions.sh를 사용하여 리더십을 재조정하거나 정상 브로커에 파티션을 재할당해야 할 수 있습니다.

5. 구성 업데이트

장애가 잘못된 구성으로 인한 경우 server.properties를 수정하고 브로커를 다시 시작하십시오. JVM 관련 문제(예: OutOfMemoryError)의 경우 kafka-server-start.sh 또는 kafka-run-class.sh에서 KAFKA_HEAP_OPTS를 조정하고 다시 시작하십시오.

# 예: 힙 크기 증가
export KAFKA_HEAP_OPTS="-Xmx8G -Xms8G"
# 그런 다음 Kafka 시작

6. 용량 계획 및 확장

지속적인 리소스 고갈(CPU, 메모리, 디스크 I/O, 네트워크)은 확장이 필요함을 나타냅니다. 여기에는 다음이 포함될 수 있습니다:

  • 클러스터에 브로커 추가.
  • 기존 브로커 하드웨어 업그레이드.
  • 토픽 구성 최적화(예: num.partitions, segment.bytes).
  • 소비자 효율성 개선.

실용적인 트라이지 흐름

압박을 받을 때 알고 있는 모든 Kafka 명령어로 시작하지 마십시오. 장애가 어디에 있는지 알려주는 가장 작은 세트로 시작하십시오.

먼저 브로커 프로세스가 살아 있고 수신 대기 중인지 확인하십시오:

systemctl status kafka
ss -lntp | grep 9092
jps -l | grep kafka

프로세스가 다운된 경우 브로커 로그와 시스템 저널이 주요 증거입니다. 마지막 오류가 아닌 첫 번째 심각한 오류를 찾으십시오. 마지막 줄은 단순히 서버가 종료되었음을 나타낼 수 있습니다. 유용한 줄은 Kafka가 로그 디렉터리를 열지 못하거나, 리스너를 바인딩하지 못하거나, 힙을 할당하지 못하거나, 메타데이터 계층에 연결하지 못한 수백 줄 앞에 있는 경우가 많습니다.

프로세스가 살아 있는 경우 클러스터가 여전히 유용하다고 간주하는지 확인하십시오:

kafka-broker-api-versions.sh --bootstrap-server <broker-host>:9092
kafka-topics.sh --bootstrap-server <bootstrap-host>:9092 --describe --under-replicated-partitions

브로커는 운영 체제 관점에서 살아 있을 수 있지만 클러스터 관점에서는 여전히 나쁜 브로커일 수 있습니다. 예를 들어 TCP 연결은 수락하지만 느린 디스크에서 읽을 수 없어 요청을 실패할 수 있습니다. 또는 랩톱에서는 연결할 수 있지만 advertised.listeners가 잘못된 주소를 가리키기 때문에 다른 브로커에서는 연결할 수 없을 수 있습니다.

그런 다음 노드를 확인하십시오:

df -h
iostat -x 1
free -h
dmesg -T | tail -100

가장 일반적인 실제 패턴은 신비로운 Kafka 버그가 아닙니다. 디스크 가득 참, 죽어가는 디스크, 동일한 호스트의 시끄러운 이웃, 메모리 압력을 받는 JVM, 또는 구성 변경 중에 도입된 리스너/네트워크 불일치입니다.

오류가 일반적으로 의미하는 것

No space left on device는 직접적입니다. 다시 시작하기 전에 공간을 확보하거나 스토리지를 추가하십시오. 또한 보존 설정이 생각한 대로 작동하는지 확인하십시오. 예기치 않게 긴 보존 기간을 가진 토픽이나 정리 진행 속도가 느린 압축 토픽은 조용히 디스크를 채울 수 있습니다.

Too many open files는 Kafka 프로세스의 운영 체제 제한을 가리킵니다. Kafka는 로그 세그먼트 파일과 네트워크 소켓을 열므로 낮은 기본값은 위험합니다. 서비스 사용자에 대한 파일 디스크립터 제한을 높이고 셸 세션뿐만 아니라 실행 중인 프로세스에서도 확인하십시오.

OutOfMemoryError는 JVM이 메모리를 할당할 수 없음을 의미하지만 원인이 항상 "힙이 너무 작음"은 아닙니다. 누수, 브로커의 너무 많은 파티션, 매우 큰 요청 처리, 또는 파일 시스템 페이지 캐시에 너무 적은 메모리를 남기는 잘못된 크기의 힙일 수 있습니다. Kafka는 OS 페이지 캐시에 크게 의존하므로 모든 RAM을 JVM에 제공하면 디스크 동작이 더 나빠질 수 있습니다.

Connection to node -1 could not be established는 종종 클라이언트 부트스트랩 중에 나타나며 advertised.listeners로 인해 발생할 수 있습니다. 클라이언트가 부트스트랩 주소에 연결할 수 있지만 해결할 수 없는 내부 호스트 이름을 수신하면 첫 번째 메타데이터 응답 후에 실패합니다.

브로커 장애 후 Leader not available은 일반적으로 리더십이 아직 이동 중이거나 영향을 받는 파티션에 준비된 동기화된 복제본이 없음을 의미합니다. 토픽에 충분한 복제가 있는지와 min.insync.replicas가 현재 정상 복제본 수와 호환되는지 확인하십시오.

예방 조치 및 모범 사례

사전 예방적 조치는 브로커 장애의 가능성과 영향을 크게 줄입니다.

  • 강력한 모니터링 및 알림: 시스템 리소스(CPU, 메모리, 디스크 I/O, 네트워크), JVM 메트릭(GC, 힙 사용량) 및 Kafka 관련 메트릭(복제 부족 파티션, 컨트롤러 상태, 소비자 지연)에 대한 포괄적인 모니터링을 구현합니다. 중요한 임계값에 대한 알림을 설정합니다.
  • 적절한 리소스 할당: 충분한 CPU, 메모리 및 고성능 디스크(SSD 권장)로 브로커를 프로비저닝합니다. 가상화 환경에서 초과 할당을 피합니다.
  • 정기적인 유지 관리 및 업데이트: Kafka 및 해당 종속성(JVM, OS)을 업데이트하여 버그 수정 및 성능 개선의 이점을 누리십시오. 비프로덕션 환경에서 업데이트를 철저히 테스트합니다.
  • 고가용성 구성: 데이터 중복성과 내결함성을 보장하기 위해 프로덕션 토픽에 항상 1보다 큰 replication.factor(일반적으로 3)를 사용합니다. 이를 통해 브로커가 데이터 손실이나 서비스 중단 없이 실패할 수 있습니다.
  • 재해 복구 계획: 중요한 구성 및 잠재적으로 로그 세그먼트의 정기적인 백업을 포함하여 데이터 복구를 위한 명확한 계획을 수립합니다(Kafka의 복제가 데이터의 기본 DR 메커니즘이지만).
  • 스와핑 비활성화: Kafka 브로커 머신에서 vm.swappiness=0 또는 swapoff -a를 확인합니다.
  • 파일 디스크립터 제한 증가: Kafka 사용자에 대해 높은 ulimit -n(예: 128000 이상)을 설정합니다.

브로커 복구 후

브로커가 시작되는 즉시 인시던트를 종료하지 마십시오. 복제본이 따라잡았는지, 오프라인 상태로 남아 있는 파티션이 있는지, 소비자가 정상적으로 복구되고 있는지 확인하십시오.

kafka-topics.sh --bootstrap-server <bootstrap-host>:9092 --describe --under-replicated-partitions
kafka-consumer-groups.sh --bootstrap-server <bootstrap-host>:9092 --all-groups --describe

또한 정확한 첫 번째 실패 신호를 기록하십시오. "브로커가 다운되었습니다"는 근본 원인이 아닙니다. "로그 디렉터리 /data2/kafka가 I/O 오류를 반환한 후 브로커가 중지되었습니다"는 다음 유지 관리 기간 동안 예방, 모니터링 및 테스트할 수 있는 것입니다.