RHEL 고급 #3 성능 분석 — sar, top/htop, iostat, vmstat, perf
#2 커널 튜닝에서 워크로드에 맞게 튜닝하는 도구를 봤습니다. 이번 글은 그 반대 방향입니다. 머신이 이미 돌고 있는데 느려졌을 때, 어디부터 봐야 할지를 정합니다. top, vmstat, iostat, sar, perf 다섯 도구를 어떤 신호 앞에서 꺼내드는지, 그리고 USE (Utilization , Saturation , Errors) 라는 단순한 체크리스트로 묶어 한 사이클로 다루겠습니다.
RHEL 고급 시리즈에서 이번 글의 위치:
- #1 부팅 프로세스 — GRUB2, dracut, 복구 모드
- #2 커널 튜닝 — sysctl, tuned, kdump
- #3 성능 분석 — sar, top/htop, iostat, vmstat, perf ← 이번 글
- #4 SELinux 고급 — 정책 작성, audit2allow
- #5 보안 강화 — auditd, OpenSCAP, FIPS
- #6 Subscription / Satellite / Insights
- #7 Cockpit으로 GUI 관리와 web console
네 자원과 USE 체크리스트 #
성능 문제는 결국 네 자원 중 하나에서 새는 것입니다.
| 자원 | 무엇을 보나 |
|---|---|
| CPU | 사용률, run queue 길이, context switch |
| Memory | 사용량, swap 활동, page fault |
| Disk I/O | IOPS, throughput, await(응답 시간), util% |
| Network | bandwidth, packet rate, error/drop |
각각에 대해 같은 세 신호를 봅니다 — Brendan Gregg의 USE 방법론.
- Utilization — 자원이 얼마나 쓰이고 있나 (사용률 %)
- Saturation — 자원이 일을 다 못 처리해 큐에 쌓이나
- Errors — 에러가 발생하나
CPU가 바빠 보여도 (U 높음) 큐에 쌓이지 않고 (S 낮음) 에러도 없으면 (E 0) 정상 운영입니다. 반대로 CPU 사용률이 50%인데 run queue가 30이면, 사용률은 평범해 보여도 saturation에서 빨간불이 켜진 상태입니다. 항상 U/S/E 셋을 같이 봐야 진단이 정확해집니다.
첫 시야 — top / htop #
가장 빨리 손에 잡히는 도구입니다. 머신에 들어간 직후 먼저 띄우는 게 표준 절차입니다.
$ top
top - 14:23:15 up 12 days, 4:11, 2 users, load average: 1.52, 0.98, 0.65
Tasks: 312 total, 2 running, 310 sleeping, 0 stopped, 0 zombie
%Cpu(s): 8.3 us, 2.1 sy, 0.0 ni, 88.5 id, 0.7 wa, 0.3 hi, 0.1 si, 0.0 st
MiB Mem : 15891.2 total, 3421.5 free, 8123.4 used, 4346.3 buff/cache
MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 7234.8 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1234 postgres 20 0 1234567 98765 43210 R 45.2 0.6 3:12.45 postgres
...첫 줄 — load average #
load average: 1.52, 0.98, 0.65의 세 숫자는 지난 1분 / 5분 / 15분 동안 평균적으로 실행 가능 상태였던 프로세스 수 입니다.
- CPU 코어 수(예: 4)와 비교 — 4를 넘으면 CPU가 모자란다는 신호
- 1/5/15 추세 — 1분 > 15분이면 부하가 올라가는 중, 반대면 가라앉는 중
- 리눅스의 load average는 R 상태 + D 상태 (uninterruptible sleep, 보통 디스크 IO 대기) 둘 다 포함. 그래서 디스크가 늦으면 CPU가 한가해도 load가 치솟습니다.
CPU 라인 — %Cpu(s) #
| 필드 | 의미 |
|---|---|
us | 사용자 공간 CPU |
sy | 커널 공간 CPU |
ni | nice 값 변경된 프로세스 |
id | idle |
wa | I/O wait — CPU는 한가한데 IO를 기다리는 비율 |
hi / si | hardirq / softirq |
st | steal — 가상화 환경에서 하이퍼바이저가 가져간 시간 |
wa가 높으면 디스크/네트워크 IO가 병목, st가 높으면 (클라우드 인스턴스에서) 노이지 네이버 영향이 의심.
htop — 더 읽기 쉬운 top #
$ sudo dnf install -y htop
$ htop- 코어별 사용률 막대 그래프
- 프로세스 트리 모드 (
F5) - 검색 (
F3), 필터 (F4), kill (F9), nice 변경 (F7/F8) - 마우스 클릭으로 정렬
운영에서는 top이 항상 있다고 가정해야 하지만 (기본 설치), 손에 잡히는 첫 도구로는 htop이 훨씬 빠릅니다.
자주 쓰는 top 단축키 #
| 키 | 동작 |
|---|---|
1 | 코어별로 펼쳐 보기 |
M | 메모리 사용량 순 정렬 |
P | CPU 사용량 순 정렬 |
T | 누적 시간 순 정렬 |
c | 전체 명령행 보기 |
H | 스레드 단위로 펼쳐 보기 |
k | kill 프로세스 |
q | 종료 |
vmstat — CPU,메모리,IO 한 화면 #
$ 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
1 0 0 421888 35420 1234560 0 0 8 23 150 280 3 1 95 1 0
0 0 0 421872 35420 1234560 0 0 0 0 120 240 1 0 99 0 0
2 1 0 421860 35420 1234560 0 0 0 512 185 320 8 2 88 2 0| 컬럼 | 의미 |
|---|---|
r | run queue — 실행 대기 중인 프로세스 수 (CPU saturation) |
b | block — uninterruptible sleep 중인 프로세스 수 (보통 IO 대기) |
si / so | swap in/out (KB/s) — 0이 아니면 메모리 부족 의심 |
bi / bo | block in/out (KB/s) — 디스크 읽기/쓰기 |
in / cs | 초당 인터럽트 / context switch |
us / sy / id / wa / st | top과 동일 |
무엇을 봐야 하나 #
r > CPU 코어 수— CPU saturation. 줄을 서서 기다리는 프로세스가 있음si/so > 0— 페이지가 스왑으로 오가는 중. 메모리 saturationwa가 높고b가 0보다 큼 — 디스크 IO 병목cs가 비정상적으로 높음 — context switch 폭주 (스레드 너무 많음, 락 경합 등)
vmstat 1 한 줄로 네 자원의 상태를 동시에 본다 — 진단의 두 번째 카드입니다.
iostat — 디스크 자세히 #
sysstat 패키지 안에 들어 있습니다.
$ sudo dnf install -y sysstat
$ iostat -xz 1
Linux 5.14.0-... (host) 04/28/2026 _x86_64_ (4 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
5.32 0.00 1.84 2.41 0.00 90.43
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util
nvme0n1 12.34 45.67 234.56 812.34 0.00 2.11 0.00 4.42 0.32 1.45 0.07 19.01 17.79 0.21 1.23
nvme0n1p1 0.00 0.01 0.02 0.05 0.00 0.00 0.00 0.00 0.10 0.50 0.00 8.00 8.00 0.05 0.00-x 확장 통계, -z 활동 없는 장치 숨김, 1 초 간격.
| 컬럼 | 의미 |
|---|---|
r/s / w/s | 초당 read/write 요청 수 (IOPS) |
rkB/s / wkB/s | 초당 read/write 처리량 |
r_await / w_await | 평균 응답 시간 (밀리초) — 큐 대기 + 서비스 시간 |
aqu-sz | 평균 큐 길이 (saturation) |
%util | 디스크가 IO 처리에 쓴 시간 비율 |
무엇을 봐야 하나 #
%util100% 가까움 +aqu-sz가 큼 — 디스크가 포화 상태. SSD라면 IOPS 한계 부근일 수 있음await가 비정상적으로 큼 (HDD: 20ms+, SSD: 5ms+) — 응답 시간 문제rkB/s+wkB/s가 디스크 사양에 가까움 — bandwidth saturation
%util만 보면 오해할 수 있습니다. 최신 NVMe는 병렬 처리가 가능해서 %util 100%가 곧 saturation은 아닙니다. aqu-sz와 await를 같이 봐야 정확합니다.
CPU와 같이 보기 #
$ iostat -xz 1iostat은 첫 단락에 CPU 평균까지 보여줍니다. CPU %iowait가 높고 디스크 %util도 높으면 디스크 병목이 명확해지는 식.
sar — 시간 흐름 #
top/vmstat/iostat은 지금 이 순간을 봅니다. 어제 새벽 3시에 무슨 일이 있었는지는 못 잡아냅니다. 그 시간대 데이터를 추적할 수 있는 도구가 sar입니다. sysstat 패키지가 백그라운드에서 매 10분(기본)마다 시스템 통계를 수집해서 /var/log/sa/에 쌓아둡니다.
$ sudo systemctl enable --now sysstat
$ sudo systemctl status sysstat-collect.timer시간 단위 조회 #
$ sar -u
Linux 5.14.0-... 04/28/2026
00:00:01 AM CPU %user %nice %system %iowait %steal %idle
00:10:01 AM all 2.34 0.00 0.81 0.12 0.00 96.73
00:20:01 AM all 3.21 0.00 0.92 0.14 0.00 95.73
...$ sar -u -f /var/log/sa/sa27 # 27일치자원별 옵션 #
| 옵션 | 자원 |
|---|---|
-u | CPU |
-r | 메모리 |
-S | 스왑 |
-b | I/O 전체 |
-d | 디스크별 |
-n DEV | 네트워크 인터페이스 |
-n EDEV | 네트워크 에러 |
-q | run queue, load average |
-w | context switch |
-W | 페이지 swap |
시점 한정과 평균 라인 #
$ sar -u -s 09:00:00 -e 11:00:00
# 평균만
$ sar -u -A | grep Average성능 사고가 났을 때 사후 분석의 핵심 도구입니다. 사고 시점에 들어가서 본 게 아니라 사고 이후에 들어가서 보는 용도. top으로는 못 잡아내는 시간대의 행적을 잡아냅니다.
sar 데이터 보존 기간 #
기본값은 28일. /etc/sysconfig/sysstat의 HISTORY=로 늘립니다.
$ sudo sed -i 's/^HISTORY=.*/HISTORY=180/' /etc/sysconfig/sysstat장기 추세 분석이 필요한 운영 머신은 90 ~ 180일로 늘리는 게 표준입니다.
perf — CPU 핫스폿 #
CPU가 바쁜데 어떤 함수에서 시간을 먹는지 알고 싶을 때. 커널 함수까지 포함한 콜스택 단위 프로파일링 도구입니다.
$ sudo dnf install -y perf30초 동안 시스템 전체 프로파일링 #
$ sudo perf record -F 99 -ag -- sleep 30
$ sudo perf report| 옵션 | 의미 |
|---|---|
-F 99 | 초당 99회 샘플링 (HZ와 겹치지 않게 99 권장) |
-a | 모든 CPU |
-g | 콜스택 포함 |
-- sleep 30 | 30초 동안 |
특정 PID #
$ sudo perf record -F 99 -p 1234 -g -- sleep 30
$ sudo perf report결과 보기 #
perf report는 텍스트 인터페이스. 함수별 CPU 시간 비율을 콜스택과 함께 보여줍니다.
+ 45.32% postgres postgres [.] hash_search_with_hash_value
+ 12.45% postgres postgres [.] heap_hot_search_buffer
+ 5.21% postgres libc-2.34.so [.] __memcpy_avx_unaligned_erms
...Flame Graph — 시각화 #
perf report의 텍스트는 깊은 콜스택을 보기 어려운 편입니다. Brendan Gregg의 FlameGraph 도구로 SVG로 변환:
$ sudo perf record -F 99 -ag -- sleep 30
$ sudo perf script > out.perf
$ ./FlameGraph/stackcollapse-perf.pl out.perf > out.folded
$ ./FlameGraph/flamegraph.pl out.folded > flame.svg브라우저에서 flame.svg를 열면 콜스택의 너비가 그대로 시간 비율이 됩니다. 어디가 뜨거운지 한눈에 보임.
묶어서 한 흐름 #
문제가 들어왔을 때 어떤 순서로 도구를 꺼내드는지 한 사이클로 정리.
1. top / htop ← 첫 시야. load avg, CPU/MEM 큰 그림
│
2. vmstat 1 ← r, b, si/so, wa로 CPU,MEM,IO 한 화면
│
3. 자원이 보이면 — 그 자원 전용 도구로 깊이
│
├─ CPU의심 → perf record / report
├─ MEM의심 → free -h, /proc/meminfo, smem
├─ Disk의심 → iostat -xz 1, biotop, iotop
└─ Net의심 → ss -s, sar -n DEV/EDEV, iftop
│
4. 시간 흐름 필요 → sar -u/-r/-d/-n DEV (-f /var/log/sa/sa..)| 신호 | 첫 도구 | 두 번째 도구 |
|---|---|---|
| load avg가 코어 수 초과 | top (r 컬럼이 vmstat에서) | perf record |
wa가 높음 | iostat -xz 1 | iotop 또는 biotop (BCC) |
si/so > 0 | free -h, vmstat | smem, OOM 후보 식별 |
cs 폭주 | pidstat -w 1 | 락 경합 의심, perf로 |
| 어제 새벽 3시 그래프 | sar -u -s 03:00 -e 04:00 -f /var/log/sa/saYY | 같은 시점 다른 자원 sar |
흔한 함정 #
- load average만 보고 CPU 부하라고 단정 — 리눅스 load는 D 상태도 포함. 디스크가 늦으면 CPU가 한가해도 치솟습니다. 항상
vmstat의r과b를 함께 봐야 합니다. %util만으로 디스크 saturation 판단 — NVMe는 병렬 처리를 지원합니다.aqu-sz와await를 함께 봐야 정확합니다.%CPU합계가 100% 를 넘는 게 이상하다 — 정상. top의 기본 표시는 코어 합산이라 4코어면 최대 400%.1키로 코어별 펼쳐 봐야 코어당 사용률이 보입니다.sar활성화 안 함 — RHEL 9는 자동이지만 일부 minimal 설치에서 빠져 있을 수 있습니다. 사고 후에 활성화해도 그 시점 데이터는 못 가져옵니다. 운영 머신은 미리 켜두기.perf record를 운영 트래픽에 길게 — 샘플링 자체가 약간의 오버헤드. 운영 인스턴스에서는 30초 ~ 1분 단위로 끊어서.top의 메모리used를 단순 합산 — buff/cache가 used에 포함된 표기 방식. 실제 가용 메모리는available로 확인해야 합니다.free -h의available컬럼이 신뢰할 수 있는 값.
기억해 둘 명령 #
| 작업 | 명령 |
|---|---|
| 첫 시야 | top 또는 htop |
| CPU/MEM/IO 한 화면 | vmstat 1 |
| 디스크 자세히 | iostat -xz 1 |
| 메모리 진짜 가용 | free -h |
| 프로세스별 CPU/IO | pidstat 1 / pidstat -d 1 |
| 시간 흐름 (오늘) | sar -u, sar -r, sar -d |
| 시간 흐름 (특정일) | sar -u -f /var/log/sa/sa<일> |
| CPU 프로파일링 | sudo perf record -F 99 -ag -- sleep 30 && sudo perf report |
| 네트워크 통계 | ss -s, sar -n DEV 1 |
| 컨텍스트 스위치 | vmstat 1의 cs, pidstat -w 1 |
정리 #
- USE 체크리스트 — Utilization , Saturation , Errors. CPU/MEM/Disk/Network 네 자원에 대해 각각 셋을 본다.
- 첫 카드는 top/htop — load average와 큰 그림. 그다음
vmstat 1으로 네 자원의 상태를 한 화면에. - 자원이 좁혀지면 전용 도구 — Disk는
iostat -xz 1, CPU 핫스폿은perf record, 메모리는free -h+smem. - 시간 흐름은 sar — 사고 후에 들어가서 보는 용도. 보존 기간을 90 ~ 180 일로 늘려두면 장기 추세 분석에 유용.
- 신호를 헷갈리지 말 것 — load avg는 D 포함,
%util은 NVMe에서 saturation 지표로 부족,top메모리used는 buff/cache 포함.
다음 글은 보안 쪽으로 다시 한 번 깊이 들어갑니다. 중급 #1 SELinux 입문에서 본 표준 도구들 너머의 영역 — 정책을 직접 작성하고 audit2allow로 모듈을 만들어 영구 적용 하는 흐름을 다루겠습니다.