Skip to main content

Load Average와 시스템 부하

아래 내용은 DevOps와 SE를 위한 리눅스 커널 이야기 3장 Load Average와 시스템 부하를 읽고 정리한 내용입니다.

Load Average

vagrant@ubuntu-xenial:~$ uptime
06:01:17 up 2 min, 1 user, load average: 0.01, 0.00, 0.00
# 1분 5분 15분
  • Load Average는 얼마나 많은 프로세스가 실행 중 혹은 실행 대기중이냐를 의미
  • Load Average가 높다면 많은 수의 프로세스가 실행 중이거나 I/O 들을 처리하기 위한 대기 상태에 있다는 것

strace -s 65535 -f -t -o uptime_dump uptime을 uptime 명령어를 분석하자 uptime은 단순히 /proc/loadavg 파일을 열고 위 파일의 내용을 읽어 화면에 출력함을 확인 여기서 그치지 않고 Load Average가 어떻게 계산되는지 커널의 동작을 살펴보기 위해 함수들을 찾아나갑니다.

  1. loadavg_proc_show() 함수
  2. (grep -R get_avnerun ./*) get_avenrun() 함수
  3. (grep -R avenrun ./*) avenrun 배열
  4. calc_global_load() 함수
  5. calc_load_acount_active() 함수

커널의 동작원리를 분석하기 위해 어디서 시작해야 할지 모를 때에는 strace로 시스템 콜을 분석해서 시작점을 찾는 방법이 유용하고 책 본문에서는 위와 같이 grep 명령어로 커널 함수를 찾아 나갑니다.

최종 함수인 cpu_load_account_active()에서 확인한 동작은 매번 Tick 주기마다 깨어나서 현재 CPU의 Run Queue에 있는 nr_running 프로세스 개수와 nr_uninterruptible 프로세스의 개수를 세어서 calc_load_task 변수에 넣어줍니다. 결국 uptime 명령어의 Load Average를 계산하는 방법은 프로세스의 개수를 세는 것입니다.

  • nr_uninterruptible: uninterruptible sleep 상태로, 디스크 혹은 네트워크 I/O를 대기하고 있는 프로세스를 의미하며 이 상태의 프로세스들은 대기하는 동안 Run Queue에서 빠져나와 Wait Queue에 들어가게 됩니다.

vmstat 명령어로 부하를 확인할 수 있는데 여기서 r열은 nr_running 개수를 의미하고 b열은 nr_uninterruptible 개수를 의미합니다.

시스템 부하

vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 3796648 9304 193044 0 0 139 1 31 40 0 1 99 0 0
0 0 0 3796644 9304 193044 0 0 0 0 38 35 0 0 100 0 0
0 0 0 3796644 9304 193044 0 0 0 0 29 30 0 0 100 0 0
0 0 0 3796644 9304 193044 0 0 0 0 38 47 0 0 100 0 0
0 0 0 3796644 9312 193036 0 0 0 12 34 45 0 0 100 0 0
0 0 0 3796644 9312 193044 0 0 0 0 25 31 0 0 100 0 0
  • procs
    • r: running
    • b: blocked
  • swap
    • si (swap in): 디스크로부터 스왑인된 메모리 양
    • so (swap out): 디스크로 스왑아웃된 메모리 양
  • io
    • bi (blocks received from a block device): 블록 디바이스(일반적으로 하드 디스크)로부터 받은 블록의 수, 디스크 읽기 작업
    • bo (blocks sent to a block device): 블록 디바이스로 보낸 블록의 수, 디스크 쓰기 작업
    • 파일을 디스크에서 읽을 때 bi 값 증가, 파일을 디스크에 저장할 때 bo 값 증가
  • system
    • in: 초당 인터럽트 수
    • cs: 초당 컨텍스트 스위치 수

본문에서는 siege를 활용한 부하테스트로 프로세스가 어떤 시스템 자원을 쓰느냐에 따라서 부하가 시스템에 미치는 영향이 다름을 보여주고 Tickless 기반의 CentOS 6.5 커널의 버그를 예시로 Load Average 자체가 잘못 계산되는 것과 이를 비교 및 확인하기 위해 /proc/sched_debug를 확인하여 각 CPU의 Run Queue 상태와 스케줄링 정보를 확인합니다.

vagrant@ubuntu-xenial:~$ cat /proc/sched_debug
Sched Debug Version: v0.11, 4.4.0-210-generic #242-Ubuntu
ktime : 896866.143380
sched_clk : 897473.839002
cpu_clk : 897473.839080
jiffies : 4295116513
sched_clock_stable() : 1
...
dl_rq[0]:
.dl_nr_running : 0

runnable tasks:
task PID tree-key switches prio wait-time sum-exec sum-sleep
----------------------------------------------------------------------------------------------------------
kthreadd 2 11195.961846 157 120 22.405601 6.591547 430365.321560 0 0 /
ksoftirqd/0 3 11195.973921 364 120 631.652051 16.878413 429516.894381 0 0 /
kworker/0:0H 5 6276.198754 4 100 0.050989 0.231853 7410.050987 0 0 /
rcu_bh 8 231.457772 2 120 0.057122 0.001201 0.001200 0 0 /
migration/0 9 0.000000 397 0 0.001291 11.877007 0.001314 0 0 /

여기서 두 가지 교훈을 얻을 수 있는데 하나의 지표로만 모니터링하거나 시스템의 상태를 확인하지 말고 다양한 툴들과 지표를 조합해서 운영해야 하며 Load Average 자체의 절대적인 높음과 낮음은 없으며 현재 시스템에 장착되어 있는 CPU 코어를 기반으로 한 상대적인 값으로 해석해야 합니다.

마지막으로 vmstat 명령어의 s 옵션을 붙여 실행한 결과이며 각 필드가 의미하는 바는 아래와 같습니다.

[ec2-user@ip-172-31-44-96 ~]$ vmstat -s
4013772 K total memory
240412 K used memory
427300 K active memory
1448372 K inactive memory
1959956 K free memory
2704 K buffer memory
1810700 K swap cache
0 K total swap
0 K used swap
0 K free swap
12419 non-nice user cpu ticks
0 nice user cpu ticks
2392 system cpu ticks
16641 idle cpu ticks
2558 IO-wait cpu ticks
0 IRQ cpu ticks
71 softirq cpu ticks
2352 stolen cpu ticks
230337 pages paged in
2718510 pages paged out
0 pages swapped in
0 pages swapped out
480638 interrupts
554888 CPU context switches
1697350914 boot time
10871 forks
  • K total memory: 시스템의 전체 RAM 크기
  • K used memory: 현재 사용 중인 메모리의 양
  • K active memory: 최근에 접근된 페이지로 구성된 메모리의 양
  • K inactive memory: 최근에 사용되지 않은 페이지로 구성된 메모리의 양
  • K free memory: 현재 사용되지 않고 사용 가능한 메모리의 양
  • K buffer memory: 버퍼로 사용되는 메모리의 양, 일반적으로 입출력 연산에 사용
  • K swap cache: 스왑 공간에서 메모리로 얽혀진 데이터를 캐시한 양
  • K total swap: 시스템의 전체 스왑 공간의 크기
  • K used swap: 현재 사용 중인 스왑 공간의 양
  • K free swap: 사용되지 않고 사용 가능한 스왑 공간의 양
  • non-nice user cpu ticks: non-nice 사용자 프로세스가 CPU를 사용한 시간
  • nice user cpu ticks: nice 사용자 프로세스가 CPU를 사용한 시간
  • system cpu ticks: 시스템(kernel) 코드가 CPU를 사용한 시간
  • idle cpu ticks: CPU가 아무 작업도 하지 않고 대기 중인 시간
  • IO-wait cpu ticks: 입출력 연산을 기다리는 동안 CPU가 대기한 시간
  • IRQ cpu ticks: 하드웨어 인터럽트를 처리하는데 사용된 CPU 시간
  • softirq cpu ticks: 소프트웨어 인터럽트를 처리하는데 사용된 CPU 시간
  • stolen cpu ticks: 가상화 환경에서 다른 가상 머신에 의해 도난 당한 CPU 시간
  • pages paged in: 디스크에서 RAM으로 읽혀진 페이지 수
  • pages paged out: RAM에서 디스크로 쓰여진 페이지 수
  • pages swapped in: 스왑 공간에서 RAM으로 읽혀진 페이지 수
  • pages swapped out: RAM에서 스왑 공간으로 쓰여진 페이지 수
  • interrpts: 발생한 인터럽트 수
  • CPU context switches: CPU 컨텍스트 전환의 횟수
  • boot time: 시스템 부팅 이후의 시간(초 단위)
  • forks: 시스템에서 생성된 프로세스 또는 스레드의 수