Published on

리눅스 디스크 100%? journalctl 로그폭주 10분 차단

Authors

리눅스 서버에서 디스크가 갑자기 100%가 되면 대개 journalctl(정확히는 systemd-journald) 로그가 폭주하는 케이스가 많습니다. 특히 컨테이너 호스트, 인증 실패 루프, 네트워크 드라이버 오류, 어떤 서비스의 무한 재시작 등이 겹치면 초당 수천 줄씩 쌓이면서 /var/log/journal이 순식간에 커집니다.

이 글은 “근본 원인 분석” 이전에, 10분만이라도 로그 폭주를 차단해서 디스크/서비스를 살리는 응급 처치 플로우를 중심으로 설명합니다. 이후 재발 방지를 위한 journald 영구 설정까지 정리합니다.

관련해서 서비스가 계속 재시작되며 로그가 폭증하는 상황이라면 아래 글도 같이 보면 원인 추적에 도움이 됩니다.

증상 확인: 진짜로 journal이 디스크를 먹고 있나

1) 디스크 사용량과 상위 디렉터리 확인

df -h
sudo du -xh /var/log | sort -h | tail -n 30
sudo du -xh /var/log/journal 2>/dev/null | sort -h | tail -n 20

/var/log/journal 또는 /run/log/journal이 비정상적으로 크면 journald 쪽을 의심할 수 있습니다.

2) journal 크기와 디스크 사용량 요약

sudo journalctl --disk-usage

여기서 수 GB 이상이거나, 짧은 시간에 급격히 증가한다면 “로그 폭주” 상황입니다.

3) 지금 당장 어떤 유닛이 미친 듯이 찍는지 보기

# 최근 1분 로그에서 많이 등장하는 유닛 추정
sudo journalctl --since "1 min ago" -o short-unix \
  | awk '{print $NF}' \
  | sort | uniq -c | sort -nr | head -n 20

위는 완벽히 정확한 방법은 아니지만, 응급 상황에서 “대략 어떤 서비스가 폭주 중인지” 감을 잡는 데 유용합니다.

좀 더 직접적으로는 특정 유닛을 찍어서 확인합니다.

sudo journalctl -u your-service.service --since "5 min ago" -n 200

10분 차단 1: 특정 서비스(유닛)만 임시로 멈추기

가장 안전한 응급 처치는 로그를 찍는 주범 서비스만 10분 멈추는 것입니다.

1) 서비스 중지 후 10분 뒤 자동 재시작

sudo systemctl stop your-service.service
sudo systemctl reset-failed your-service.service

# 10분 뒤 자동 시작
sudo systemd-run --on-active=10m --unit=resume-your-service \
  /usr/bin/systemctl start your-service.service
  • systemd-run --on-active=10m은 “10분 뒤 실행”을 systemd 타이머 형태로 만들어줍니다.
  • reset-failed는 실패 상태가 남아 재시작 정책이 꼬이는 것을 줄여줍니다.

2) 서비스가 무한 재시작 중이면 재시작 자체를 잠깐 막기

서비스가 Restart=always 같은 설정으로 계속 튕기며 로그를 쏟는다면, 10분 동안은 재시작을 막는 편이 빠릅니다.

# 재시작 방지(마스킹)
sudo systemctl mask your-service.service

# 10분 뒤 언마스크 + 시작
sudo systemd-run --on-active=10m --unit=unmask-your-service \
  /bin/bash -lc 'systemctl unmask your-service.service && systemctl start your-service.service'
  • mask는 심볼릭 링크로 /dev/null에 연결해 아예 시작을 못 하게 합니다.
  • 응급 상황에서 “재시작 루프”를 강제로 끊는 데 효과적입니다.

10분 차단 2: journald 자체를 잠깐 완화(주의 필요)

서비스를 멈출 수 없고, 일단 디스크를 살려야 한다면 journald 자체의 기록을 10분간 줄이는 선택지가 있습니다. 다만 장애 분석에 필요한 로그까지 줄어들 수 있어 가능하면 서비스 단위 차단이 우선입니다.

1) Rate limit을 일시적으로 강하게 적용

journald는 기본적으로 rate limit이 있지만, 설정에 따라 충분하지 않을 수 있습니다. 런타임에 즉시 반영되는 방식은 제한적이라, 가장 실용적인 방법은 드롭인 설정을 만들고 재시작하는 것입니다.

sudo mkdir -p /etc/systemd/journald.conf.d

cat <<'EOF' | sudo tee /etc/systemd/journald.conf.d/99-rate-limit.conf
[Journal]
RateLimitIntervalSec=10s
RateLimitBurst=200
EOF

sudo systemctl restart systemd-journald

그리고 10분 뒤 원복합니다.

sudo systemd-run --on-active=10m --unit=revert-journald-rate \
  /bin/bash -lc 'rm -f /etc/systemd/journald.conf.d/99-rate-limit.conf && systemctl restart systemd-journald'
  • RateLimitBurst를 너무 낮추면 필요한 로그가 드랍될 수 있습니다.
  • 그래도 디스크 100%로 서비스 전체가 죽는 것보다는 낫다는 판단일 때만 사용하세요.

2) 저장소를 휘발성으로 바꾸는 건 “응급”에선 비추

Storage=volatile로 바꾸면 디스크 대신 /run(메모리 기반)에 저장되어 디스크는 살릴 수 있지만, 서버 메모리 압박과 로그 유실이 커서 운영 환경에서 즉흥적으로 적용하기엔 리스크가 큽니다. (테스트/일시적 복구 시나리오에만 권장)

디스크 즉시 회복: journal 용량 줄이기(삭제)

폭주를 멈췄다면, 이제 디스크 공간을 즉시 확보해야 합니다.

1) 시간 기준으로 오래된 로그 삭제

# 2일보다 오래된 로그 삭제
sudo journalctl --vacuum-time=2d

2) 용량 기준으로 상한선까지 줄이기

# journal 총량을 1G로 맞춤
sudo journalctl --vacuum-size=1G

3) 파일 단위로 강제 정리(최후 수단)

정상적인 vacuum이 너무 느리거나, 디스크가 꽉 차서 다른 작업이 안 될 때는 아래처럼 강제 정리를 고려할 수 있습니다.

sudo systemctl stop systemd-journald
sudo rm -f /var/log/journal/*/*.journal /var/log/journal/*/*.journal~ 2>/dev/null || true
sudo systemctl start systemd-journald
  • 이 방식은 로그를 강제로 날립니다. 장애 분석이 필요하면 먼저 백업을 고려하세요.

원인 추적: “누가” 로그를 폭주시켰나

응급 처치 후에는 반드시 원인을 찾아야 재발을 막을 수 있습니다.

1) 특정 시간대에 어떤 메시지가 반복되는지

sudo journalctl --since "2026-02-24 10:00" --until "2026-02-24 10:10" \
  | head -n 200

# 반복 문자열 카운트(대략적인 패턴 파악)
sudo journalctl --since "10 min ago" \
  | sed 's/[0-9][0-9]*//g' \
  | sort | uniq -c | sort -nr | head -n 30
  • 숫자(포트, PID, 카운터) 같은 변동 요소를 제거하면 반복 패턴이 더 잘 보입니다.

2) 커널 메시지 폭주인지 확인

sudo journalctl -k --since "10 min ago" -n 200

네트워크 드라이버, 디스크 I/O 에러, 파일시스템 경고가 커널 로그로 무한 반복되면 journald가 아니라 “커널 레벨 이슈”일 수 있습니다.

3) 컨테이너 환경이면 stdout 로그 라우팅 확인

Docker 또는 containerd 환경에서는 애플리케이션이 stdout에 과도한 로그를 찍고, 그것이 journald로 흘러 들어가 폭주하는 경우가 많습니다.

  • 애플리케이션 로그 레벨이 debug로 고정되어 있지 않은지
  • 에러 발생 시 retry 루프가 너무 촘촘하지 않은지
  • readiness/liveness 실패로 재시작 루프가 아닌지

이런 유형은 “서비스 무한 재시작”과 결합되기 쉬우니 앞서 소개한 글의 체크리스트가 도움이 됩니다.

재발 방지: journald 영구 설정(권장 프리셋)

응급 대응이 끝났다면, journald가 디스크를 무한정 먹지 않도록 상한선을 걸어두는 게 좋습니다.

/etc/systemd/journald.conf.d/00-limits.conf 같은 드롭인을 만듭니다.

sudo mkdir -p /etc/systemd/journald.conf.d

cat <<'EOF' | sudo tee /etc/systemd/journald.conf.d/00-limits.conf
[Journal]
# 디스크 상한선(환경에 맞게 조정)
SystemMaxUse=2G
SystemKeepFree=1G

# 파일 단위 상한
SystemMaxFileSize=200M

# 런타임(휘발성)도 과도해지지 않게
RuntimeMaxUse=512M

# 기본 rate limit(너무 낮추면 로그 유실)
RateLimitIntervalSec=30s
RateLimitBurst=1000
EOF

sudo systemctl restart systemd-journald
  • SystemMaxUse는 journal이 사용할 총량 상한입니다.
  • SystemKeepFree는 디스크에 최소로 남겨둘 여유 공간입니다.
  • 운영 서버에서는 보통 둘 다 설정하는 편이 안전합니다.

운영 팁: “10분 차단”을 스크립트로 만들어두기

장애 상황에서 타이핑 실수를 줄이려면, 자주 쓰는 10분 차단을 스크립트로 준비해두는 것도 좋습니다.

아래는 유닛을 10분 마스킹하는 간단 예시입니다.

cat <<'EOF' | sudo tee /usr/local/sbin/block-unit-10m
#!/usr/bin/env bash
set -euo pipefail

UNIT="$1"

systemctl mask "$UNIT"

systemd-run --on-active=10m --unit="unmask-${UNIT//./-}" \
  /bin/bash -lc "systemctl unmask '$UNIT' && systemctl start '$UNIT'"

echo "masked $UNIT for 10 minutes"
EOF

sudo chmod +x /usr/local/sbin/block-unit-10m

# 사용 예
sudo /usr/local/sbin/block-unit-10m your-service.service
  • 팀 운영 환경이라면 실행 권한, sudoers, 감사 로그 정책까지 함께 정리하세요.

체크리스트 요약

  • 디스크 100% 직전: journalctl --disk-usage, du -xh /var/log/journal로 확인
  • 주범이 특정 유닛이면: systemctl stop 또는 mask로 10분 차단 + systemd-run --on-active=10m으로 자동 복구
  • 디스크 회복: journalctl --vacuum-size=1G 또는 --vacuum-time=2d
  • 재발 방지: SystemMaxUse, SystemKeepFree, RateLimitIntervalSec, RateLimitBurst를 드롭인으로 고정
  • 근본 원인: 재시작 루프, 인증 실패 루프, 커널 에러 반복, 컨테이너 stdout 로그 과다를 우선 의심

디스크 100%는 보통 “결과”이고, 로그 폭주는 “증상”입니다. 10분 차단으로 숨을 돌린 뒤, 어떤 루프가 로그를 만들어냈는지(재시작, 재시도, 실패 반복)를 끝까지 추적해야 같은 장애를 막을 수 있습니다.