2. Load Average 실습

TaekJun Jeong·6일 전

Linux

목록 보기
5/5

Load Average가 무엇인지, 어떤 방식을 통해 계산되는지 정리한 문서입니다.


1편에서는 Load Average가 무엇이고 어떻게 계산되는지를 다뤘습니다.

핵심은 load가 실행 대기(R)와 I/O 대기(D)를 한 숫자에 섞어 담는다는 것이었습니다.

그렇다면 실제로 load가 치솟았을 때, 그 원인이 CPU 경합인지 디스크 I/O 병목인지 어떻게 가려낼 수 있을까요?

이 글에서는 CPU-bound와 I/O-bound 상황을 직접 만들어 load average가 어떻게 달라지는지 관찰하고, vmstat으로 부하의 정체를 진단하는 방법을 실습으로 확인합니다.

실습 환경 준비

항목
호스트dev VM (전용)
vCPU4 → load 4 = 포화 지점 (load ÷ 4 로 해석)
OS / 커널Ubuntu 24.04.4 LTS / 6.8.0-124-generic
idle load0.00, 0.00, 0.00
실습 도구stress-ng, vmstat, pidstat, fio

CPU-bound 재현

# 1. idle 기준선 (5초)
vmstat 1 5

# 2. CPU 부하 - 코어 수(4)만큼, 3분간 백그라운드
stress-ng --cpu 4 --timeout 180s &

# 3. 부하 도는 중 관찰
vmstat 1  # r·us·id·b·wa 확인, 충분히 봤으면 Ctrl+C
uptime    # 1분쯤 / 3분쯤 두 번 찍기


stress-ng로 코어 수(4개)만큼 CPU 부하를 걸자, vmstat의 r(run queue)이 즉시 4로 올라갔습니다.
실행 가능한(R) 태스크 4개가 4개의 코어를 꽉 채운 것입니다.

동시에 us(사용자 CPU)는 100%, id(유휴)는 0으로 떨어졌지만, b(블록된 태스크)wa(iowait)는 계속 0이었습니다.
즉 이 부하는 순수하게 CPU 경합이며 I/O 대기는 전혀 없습니다.

한편 load average는 즉시 4가 되지 않고 서서히 올라갔습니다.
부하 시작 약 1분 뒤 1분 load는 2.76(≈목표 4의 63%), 약 3분 뒤에는 3.83(≈95%) 까지 상승했습니다.

이는 1편에서 본 EWMA의 계단 응답과 정확히 일치합니다.

load average가 실시간 값이 아니라 시정수를 가진 지수 감쇠 추정치임을 실제로 확인할 수 있습니다.



I/O-bound 재현

# 1. 디스크 여유 확인 (파일 만들 거라)
df -h /var/tmp
free -h

# 2. 테스트 디렉토리
mkdir -p /var/tmp/fiotest

# 3. I/O 부하: 캐시 우회(direct) + 동기 읽기, 8병렬, 3분
#    -> 각 워커가 디스크 대기로 D 상태에 빠짐
fio --name=iobound --directory=/var/tmp/fiotest \
    --rw=randread --bs=4k --size=256m --numjobs=8 \
    --direct=1 --ioengine=sync --time_based --runtime=180 \
    --group_reporting > /tmp/fio.out 2>&1 &

# 4. 부하 도는 중 관찰
vmstat 1  # b·wa 확인! (Ctrl+C로 멈춤)
uptime    # load 오르는데 CPU는 노는 거 확인


위 캡쳐에서 bo(블록 쓰기)가 크게 나온 이유는 fio가 테스트 파일을 먼저 생성하는 단계이기 때문.

그래서 bi(읽기)보다 bo(쓰기)가 크게 나왔다.

fio로 8개의 동기 디스크 I/O 워커를 띄우자, CPU-bound와는 정반대 그림이 나왔습니다.

vmstat의 b(블록된 태스크)가 1~3으로 계속 0을 넘었고, wa(iowait)는 25~49%까지 올랐습니다.

반면 us(사용자 CPU)는 0~3%에 불과했고 id(유휴)는 50~75%로, CPU는 대부분 I/O 완료를 기다리며 놀고 있었습니다.

그런데도 load average는 5.55까지 치솟았습니다.

코어가 4개인 시스템에서 load 5.55는 겉보기엔 심각한 과부하지만, CPU는 거의 쉬고 있습니다.

이 부하의 정체는 CPU 경합이 아니라 디스크 I/O 대기(D 상태) 입니다.

1편에서 말한 "load는 CPU 사용률이 아니다" 가 이 한 화면에 그대로 드러납니다.



vmstat으로 정체 판단하기

두 실험을 한 표로 모으면, load라는 하나의 숫자가 실제로 무엇 때문에 올랐는지를 vmstat 몇 개의 칼럼으로 가려낼 수 있습니다.

관찰 항목CPU-boundI/O-bound
load average높음높음
r (run queue)높음 (≈코어 수)낮음
b (blocked)0높음
wa (iowait)0높음
us / idus↑ / id≈0us≈0 / id↑

핵심은 이것입니다.

load average는 R(실행 대기)과 D(I/O 대기)를 한 숫자에 섞어 담기 때문에 그 값만으로는 원인을 알 수 없지만, vmstat의 r·b·wa 세 칼럼이 그 둘을 분리해 줍니다.

  • r이 높다 → 실행 대기(R)가 많다 → CPU-bound
  • b + wa가 높다 → I/O 대기(D)가 많다 → I/O-bound

진단 순서를 정리하자면:



범인 프로세스까지 특정하기 - pidstat

부하의 성격(CPU인지 I/O인지)을 알았다면, 다음은 어떤 프로세스가 원인인지입니다.

pidstat(sysstat 패키지)이 프로세스별로 나눠 보여줍니다.

# CPU-bound일 때 — CPU 먹는 프로세스
pidstat -u 1        # %CPU 높은 놈이 범인

# I/O-bound일 때 — 디스크 때리는 프로세스
pidstat -d 1        # kB_rd/s, kB_wr/s, iodelay 높은 놈이 범인

# 지금 D 상태로 멈춰 있는 프로세스 바로 보기
ps -eo s,pid,comm,wchan | awk '$1=="D"'   # 상태 D + 무엇을 기다리는지(wchan)




Load Average의 한계, 그리고 PSI

지금까지 vmstat로 부하의 정체를 가려냈지만, load average 자체에는 구조적인 한계가 남아 있습니다.

  • 코어 수에 종속적이다 — load 4는 4코어에서는 포화지만 8코어에서는 절반입니다.
    값만 보고는 심각도를 판단할 수 없고, 항상 코어 수로 나눠 해석해야 합니다.
  • R과 D가 한 숫자에 섞인다 — load 5.55가 CPU 경합인지 I/O 병목인지 그 값만으로는 알 수 없어, 우리는 vmstat를 따로 봐야 했습니다.
  • "얼마나 심각하게 멈췄는가"를 알려주지 못한다 — load는 대기 태스크의 개수일 뿐, 시스템이 자원 부족으로 실제로 몇 %의 시간을 정지했는지는 말해주지 않습니다.

바로 이 한계를 메우기 위해 리눅스 커널에는 PSI(Pressure Stall Information) 라는 지표가 있습니다.

PSI는 "대기 태스크가 몇 개인가"가 아니라, 자원(CPU·메모리·I/O) 부족으로 작업이 정지한 시간의 비율(%) 을 직접 측정합니다.

  • load average: 평균 몇 개가 밀려 있었나 (개수, 코어 수에 종속)
  • PSI: 벽시계 시간의 몇 %를 자원 압박으로 멈췄나 (비율, 코어 수와 무관)

즉 load average가 남긴 모호함(무엇 때문에, 얼마나 심각하게) 을 PSI가 정량적으로 보완합니다.

실제로 이 PSI 지표를 수집·시각화하는 관측 파이프라인을 직접 구축한 과정은 아래 글에 정리해 두었습니다.

https://velog.io/@iamtaekjun/PSI-%EC%A7%80%ED%91%9C-%EB%8C%80%EC%8B%9C%EB%B3%B4%EB%93%9C-%EA%B5%AC%EC%B6%95%EA%B8%B0



마치며

두 편에 걸쳐 Load Average를 정리했습니다.

  • 1편 — load는 %가 아니라 대기 작업의 개수이며, CPU(R)뿐 아니라 I/O 대기(D)까지 포함하고, 단순 평균이 아니라 EWMA로 계산된다는 것을 커널 소스까지 확인했습니다.
  • 2편 — CPU-bound와 I/O-bound를 직접 재현해, 같은 "높은 load"라도 vmstat의 r·b·wa로 그 정체를 가려낼 수 있음을 확인했습니다.

Load Average는 시스템에 이상이 있다는 신호를 가장 빠르게 알려주는 지표이지만, 그 신호가 무엇 때문인지까지는 말해주지 않습니다.

uptime으로 이상을 감지하고, vmstat로 정체를 좁히고, pidstat으로 범인을 특정하고, 더 정밀한 관측이 필요하면 PSI로 넘어가는 흐름.

이것이 load라는 익숙한 숫자를 제대로 읽는 방법이라고 생각합니다.

감사합니다.




정택준
Team: https://nangman.cloud/ko
E-mail: taekjunnnn@nangman.cloud

0개의 댓글