- Published on
리눅스 journald 로그 폭주로 디스크 꽉 찰 때 해결
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
운영 중인 리눅스 서버에서 갑자기 디스크 사용량이 치솟고, df -h 에서 루트 파티션이 100%에 가까워지는 상황이 종종 발생합니다. 특히 systemd 기반 배포판에서는 journald 가 바이너리 저널을 /var/log/journal 또는 /run/log/journal 에 쌓기 때문에, 특정 서비스가 에러를 반복하거나 디버그 로그를 과다 출력하면 짧은 시간에 디스크를 잠식할 수 있습니다.
이 글에서는 journald 디스크 점유가 폭주했을 때의 전형적인 증상, 빠른 진단, 안전한 정리 방법, 그리고 재발 방지를 위한 보존 정책과 서비스 레벨 억제까지 한 번에 정리합니다.
1) 증상: 왜 journald 가 디스크를 다 먹나
journald 는 텍스트 로그 파일처럼 줄 단위로 쌓는 것이 아니라, 인덱싱된 바이너리 포맷으로 이벤트를 기록합니다. 기본 설정은 배포판마다 조금씩 다르지만, 대체로 다음 요인에서 폭주가 시작됩니다.
- 애플리케이션이 짧은 주기로 동일 에러를 반복 출력 (예: DB 커넥션 실패 루프)
- 로그 레벨이
debug로 켜진 채 운영 배포됨 - 시스템 단에서 커널 메시지 또는 드라이버 오류가 지속 발생
- 컨테이너 환경에서
stdout로그가 journald 로 흡수되며 폭증
애플리케이션 레벨에서 로그 폭주가 발생하는 패턴은 프론트엔드의 렌더 루프나 백엔드의 재시도 루프처럼 “조건이 충족되지 않는데 계속 반복” 형태인 경우가 많습니다. 원인 규명 방식 자체는 유사하므로, 루프성 폭주 디버깅 관점은 React 렌더 폭주? useEffect 의존성 루프 디버깅 같은 글에서 접근법을 참고해도 도움이 됩니다.
2) 가장 먼저 할 진단: 어디가 얼마나 쓰는지
2.1 journald 전체 사용량 확인
가장 빠른 확인 명령은 아래입니다.
journalctl --disk-usage
출력 예시는 다음과 같습니다.
Archived and active journals take up 8.0G in the file system.
이 수치가 갑자기 커졌다면 journald 가 범인일 가능성이 큽니다.
2.2 저널 저장 위치 확인
저널은 보통 아래 중 하나에 저장됩니다.
- 영구 저장:
/var/log/journal - 휘발 저장:
/run/log/journal
확인은 다음처럼 합니다.
ls -al /var/log/journal
ls -al /run/log/journal
2.3 어떤 유닛이 로그를 폭주시켰는지 찾기
journalctl 로 최근 로그를 유닛별로 확인합니다.
journalctl -u your-service.service -n 200 --no-pager
특정 시간대부터 폭증했다면 시간 범위를 좁혀서 확인합니다.
journalctl --since "2026-02-24 00:00:00" --until "2026-02-24 01:00:00" --no-pager
또는 우선순위가 낮은 로그까지 포함되어 폭주하는지 확인하려면 -p 를 활용합니다.
journalctl -p debug -n 200 --no-pager
3) 급한 불 끄기: journald 디스크 정리
디스크가 꽉 차면 서비스가 연쇄적으로 장애가 날 수 있으니, 먼저 용량을 확보해야 합니다.
3.1 크기 기준으로 정리
예를 들어 저널을 총 1GB 로 줄이려면 아래처럼 실행합니다.
sudo journalctl --vacuum-size=1G
3.2 기간 기준으로 정리
최근 7일만 남기고 지우려면 다음을 사용합니다.
sudo journalctl --vacuum-time=7d
3.3 파일 개수 기준으로 정리
저널 파일을 10개만 남기는 방식도 가능합니다.
sudo journalctl --vacuum-files=10
3.4 즉시 반영을 위한 재시작
정리 후에도 점유가 즉시 줄지 않거나 로테이션이 꼬였다면 journald 를 재시작합니다.
sudo systemctl restart systemd-journald
주의할 점은, 디스크가 100%에 가까운 상태에서는 journald 자체가 쓰기 실패를 반복할 수 있으니, 가능하면 먼저 큰 파일을 줄여 여유 공간을 만든 뒤 재시작하는 것이 안전합니다.
4) 재발 방지 핵심: journald 보존 정책을 명시적으로 설정
폭주가 한 번이라도 있었다면 “기본값에 맡기지 말고” 정책을 고정하는 게 좋습니다. 설정 파일은 보통 /etc/systemd/journald.conf 이며, 배포판에 따라 /etc/systemd/journald.conf.d/*.conf 를 권장하기도 합니다.
4.1 권장 설정 예시
예시는 아래처럼 작성할 수 있습니다.
# /etc/systemd/journald.conf.d/99-retention.conf
[Journal]
Storage=persistent
SystemMaxUse=1G
SystemKeepFree=2G
SystemMaxFileSize=128M
MaxRetentionSec=7day
Compress=yes
Seal=yes
각 옵션의 의미는 다음과 같습니다.
Storage=persistent: 재부팅 후에도 저널 유지. 디스크가 작다면volatile도 고려SystemMaxUse: 저널이 사용할 수 있는 최대 용량SystemKeepFree: 파일시스템에 반드시 남겨둘 여유 공간SystemMaxFileSize: 저널 파일 1개당 최대 크기MaxRetentionSec: 최대 보존 기간Compress: 오래된 저널 압축
설정 적용은 다음으로 합니다.
sudo systemctl restart systemd-journald
운영 팁으로는 SystemKeepFree 를 반드시 잡아두는 것을 권합니다. SystemMaxUse 만 설정하면 “저널은 제한되지만 다른 서비스가 디스크를 다 써버리는” 상황에서 journald 가 여전히 쓰기 실패를 만들 수 있습니다.
5) 로그 폭주의 근본 원인 줄이기: 서비스 레벨에서 막기
journald 정책은 최후의 안전장치이고, 진짜 해법은 폭주를 만든 서비스의 로그를 정상화하는 것입니다.
5.1 반복 재시도 루프와 에러 로그 폭주
예를 들어 DB 커넥션이 고갈되거나 실패하는 상황에서 애플리케이션이 초당 수백 줄의 에러를 쏟아내면 journald 는 금방 커집니다. 이런 경우는 커넥션 풀 고갈, 타임아웃, 재시도 정책이 원인인 경우가 많습니다. 백엔드에서 흔한 진단 흐름은 Spring Boot HikariCP 커넥션 고갈 3분 진단 같은 접근을 참고하면 빠르게 원인을 좁힐 수 있습니다.
실무적으로는 다음을 함께 점검합니다.
- 재시도에 지수 백오프 적용 (고정 주기 재시도 금지)
- 동일 에러의 반복 로깅에 rate limit 적용
- 에러 발생 시 스택트레이스 전체를 매번 찍지 않도록 조정
- 정상 상태로 복귀하면 경고 로그를 줄이도록 상태 기반 로깅 적용
5.2 systemd 유닛에서 로그 레벨과 출력 제어
서비스가 stdout 으로 과도하게 출력한다면, 유닛 파일에서 출력 경로를 조정할 수 있습니다.
# /etc/systemd/system/your-service.service.d/10-logging.conf
[Service]
StandardOutput=journal
StandardError=journal
LogRateLimitIntervalSec=30s
LogRateLimitBurst=200
LogRateLimitIntervalSec와LogRateLimitBurst는 systemd 가 동일 유닛의 로그를 일정량 이상 버스트로 쏟아낼 때 제한을 걸어줍니다.
적용은 다음과 같습니다.
sudo systemctl daemon-reload
sudo systemctl restart your-service.service
배포판 및 systemd 버전에 따라 동작이 다를 수 있으니, 실제 지원 여부는 다음으로 확인합니다.
systemd --version
man systemd.exec
6) 운영에서 자주 하는 실수와 체크리스트
6.1 rm -rf /var/log/journal 로 지워도 되나
권장하지 않습니다. 저널 파일을 강제로 삭제하면 인덱스나 권한, 런타임 상태가 꼬일 수 있습니다. 정리는 journalctl --vacuum-* 계열을 우선 사용하고, 정말로 디렉터리 초기화가 필요하면 아래처럼 서비스 정지 후 처리합니다.
sudo systemctl stop systemd-journald
sudo rm -rf /var/log/journal/*
sudo systemctl start systemd-journald
그래도 가능하면 위 방법은 “마지막 수단”으로만 두는 게 안전합니다.
6.2 디스크가 꽉 찼을 때 자동 복구 스크립트
디스크가 임계치에 도달하면 저널을 자동으로 줄이는 간단한 스크립트를 크론이나 타이머로 돌릴 수 있습니다. 다만 이런 스크립트는 실패 시 더 큰 장애를 만들 수 있으니, set -euo pipefail 같은 방어적 옵션을 권합니다. 관련 패턴은 bash set -euo pipefail로 스크립트 터질 때 대처법 을 참고하세요.
예시 스크립트는 다음과 같습니다.
#!/usr/bin/env bash
set -euo pipefail
threshold=90
used_pct=$(df -P /var | awk 'NR==2 {gsub(/%/,"",$5); print $5}')
if [ "${used_pct}" -ge "${threshold}" ]; then
journalctl --disk-usage
sudo journalctl --vacuum-size=1G
sudo systemctl restart systemd-journald
journalctl --disk-usage
fi
7) 마무리: journald 는 제한하고, 폭주는 원인을 제거
정리하면 대응 우선순위는 다음이 효율적입니다.
journalctl --disk-usage로 journald 점유 확인journalctl --vacuum-size또는--vacuum-time으로 즉시 공간 확보/etc/systemd/journald.conf.d/*.conf로SystemMaxUse와SystemKeepFree를 명시- 폭주를 만든 유닛을 찾아 재시도 정책과 로그 레벨을 정상화하고, 필요하면 systemd rate limit 적용
이렇게 해두면 “한 번의 로그 폭주가 디스크를 가득 채우고, 그로 인해 더 많은 오류 로그가 쌓이는 악순환”을 대부분 끊을 수 있습니다.