본문 바로가기
카테고리 없음

리눅스 서버 CPU, 메모리 점유율 100%일 때 의심해보아야 할 것들

by 기본기를 다지는 블로그 2025. 3. 10.

 

이번 글에서는 현업에서 종종 접하는 리눅스 서버의 CPU, memory의 high load 이슈의 대응방안으로 고려해볼 것들에 대해 생각해보았습니다.

 

성능을 측정하거나 얼마나 리소스를 소모하는지 모니터링할 수 있는 툴은 매우 다양합니다.

cpu와 메모리가 과점유되면서 시스템이 불안정해지고, 이에 따라 대응할수 있는 방안들과 주로 사용하는 몇가지 툴을 사용 예시로 적어 보았습니다.

 

CPU 점유율 100%일 때 의심할 것들

 

1. 과부하를 유발하는 프로세스 확인 - 특정 프로세스가 CPU를 과도하게 사용하는지 확인

# top -o %CPU
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                        
 343483 root      rt   0  671220 196584  69060 S   0.3  23.7  56:41.04 corosync                                       
      1 root      20   0  183904   9144   7296 S   0.0   1.1   0:37.22 systemd                                        
      2 root      20   0       0      0      0 S   0.0   0.0   0:00.62 kthreadd    
...

# ps -eo pid,ppid,user,%cpu,%mem,cmd --sort=-%cpu | head -n 20
    PID    PPID USER     %CPU %MEM CMD
 343483       1 root      0.3 23.7 /usr/sbin/corosync -f
      1       0 root      0.0  1.1 /usr/lib/systemd/systemd --switched-root --system --deserialize 18
      2       0 root      0.0  0.0 [kthreadd]
      3       2 root      0.0  0.0 [rcu_gp]
...
  • 만약 특정 프로세스가 지속적으로 높은 CPU를 차지하고 있다면, 그 원인을 분석해야 합니다.

 

2. CPU 코어 대비 높은 처리량 확인

# cat /proc/cpuinfo | grep processor | wc -l
8

 

  • 만약 서버의 Core가 8개 보다  runq-sz (15:42:19 : 95)가 높아 평균값의(ldavg) 수가 더 높을 경우 시스템 부하로 간주될 수 있습니다.
# sar -q 
00:00:01      runq-sz  plist-sz   ldavg-1   ldavg-5  ldavg-15
<snip>
14:50:01            0       322      0.07      0.05      0.04
15:20:01            0       331      2.46     53.30     68.72
15:42:19           95       343    109.15    107.25     91.37
16:00:01            0       311     38.94     87.63     98.53
16:10:01            0       297      0.00     11.75     51.62
16:20:01            0       295      0.00      1.56     27.03

 

  • plist-sz : 프로세스 목록에 있는 프로세스 및 스레드 수
    ldavg-1 : 마지막 1분간의 시스템 부하 평균
    ldavg-5 : 지난 5분 동안의 시스템 부하 평균
    ldavg-15 : 지난 15분 동안의 시스템 부하 평균

 

  • 추가적으로 ps 명령으로 부하 상황 상시 확인 - R 또는 D 상태이고 높은 %CPU를 얻고 있는 스레드를 식별합니다.
# ps -eLo pid,tid,stat,wchan=WIDE-WCHAN-COLUMN,comm
# ps auxH

 

  • 부하 평균은 실행 중이거나 실행 가능한 스레드(R)와 중단 불가능한 슬립 스레드(D)에 의해 계산됩니다.
  • 부하 평균이 시스템의 CPU 코어/스레드 수보다 적으면 시스템이 과부하되지 않았으며 작업 부하를 처리할 리소스가 충분함을 나타냅니다. 부하 평균이 CPU 코어/스레드 수보다 높으면 시스템이 처리할 수 있는 것보다 CPU 리소스에 대한 수요가 더 높으며, 이로 인해 성능이 저하되고 응답성이 느려질 수 있습니다.

 

3. 시스템(%sys), 유저(%usr) 영역의 CPU 사용량 확인

mpstat 명령어로 CPU 사용량 중 시스템(%sys) 영과 유저(%usr)  영역이 높은지 확인합니다. 

# mpstat -P ALL 1
04:50:56 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
04:50:57 PM  all    0.00   26.53   43.88   25.51    1.02    1.02    0.00    0.00    0.00    2.04
04:50:57 PM    0    0.00   26.53   43.88   25.51    1.02    1.02    0.00    0.00    0.00    2.04

 

  • %sys 영역의 값이 높다면 시스템에서 사용중인 프로세스(OS 사이드)중 어떤 프로세스가 리소스를 많이 소모하고 있는지 확인이 필요합니다. 이 때는 perf 툴을 이용하여 면밀히 확인할 수 있습니다.
# yum install bzip2 perf kernel-debuginfo-$(uname -r) kernel-debuginfo-common-x86_64-$(uname -r)
# perf record -a -g -- sleep 30
# perf archive

...
# perf report --showcpuutilization --sort comm,overhead -f -i perf.data
Samples: 1M of event 'cpu-clock', Event count (approx.): 360006500000
  Children      Self       sys       usr  Command
+   96.88%    96.88%    90.18%     6.69%  sshd      <-----
     2.08%     2.08%     1.46%     0.62%  sftp-server
     0.21%     0.21%     0.13%     0.08%  bash
     0.17%     0.17%     0.11%     0.06%  BESClient

 

  •  sshd 데몬에서 CPU 리소스를 많이 소모 하고 있네요, 무슨 이유에서 많은 리소스 소모가 일어나는지  sshd에 대한 분석이 필요해 보입니다.

 

  • 또는 mpstat 명령을 통해 $usr (유저스페이스) 가 증가됨이 확인되었다면 pidstat 과 같은 툴을 이용하여 어떤 어플리캐이션에서 CPU를 소모하고 있는지 확인합니다.
# pidstat | sort -k 5 -r
Linux 4.18.0-305.el8.x86_64 (pcs02) 04/03/2025 _x86_64_(1 CPU)
08:45:45 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
08:45:45 PM     0       955    12.03    0.02    0.00    0.29    0.05     0  vmtoolsd
08:45:45 PM     0    343483    0.03    0.01    0.00    0.00    0.04     0  corosync
08:45:45 PM     0      1575    0.02    0.00    0.00    0.03    0.02     0  pcsd
08:45:45 PM     0      1051    0.01    0.00    0.00    0.03    0.01     0  pcsd

 

 

4. 디스크 병목 확인

 

iostat로 디스크 I/O ( utilization ) 문제를 확인합니다.

# iostat -x 1
04/03/2025 04:51:43 PM
Device:       rrqm/s wrqm/s  r/s  w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm  %util
sda             0.00   2.00 10.0 80.0 1000  4000    102.4     2.30  12.3   5.1   97.5

 

  • %util = 97.5 → 디스크가 97.5%의 시간 동안 바쁘게 작업 중
  • 일반적으로 80% 이상이면 병목 가능성 있음

I/O Wait (%iowait) 확인

12:00:00 AM  CPU  %usr  %nice  %sys  %iowait  %irq  %soft  %steal  %guest  %gnice  %idle
12:00:01 AM  all   5.3    0.0   8.2    45.6    2.0    3.2    0.0     0.0     0.0   35.7

 

 

  • %iowait = 45.6% → CPU가 대부분의 시간을 I/O 작업 대기 상태로 보냄
  • %idle 값이 낮지 않다면, CPU는 쉬고 있지만 디스크 응답을 기다리는 상태
  • 디스크 I/O 성능 저하 또는 디스크 병목 가능성 있음

 

 

4. 좀비 프로세스 및 스레드 확인


좀비 프로세스가 다수 생성되어 있는 경우

# ps aux | grep 'Z'

 

 

MEMORY 점유율 100%일 때 의심할 것들

1. 메모리 사용량이 높은 프로세스 확인

  • top 또는 ps 명령어로 메모리를 많이 차지하는 프로세스를 확인합니다.
# top -o %MEM
   1780 gdm       20   0 3887540 244492 124264 S   0.0  13.5   4:04.14 gnome-shell                                    
   2125 gdm       20   0  581668  54096  48080 S   0.0   3.0   0:00.13 ibus-x11      
   
# ps -eo pid,ppid,user,%cpu,%mem,cmd --sort=-%mem | head -n 20
    PID    PPID USER     %CPU %MEM CMD
   1780    1705 gdm       0.0 13.4 /usr/bin/gnome-shell
   2125       1 gdm       0.0  2.9 /usr/libexec/ibus-x11 --kill-daemon

 

2. Out of Memory (OOM) Killer 발생 여부 확인

  • 메모리가 부족하면 커널이 OOM(Out of memory) Killer를 실행해 프로세스를 강제 종료 합니다.
# dmesg 
[Wed Aug 31 16:36:42 2016] Out of memory: Kill process 43805 (keystone-all) score 249 or sacrifice child
[Wed Aug 31 16:36:42 2016] Killed process 43805 (keystone-all) total-vm:4446352kB, anon-rss:4053140kB, file-rss:68kB
[Wed Aug 31 16:56:25 2016] keystone-all invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0
[Wed Aug 31 16:56:25 2016] keystone-all cpuset=/ mems_allowed=0
[Wed Aug 31 16:56:25 2016] CPU: 2 PID: 88196 Comm: keystone-all Not tainted 3.10.0-327.13.1.el7.x86_64 #1

 

3. 캐시 메모리 과다 사용 여부

 

buff/cache가 지나치게 높은 경우, 물론 성능향상을 목적으로 하는 좋은 현상일 수 있겠으나, 메모리 압박 상황에서는 파일 캐시보다 프로세스를 먼저 swapout할 가능성이 있으므로 주의하여야 합니다.

 

마찬가지로 커널이 캐시로서 사용하는 Slab 메모리가 높은 경우도 있습니다.

Slab은 Kernel에 의해서 사용되며, 디렉토리 구조나 inode 정보 등이 저장됩니다. 예를 들어 ls를 실행하는 것으로도 증가됩니다.

 

다음 명령어를 통해 수동으로 slab 캐쉬( Dentry 및 Inode 캐시 포함) 반환도 가능합니다만, 메모리가 필요할 시 커널이 자동으로 캐시를 정리하여 반환시키므로 특별히 문제가 되지는 않습니다.

따라서 일반적인 상황에서는 수동으로 drop_caches를 할 필요는 없습니다.

# echo 2 > /proc/sys/vm/drop_caches
# 만약 drop_cache를 꼭 하셔야 한다면 가급적 백업작업, 높은 IO부하 등이 없는 시점에서 반환 작업을 하시기 바랍니다.

 

다만 drop_caches를 강제로 수행해야할 때가 있을 수 있습니다.

 

일례로 Slab 메모리의 반환이 불가능해서(SUnreclaim) 메모리 사용률이 극단적으로 높게 유지되는 경우가 있었습니다.

계속 Slab이 쌓이면서 반환이 불가능한 경우 커널 버그를 의심해볼 수 있는데, 메모리가 계속 누적이 되므로써 시스템이 불안정해지는 상황이 발생할 수 있습니다. 따라서 강제로 drop_caches를 사용하여 slab 캐쉬를 임시 방편으로 drop 하였습니다.  

drop caches를 해주었음에도 불구하고 Slab이 지속적으로 쌓이고, 반환이 불가능하여 메모리가 계속 높게 유지되는 이슈인 것으로 확인되었고, 커널을 업데이트하고 해소되었습니다.

# cat /proc/meminfo
MemTotal:       32837976 kB
MemFree:         3350844 kB
Buffers:          322212 kB
Cached:          3248944 kB
SwapCached:       120324 kB
Active:          5910876 kB
Inactive:        1430572 kB
Active(anon):    2925684 kB
Inactive(anon):   877612 kB
Active(file):    2985192 kB
Inactive(file):   552960 kB
Unevictable:       48480 kB
Mlocked:           40304 kB
SwapTotal:      32767996 kB
SwapFree:       31062204 kB
Dirty:             28816 kB
Writeback:            88 kB
AnonPages:       3720372 kB
Mapped:            70456 kB
Shmem:             24248 kB
Slab:           21748812 kB  
SReclaimable:   116888 kB    
SUnreclaim:     21631924 kB    <---------

 

 

시스템에 CPU와 메모리 리소스가 과 점유될 때 살펴봐야할 내용들을 정리해 보았습니다.

제가 작성한 내용 외에 성능 분석을 목적으로 하는 많은 툴들이 존재하며 (perf, valgrind, systemtab 등) , 다양한 시각에서 문제를 살펴볼 안목을 키우는것이 중요합니다.