환경: Ubuntu 24.04 LTS / Apache Kafka 3.x
Kafka는 기본 OS 설정만으로도 동작하지만, 운영 환경에서 안정성과 처리량을 끌어올리려면 커널 파라미터와 파일시스템 옵션을 튜닝해야 합니다. 이 글은 설치 전 체크리스트로 활용할 수 있도록 구성했습니다.
1. 메모리 & 가상 메모리
Kafka는 메시지를 JVM 힙이 아닌 OS 페이지 캐시에 의존해 읽기/쓰기 성능을 냅니다. 프로듀서가 쓴 메시지는 페이지 캐시에 올라가고, 컨슈머가 빠르게 소비하면 디스크를 거치지 않고 캐시에서 바로 읽힙니다. 이 구조 덕분에 Kafka는 높은 처리량을 낼 수 있지만, 페이지 캐시가 Swap으로 밀려나거나 더티 페이지가 한꺼번에 플러시되면 지연 스파이크(latency spike)가 발생합니다.

vm.swappiness
# 권장값
vm.swappiness=1
메모리가 부족할 때 얼마나 적극적으로 Swap을 사용할지 결정합니다 (0~100). 기본값(60)은 메모리 여유가 있어도 Swap을 사전에 활용합니다.
Kafka 브로커에서 페이지 캐시가 Swap으로 밀려나면 처리 지연이 급격히 올라가므로, 1로 설정해 Swap 사용을 최소화합니다. 0으로 설정하면 메모리가 부족할 때 OOM Killer가 프로세스를 강제 종료할 수 있어 권장하지 않습니다.
vm.dirty_background_ratio / vm.dirty_ratio
# 권장값
vm.dirty_background_ratio=5
vm.dirty_ratio=60
| 파라미터 | 역할 |
vm.dirty_background_ratio |
전체 메모리 대비 더티 페이지 비율. 이 값을 초과하면 백그라운드 플러시 시작 |
vm.dirty_ratio |
이 값을 초과하면 쓰기 프로세스를 블로킹하고 강제 플러시 |

dirty_ratio가 너무 낮으면 플러시가 잦아져 디스크 I/O 부담이 커집니다. 반대로 너무 높으면 장애 시 유실 가능한 더티 페이지가 많아지고, 한꺼번에 플러시될 때 지연 스파이크가 발생합니다.
Kafka는 복제를 통해 내구성을 보장하므로, dirty_ratio를 다소 높게 잡아 플러시 빈도를 줄이는 방향이 유리합니다.
vm.max_map_count
# 권장값
vm.max_map_count=262144
프로세스가 생성할 수 있는 메모리 맵(mmap) 영역의 최대 수입니다. Kafka는 세그먼트 파일과 인덱스 파일을 mmap으로 매핑하는데, 파티션 수가 많아질수록 필요한 mmap 수도 함께 늘어납니다.
기본값(65530)을 그대로 두면 파티션이 많은 환경에서 Too many open files 또는 mmap 한계 오류가 발생할 수 있습니다.
vm.overcommit_memory
# 권장값
vm.overcommit_memory=1
| 값 | 동작 |
0 (기본) |
휴리스틱 기반으로 오버커밋 허용 여부 결정 |
1 |
항상 오버커밋 허용 |
2 |
오버커밋 금지 |
Kafka JVM은 시작 시 대용량 메모리를 한 번에 예약합니다. 기본값(0)에서는 커널이 이를 거부해 JVM 시작 자체가 실패할 수 있습니다. 1로 설정하면 JVM의 메모리 예약을 허용하고, 실제 사용 시점에 물리 메모리를 할당합니다.
2. 디스크 & 파일시스템
Kafka의 쓰기 성능은 디스크 I/O 효율에 직결됩니다. 파일시스템 선택과 마운트 옵션만으로도 체감할 수 있는 차이가 납니다.
XFS 사용 권장
Kafka 공식 문서와 실무에서 XFS를 권장합니다.
| 파일시스템 | 특징 |
| XFS | 대용량 파일, 순차 쓰기에 최적화. 메타데이터 잠금 경합이 적어 Kafka 세그먼트 파일에 유리 |
| ext4 | 범용적이지만 대용량 파일 처리 시 XFS 대비 메타데이터 오버헤드 발생 |
# XFS 포맷 후 마운트
mkfs.xfs /dev/sdb
mount /dev/sdb /data/kafka
noatime 마운트 옵션
# /etc/fstab 예시
/dev/sdb /data/kafka xfs defaults,noatime 0 0
기본 마운트 옵션은 파일을 읽을 때마다 최종 접근 시간(atime)을 디스크에 기록합니다. Kafka는 세그먼트 파일을 지속적으로 읽기 때문에, 이 atime 업데이트가 불필요한 쓰기 I/O를 대량으로 유발합니다.
noatime을 설정하면 이 불필요한 쓰기를 제거해 I/O 부하를 줄일 수 있습니다.
참고:
relatime(많은 배포판의 기본값)은 atime 업데이트 빈도를 줄여주지만,noatime보다 효과가 작습니다.
3. 네트워크
Kafka는 프로듀서, 컨슈머, 브로커 간 복제 트래픽이 모두 네트워크를 통해 흐릅니다. 소켓 버퍼 크기와 백로그 설정이 처리량과 연결 안정성에 직접적인 영향을 줍니다.
네트워크 버퍼 파라미터는 계층 구조로 동작합니다. 상위 레이어의 설정이 하위 레이어의 상한선이 되므로, OS 레벨 상한선을 먼저 충분히 확보해야 Kafka 설정이 실제로 적용됩니다.

OS 소켓 버퍼 (전체 상한선)
# 권장값
net.core.wmem_default=131072
net.core.rmem_default=131072
net.core.wmem_max=2097152
net.core.rmem_max=2097152
| 파라미터 | 설명 |
net.core.wmem_default |
소켓 송신 버퍼 기본 크기 (bytes) |
net.core.rmem_default |
소켓 수신 버퍼 기본 크기 (bytes) |
net.core.wmem_max |
소켓 송신 버퍼 최대 크기 (상한선) |
net.core.rmem_max |
소켓 수신 버퍼 최대 크기 (상한선) |
net.core.*는 모든 소켓 유형(TCP 포함)에 적용되는 OS 레벨 상한선입니다. Kafka의 socket.send.buffer.bytes / socket.receive.buffer.bytes는 이 값을 초과할 수 없으므로, OS 최대값을 먼저 충분히 확보해야 합니다.
TCP 소켓 버퍼 (TCP 특화)
# 권장값 (최솟값 / 기본값 / 최댓값, bytes)
net.ipv4.tcp_wmem=4096 65536 2097152
net.ipv4.tcp_rmem=4096 65536 2097152
| 파라미터 | 설명 |
net.ipv4.tcp_wmem |
TCP 송신 버퍼 크기 범위 (최솟값 / 기본값 / 최댓값) |
net.ipv4.tcp_rmem |
TCP 수신 버퍼 크기 범위 (최솟값 / 기본값 / 최댓값) |
net.core.*가 OS 전체 상한선이라면, net.ipv4.tcp_*는 TCP 소켓에 특화된 버퍼 범위입니다. 커널이 네트워크 상태에 따라 이 범위 안에서 자동으로 버퍼 크기를 조정합니다.
TCP Window Scaling
# 권장값
net.ipv4.tcp_window_scaling=1
수신 윈도우 크기를 65535 bytes(64KB) 이상으로 확장할 수 있게 해주는 RFC 1323 기능입니다. 대부분의 최신 커널에서 기본값이 1(활성화)이지만, 명시적으로 설정해두는 것을 권장합니다. 고처리량 Kafka 환경에서 이 값이 0이면 네트워크 대역폭을 충분히 활용하지 못합니다.
TCP SYN 백로그 & 네트워크 수신 큐
# 권장값
net.ipv4.tcp_max_syn_backlog=4096
net.core.netdev_max_backlog=5000
| 파라미터 | 설명 |
net.ipv4.tcp_max_syn_backlog |
accept() 전 SYN 연결 요청 대기 큐 크기 |
net.core.netdev_max_backlog |
NIC → 커널 패킷 수신 큐 최대 크기 |
Kafka 브로커는 프로듀서, 컨슈머, 브로커 간 복제 연결을 동시에 다량으로 처리합니다. 브로커 재시작 시나 트래픽 급증 시 SYN 큐가 가득 차면 연결 요청이 드롭됩니다. netdev_max_backlog는 패킷 수신 속도가 처리 속도를 초과할 때 패킷 드롭을 방지합니다.
4. 설정 적용 방법
임시 적용 (재부팅 시 초기화)
sysctl -w vm.swappiness=1
sysctl -w vm.dirty_background_ratio=5
sysctl -w vm.dirty_ratio=60
sysctl -w vm.max_map_count=262144
sysctl -w vm.overcommit_memory=1
sysctl -w net.core.wmem_default=131072
sysctl -w net.core.rmem_default=131072
sysctl -w net.core.wmem_max=2097152
sysctl -w net.core.rmem_max=2097152
sysctl -w net.ipv4.tcp_wmem="4096 65536 2097152"
sysctl -w net.ipv4.tcp_rmem="4096 65536 2097152"
sysctl -w net.ipv4.tcp_window_scaling=1
sysctl -w net.ipv4.tcp_max_syn_backlog=4096
sysctl -w net.core.netdev_max_backlog=5000
영구 적용 (/etc/sysctl.d/99-kafka.conf)
# /etc/sysctl.d/99-kafka.conf
# 메모리
vm.swappiness=1
vm.dirty_background_ratio=5
vm.dirty_ratio=60
vm.max_map_count=262144
vm.overcommit_memory=1
# 네트워크 - OS 소켓 버퍼
net.core.wmem_default=131072
net.core.rmem_default=131072
net.core.wmem_max=2097152
net.core.rmem_max=2097152
# 네트워크 - TCP
net.ipv4.tcp_wmem=4096 65536 2097152
net.ipv4.tcp_rmem=4096 65536 2097152
net.ipv4.tcp_window_scaling=1
net.ipv4.tcp_max_syn_backlog=4096
net.core.netdev_max_backlog=5000
# 적용
sysctl -p /etc/sysctl.d/99-kafka.conf
디스크 영구 마운트 (/etc/fstab)
/dev/sdb /data/kafka xfs defaults,noatime 0 0
5. 체크리스트 요약
| 항목 | 권장값 | 적용 |
vm.swappiness |
1 |
☐ |
vm.dirty_background_ratio |
5 |
☐ |
vm.dirty_ratio |
60 |
☐ |
vm.max_map_count |
262144 |
☐ |
vm.overcommit_memory |
1 |
☐ |
| 파일시스템 | XFS | ☐ |
| 마운트 옵션 | noatime |
☐ |
net.core.wmem_default |
131072 |
☐ |
net.core.rmem_default |
131072 |
☐ |
net.core.wmem_max |
2097152 |
☐ |
net.core.rmem_max |
2097152 |
☐ |
net.ipv4.tcp_wmem |
4096 65536 2097152 |
☐ |
net.ipv4.tcp_rmem |
4096 65536 2097152 |
☐ |
net.ipv4.tcp_window_scaling |
1 |
☐ |
net.ipv4.tcp_max_syn_backlog |
4096 |
☐ |
net.core.netdev_max_backlog |
5000 |
☐ |
참고
- Apache Kafka 공식 문서 - OS 권장 설정
- 카프카 핵심 가이드 (Kafka: The Definitive Guide)
- Kafka 브로커 핵심 매개변수 레퍼런스 (이전 포스트)
작성 기준: Ubuntu 24.04 LTS / Apache Kafka 3.x / 오탈자·수정 제안은 댓글로 남겨주세요
'Data > Kafka' 카테고리의 다른 글
| [Kafka] 카프카 프로듀서 완전 정복 2편 — 설정, 파티션 전략, 인터셉터, 쿼터 (0) | 2026.06.04 |
|---|---|
| [Kafka] 카프카 프로듀서 완전 정복 1편 — 구조, 전송, 시리얼라이저 (0) | 2026.06.04 |
| [Kafka] 브로커 핵심 매개변수 레퍼런스 (0) | 2026.06.03 |
| [Kafka] 메시지 신뢰성 보장 — At-most-once, At-least-once, Exactly-once (0) | 2026.05.14 |
| [Kafka] 카프카(Kafka)는 어떻게 메시지를 잃지 않는가 (0) | 2026.05.14 |