Kafka

[Kafka 에러해결] ERROR Shutdown broker because all log dirs in have failed (kafka.log.LogManager)

딸기케잌🍓 2024. 11. 28. 17:09

문제 상황

window 서버에 kafka 3.8.0버전 (2023년 4월에 릴리스)을 설치하고 운영하고 있는데, 주기적으로

ERROR Shutdown broker because all log dirs in [카프카 log 경로] have failed (kafka.log.LogManager) 라는 에러가 나며 카프카가 자동 종료되는 현상

 

다음처럼 로그 파일을 rename할 수 없다는 에러가 발생하고

log4j:ERROR Failed to rename [C:\kafka_2.12-3.8.0/logs/server.log] to [C:\kafka_2.12-3.8.0/logs/server.log.2024-11-19-20].
log4j:ERROR Failed to rename [C:\kafka_2.12-3.8.0/logs/controller.log] to [C:\kafka_2.12-3.8.0/logs/controller.log.2024-11-19-20].
log4j:ERROR Failed to rename [C:\kafka_2.12-3.8.0/logs/controller.log] to [C:\kafka_2.12-3.8.0/logs/controller.log.2024-11-19-21].
log4j:ERROR Failed to rename [C:\kafka_2.12-3.8.0/logs/controller.log] to [C:\kafka_2.12-3.8.0/logs/controller.log.2024-11-19-22].
log4j:ERROR Failed to rename [C:\kafka_2.12-3.8.0/logs/controller.log] to [C:\kafka_2.12-3.8.0/logs/controller.log.2024-11-19-23].

 

 

다른 프로세스가 파일을 사용 중이라 액세스 할 수 없다는 에러가 발생했습니다.

[2024-11-26 20:59:13,132] WARN Failed atomic move of C:\kafka\kafka-logs\__consumer_offsets-25\00000000000000000000.timeindex.cleaned to C:\kafka\kafka-logs\__consumer_offsets-25\00000000000000000000.timeindex.swap retrying with a non-atomic move (org.apache.kafka.common.utils.Utils)
java.nio.file.FileSystemException: C:\kafka\kafka-logs\__consumer_offsets-25\00000000000000000000.timeindex.cleaned -> C:\kafka\kafka-logs\__consumer_offsets-25\00000000000000000000.timeindex.swap: 다른 프로세스가 파일을 사용 중이기 때문에 프로세스가 액세스 할 수 없습니다

 

 

그리고 결국 ERROR Shutdown...을 뿜으며 종료되는 현상이 있었습니다.

[2024-11-26 20:59:13,163] WARN [ReplicaManager broker=0] Broker 0 stopped fetcher for partitions __consumer_offsets-22,__consumer_offsets-30,__consumer_offsets-8,__consumer_offsets-21,__consumer_offsets-4,fcm-push-topic.DLT-0,__consumer_offsets-27,__consumer_offsets-7,__consumer_offsets-9,__consumer_offsets-46,fcm-push-topic-0,__consumer_offsets-25,__consumer_offsets-35,__consumer_offsets-41,__consumer_offsets-33,__consumer_offsets-23,__consumer_offsets-49,jpush-push-topic-0,mps-push-topic.DLT-0,__consumer_offsets-47,__consumer_offsets-16,__consumer_offsets-28,__consumer_offsets-31,__consumer_offsets-36,mps-push-topic-0,__consumer_offsets-42,__consumer_offsets-3,__consumer_offsets-18,__consumer_offsets-37,__consumer_offsets-15,__consumer_offsets-24,__consumer_offsets-38,__consumer_offsets-17,__consumer_offsets-48,jpush-push-topic.DLT-0,__consumer_offsets-19,__consumer_offsets-11,__consumer_offsets-13,__consumer_offsets-2,__consumer_offsets-43,__consumer_offsets-6,__consumer_offsets-14,__consumer_offsets-20,__consumer_offsets-0,__consumer_offsets-44,__consumer_offsets-39,__consumer_offsets-12,__consumer_offsets-45,__consumer_offsets-1,__consumer_offsets-5,__consumer_offsets-26,__consumer_offsets-29,__consumer_offsets-34,__consumer_offsets-10,__consumer_offsets-32,__consumer_offsets-40 and stopped moving logs for partitions  because they are in the failed log directory C:\kafka\kafka-logs. (kafka.server.ReplicaManager)
[2024-11-26 20:59:13,165] WARN Stopping serving logs in dir C:\kafka\kafka-logs (kafka.log.LogManager)
[2024-11-26 20:59:13,171] ERROR Shutdown broker because all log dirs in C:\kafka\kafka-logs have failed (kafka.log.LogManager)

 

 

 

 

방법1 - back slash

윈도우 서버에서는 / 대신 \\ (back slash 2개)를 써야 한다는 글이 있었습니다.

다음의 세 파일의 경로에서 /를 \\로 대치해보았습니다.

  • zookeeper.properties 파일에서 dataDir 경로 수정
  • server.properties파일에서 log.dirs 경로 수정
  • log4j.properties 파일에서 ${kafka.logs.dir}\\server.log 수정

log4j.properties 파일에서는 아래 코드처럼 다음과 같은 부분들에서 모두 \\로 바꿔주어야 합니다.

Line 26: log4j.appender.kafkaAppender.File=${kafka.logs.dir}\\server.log
Line 32: log4j.appender.stateChangeAppender.File=${kafka.logs.dir}\\state-change.log
Line 38: log4j.appender.requestAppender.File=${kafka.logs.dir}\\kafka-request.log
Line 44: log4j.appender.cleanerAppender.File=${kafka.logs.dir}\\log-cleaner.log
Line 50: log4j.appender.controllerAppender.File=${kafka.logs.dir}\\controller.log
Line 56: log4j.appender.authorizerAppender.File=${kafka.logs.dir}\\kafka-authorizer.log

https://stackoverflow.com/questions/68466796/issue-with-log4j-1-2-17-version-while-renaming-kafka-log-files-on-windows

 

 

=> 시도해봤지만 여전히 문제 발생...

 

 

방법2 - log4j 파일 수정

log4j 파일 자체를 수정해야 한다는 중국 블로거 글

https://blog.csdn.net/qq_41600330/article/details/123525153?ydreferer=aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS8%3D

=> 너무 복잡한 방법이라 마지막으로 보류
 
 
 

방법3 - 로그 위치 변경

기본적으로 카프카와 주키퍼 로그는 C:\tmp 하위에 쌓이고 있었는데 tmp 폴더는 리눅스에서 운영체제가 관리하는 폴더라(저는 windows 서버에 설치하긴 했지만....) 변경하라는 글이 있었고, 서버 종료시 지워지니 다른곳으로 하라는 글도 있어서 로그 파일 경로를 새롭게 수정했습니다.
카프카와 주키퍼 로그 모두 다음과 같이 C:\kafka 하위로 모두 변경했습니다.
 

zookeeper.properties

dataDir=\\kafka\\zookeeper

 

server.properties

log.dirs=\\kafka\\kafka-logs

 

https://stackoverflow.com/questions/51644409/kafka-broker-fails-because-all-log-dirs-have-failed

 

=> 동일한 현상 계속 발생..

 

 

방법4 - 카프카 로직 점검

스프링부트 서버 로그를 보니 계속해서 fcm 관련(카프카를 이용해 fcm을 보내고 있음) 로그가 올라오고 있었고, 로직 자체에 문제가 있음을 예상,,,(문제는 나한테 있었다..) (문제는 나한테도 있었다..)

fcm 푸쉬가 실패시 fcm topic과 dlt topic간의 무한 루프가 돌고 있었고, 이를 해결하니 아직 까지는 카프카가 죽지 않음..

 

카프카를 활용한 자체 로직 점검을 해보세요!

 

실제로 무한루프를 해결하니 카프카 서버 자체가 종료되는 일은 아직까지는 재현은 안되고, "Failed to rename"에러만 발생중입니다.ㅠ

log4j:ERROR Failed to rename [C:\kafka_2.12-3.8.0/logs/controller.log] to [C:\kafka_2.12-3.8.0/logs/controller.log.2024-11-26-17].

 

 

 

방법 5 - 카프카 실행 계정에 권한 추가

log4j:ERROR Failed to rename [C:\kafka_2.12-3.8.0/logs/controller.log] to [C:\kafka_2.12-3.8.0/logs/controller.log.2024-11-26-17].

"Failed to rename" 이 에러도 어떻게든 해결하고 싶은 시도방안입니다.

 

ctrl + shift + esc 실행으로 작업 관리자를 열어서 세부정보 탭으로 이동

kafka나 java.exe를 실행중인 사용자 이름을 찾아보면 어떤 계정으로 Kafka를 실행했는지 알 수 있습니다.

터미널에서 kafka 실행 계정의 권한을 변경해줍니다.

icacls C:\kafka\kafka-logs /grant "카프카실행 계정명:(OI)(CI)F"

 

카프카 로그 파일에 읽기/쓰기, 파일/폴더 생셩 및 삭제, 권한 수정, 하위 폴더에 대한 권한을 주었습니다.

 

 

다음의 명령어 실행시 

icacls C:\kafka\kafka-logs

 

다음과 같이 나옵니다.

C:\kafka\kafka-logs 카프카실행 계정명:(OI)(CI)(F)
                    NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
                    BUILTIN\Administrators:(I)(OI)(CI)(F)
                    BUILTIN\Users:(I)(OI)(CI)(RX)
                    BUILTIN\Users:(I)(CI)(AD)
                    BUILTIN\Users:(I)(CI)(WD)
                    CREATOR OWNER:(I)(OI)(CI)(IO)(F)

 

  • (OI): 모든 파일에 권한 상속
  • (CI): 모든 하위 폴더에 권한 상속
  • (F): 전체 권한(Full Control)

 

카프카에 권한을 추가해도 같은 에러는 계속 발생했고, 심지어 카프카가 죽는 현상도 재현되었습니다.. 0_0

이상한게 권한을 준 뒤에 며칠 후 다시 이 명령어로 확인을 해보면,

icacls C:\kafka\kafka-logs

카프카 실행 계정명:(OI)(CI)(F)  <------ 이 부분이 나오지 않더라고요. 이유는 아시는 분은 알려주시면 감사드리겠습니다..

 

방법6 = 방법2

최후의 수단으로 미뤄놨던 방법2의 중국 블로거글 방법밖에는 없다고 생각이 들었습니다..

 

stackoverflow 관련글

https://stackoverflow.com/questions/68466796/issue-with-log4j-1-2-17-version-while-renaming-kafka-log-files-on-windows

 

위 stackoverflow에서 링크건 중국블로거 글

https://blog.csdn.net/qq_41600330/article/details/123525153?ydreferer=aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS8%3D

 

stackoverflow 글을 보면 kafka source, gradle, "apache-log4j-2.20.0-src.tar.gz" 를 다운 받으라고 하는데 결과적으로 필요 없습니다....

제가 설치한 버전 Apache Kafka 3.8.0 기준으로 kafka설치폴더/libs 를 보면 kafka-log4j-appender-3.8.0.jar 파일이 있습니다.

저는 처음에 저 파일을 수정해야 하는줄 알고, 삽질을 조금 했는데요.

java 디코더로 봐도 "ERROR Failed to rename" 이 코드는 보이지 않아서 도대체 어디서 저 에러로그가 나오는지 의문을 품고있었어요.

 

처음엔 stackoverflow에서 말한대로 https://logging.apache.org/log4j/2.x/download.html 이 사이트에서 log4j 최신 버전을 다운받았습니다. 

log4j-1.2.-api 디렉토리 하위의 RollingFileAppender.java를 수정해서 새로운 인스톨한 jar파일로 kafka설치폴더/libs/kafka-log4j-appender-3.8.0.jar 파일을 대치하니 카프카가 기동이 안되었습니다.

 

log4j-core 디렉토리 하위의 RollingFileAppender.java를 수정후 대치해도 같았습니다.

 

ai에게 libs 하위의 파일 목록을 주고 물어보니 reload4j-1.2.25.jar 파일이 Log4j 관련 파일이고, Kafka 3.8.0 버전은 Log4j2가 아닌 reload4j(Log4j1의 fork 버전)을 사용하고 있다고 합니다.

따라서 엉뚱한 Log4j2의 log4j-core-2.24.2.jar를 libs 하위로 옮겨서 호환성 문제가 발생한 것 같습니다.

 

reload4j-1.2.25.jar 이 파일이 핵심 파일이었습니다..이 소스코드를 다운받고 까보니 여기서 "ERROR : Failed to rename..."이라는 로그가 있군요...계속 이게 어디있나 찾고 있었는데!

 

https://repo1.maven.org/maven2/ch/qos/reload4j/reload4j/1.2.25/reload4j-1.2.25.jar 여기서

reload4j-1.2.25-sources.jar    

파일을 클릭해서 다운받습니다.

 

unzip reload4j-1.2.25-sources.jar 하면 org, META-INF 폴더가 생깁니다. IDE로 임포트하고

 

프로젝트루트/
├── src/
│   └── main/
│       └── java/
│           └── org/
│               └── apache/
│                   └── log4j/
│                       └── (소스 파일들)
├── pom.xml

 

위와 같은 구조로 폴더를 맞춰 준후 DailyRollingFileAppender.java를 다음과 같이 수정합니다.

File file = new File(fileName);
boolean result = file.renameTo(target);
if (result) {
    LogLog.debug(fileName + " -> " + scheduledFilename);
} else {
    LogLog.error("Failed to rename [" + fileName + "] to [" + scheduledFilename + "].");
}

위 내용을 아래와 같이 수정합니다.

File file = new File(fileName);
        boolean result = copy(file, target);
        if (result) {
            FileWriter fw = new FileWriter(file);
            fw.write("");
            fw.flush();
            fw.close();
            LogLog.debug(fileName + " -> " + scheduledFilename);
        } else {
            LogLog.error("Failed to rename [" + fileName + "] to [" + scheduledFilename + "].");
        }

        try {
            // This will also close the file. This is OK since multiple
            // close operations are safe.
            this.setFile(fileName, true, this.bufferedIO, this.bufferSize);
        } catch (IOException e) {
            errorHandler.error("setFile(" + fileName + ", true) call failed.");
        }
        scheduledFilename = datedFilename;
    }

    boolean copy(File src, File dst) throws IOException {

        try{
            InputStream in = new FileInputStream(src);
            OutputStream out = new FileOutputStream(dst);

            byte[] buf = new byte[8192];
            int len;
            while((len = in.read(buf)) > 0){
                out.write(buf, 0 ,len);
            }
            in.close();
            out.close();
            return true;
        }catch(FileNotFoundException e){
            LogLog.error("File not found");
            return false;
        }catch (IOException e){
            LogLog.error("IOException");
            return false;
        }

    }

 

mvn clean install하고 새로 생성된 jar 파일로 기존의 reload4j-1.2.25.jar 파일을 대치해주면 이제 에러가 사라졌습니다. 

후..오래걸렸다!