카프카 운영 - 새 장비의 디스크 부족 경고

얼마전부터 카프카 운영을 일부 담당하기 시작했습니다. 현재 운영 중이신 분들은 여러 번 겪어봤을 상황이지만, 처음 경험하는 입장에서 문제 해결을 위해 시도했던 접근방법을 기록하기 위해 이 글을 작성합니다.

1. 상황

하드웨어 문제로 서비스에서 제외시켰던 카프카 브로커(broker) 노드를 다시 투입했습니다. 복제(replication)이 동작하는 것을 확인 후 얼마 뒤 디스크 사용률이 높다는 경고를 받았습니다. 일반 카프카 브로커의 로그 디렉터리가 50±5% 정도의 사용률이지만, 새로 투입한 장비 - 이하 노드A - 의 로그 디렉터리는 이미 80%를 넘겨서 계속 증가하고 있었습니다.

임시방편: 노드A의 로그 삭제 후 재시작

노드A에 할당된 파티션들의 리더(leader) 파티션의 크기보다 큰 로그에 대해 이상 현상으로 생각하고 빠른 서비스 투입을 위해 임시방편으로 노드A의 로그를 삭제 후 재시작 했습니다. 하지만, 문제는 해결되지 않고 또다시 로그가 계속 증가하는 현상이 발생했습니다.

2. 문제 분석

로그 디렉토리를 좀 더 살펴보았습니다.

2.1 디스크 사용량 확인

df 명령으로 현재 디스크 사용률의 변동을 확인합니다.

$ df -h
...
/dev/sdb1 559G 464G 95G 84% /data1

2.2 파티션 크기 확인

가장 용량이 큰 파일을 찾기 위해 du 명령으로 로그 디렉토리의 폴더 크기를 확인합니다. topic.big 토픽의 37번 파티션이 대부분의 용량을 차지하고 있습니다.

$ du -h /data1/kafka-log/
1.8G /data1/kafka-log/topic.video-24
34G /data1/kafka-log/topic.click-3
...
446G /data1/kafka-log/topic.big-37
488G /data1/kafka-log/

2.3 리플리카와 비교 확인

topic.big 토픽의 37번 파티션의 리플리카와 용량을 비교하기 위해 bin/kafka-topics.sh 스크립트를 사용합니다. 37번 파티션의 리플리케이션 팩터는 2, 리더는 13번 노드임을 확인했습니다.

$ bin/kafka-topics.sh --describe --zookeeper zk.host:2181 --topic topic.big | grep 37
Topic: topic.big Partition: 11 Leader: 12 Replicas: 12,37 Isr: 12,37
Topic: topic.big Partition: 36 Leader: 37 Replicas: 37,12 Isr: 12,37
Topic: topic.big Partition: 37 Leader: 13 Replicas: 38,13 Isr: 13,38
Topic: topic.big Partition: 61 Leader: 12 Replicas: 12,37 Isr: 12,37
Topic: topic.big Partition: 86 Leader: 37 Replicas: 37,12 Isr: 12,37

동일 파티션의 리플리카끼리 로그 비교

38번 노드는 앞에서 노드A 라고 했고, 13번 노드는 노드B 라고 합시다. 각 노드의 파일 개수와 용량을 확인해보니, 리더 노드인 노드B가 456개 로그를 가진 것에 비해 리플리카 노드인 노드A가 892개로 지나치게 많은 로그와 인덱스 파일을 가지고 있습니다.

노드A

$ ls -1 /data1/kafka-log/topic.log-37 | wc -l
892
$ du -h /data1/kafka-log/topic.log-37
446G /data1/kafka-log/topic.log-37

노드B

$ ls -1 /data1/kafka-log/topic.log-37 | wc -l
456
$ du -h /data1/kafka-log/topic.log-37
227G /data1/kafka-log/topic.log-37

그래서 가장 오래된 로그를 비교해보니 문제의 원인을 확인할 수 있었습니다.

노드A

$ ls -lha /data1/kafka-log/topic-big-37 | head -n 20
total 446G
drwxr-xr-x 2 www www 36K Feb 20 10:34 .
drwxr-xr-x 15 www www 4.0K Feb 20 10:37 ..
-rw-r--r-- 1 www www 8.0K Feb 17 15:28 00000000016962743949.index
-rw-r--r-- 1 www www 1.0G Feb 17 15:28 00000000016962743949.log
-rw-r--r-- 1 www www 8.1K Feb 17 15:30 00000000016963745611.index
-rw-r--r-- 1 www www 1.0G Feb 17 15:30 00000000016963745611.log
-rw-r--r-- 1 www www 8.0K Feb 17 15:32 00000000016964759877.index
-rw-r--r-- 1 www www 1.0G Feb 17 15:32 00000000016964759877.log

노드B

$ ls -lha /data1/kafka-log/topic-big-37 | head -n 20
total 446G
drwxr-xr-x 2 www www 36K Feb 20 10:34 .
drwxr-xr-x 15 www www 4.0K Feb 20 10:37 ..

2.4 분석 결론

로그 디렉토리의 사용량이 계속 증가하는 문제는, 새로 투입한 노드A의 로그가 지워지지 않았기 때문이었습니다. 그런데 남아있는 로그들 중에 절반 가까이가 리더 노드에서는 이미 지워진 로그입니다. 로그 수명(retention)이 지났기 때문이죠. 파티션 리더와 리플라카의 불일치는 로그 수명 관리 방법이 로그 발생 시점이 아니라 로그 기록 시점을 기준으로 동작하기 때문임을 확인할 수 있었습니다.

이미 이슈가 된 문제로 현재 사용하는 카프카 0.10 버전에는 이미 로그 내부에 시간을 기록하고 있습니다. 단! 변경된 로그 삭제 기능은 0.10.1 버전부터 적용입니다.

관련 항목입니다.

3. 해결 방법

리더 파티션이 관리하는 로그보다 더 오래된 로그를 수동으로 지우고 카프카 브로카를 재시작 합니다.

3.1 지울 대상 파일 확인

리더 노드에서 가장 오래된 파일명을 가져와서 노드Afind -newer 명령으로 지울 대상 파일들을 확인합니다.

find /path/of/the/partition -type f ! -newer /path/of/the/partition/the_oldest_file_in_the_partition_leader_node | xargs ls -alh

3.2 오래된 로그 삭제

find /path/of/the/partition -type f ! -newer /path/of/the/partition/the_oldest_file_in_the_partition_leader_node | xargs rm -rf

3.3 카프카 브로커 재시작