Linux 커널 심화 시리즈 전체 목차 | 프로덕션 튜닝과 트러블슈팅
이 글의 핵심
Linux 커널 심화 시리즈 전체 목차: 파일시스템, 프로세스, 메모리, 디스크 관리 4개 고급 주제로 프로덕션 전문가 되기.
시리즈 소개: 내가 읽는 Linux
Linux 커널 심화 시리즈는 운영체제 안쪽을 파고드는 글들이다. 아래 정리는 교과서 식 커리큘럼이 아니라, 내가 “나중에 다시 찾기 쉬우라고” 써 둔 개인용 안내에 가깝다. 파일시스템, 프로세스 스케줄링, 가상 메모리, 블록·디스크 I/O 네 가지로 줄을 세웠고, 프로덕션에서 자꾸 나오는 “디스크는 남는데 쓰기가 막힌다”, “CPU는 한가한데 응답이 느리다”, “갑자기 OOM으로 죽는다” 같은 이야기를 커널 쪽 눈으로 읽는 데 쓰면 된다.
“한 번에 다 이해”하려 하지 말고, 스토리지 → CPU 스케줄 → 메모리 → I/O 순으로 층을 쌓는 편이 낫다. 나머지(네트워크, 보안, 자동화)는 그다음에 같은 사고 틀에 끼워 넣으면 된다.
SRE·DevOps, 백엔드/인프라 쪽이면 perf, bpftrace, sysctl, cgroup으로 가설을 좁히는 연습이 본문과 맞물린다.
이 시리즈가 잘 맞는 편
- 프로덕션 Linux에서 장애·성능이 바로 실적으로 이어지는 역할
- 응용은 쓰는데 VFS·메모리 회수 쪽이 빈 느낌일 때
- cgroup·NUMA·페이지 폴트 이름은 아는데 문장으로 묶기 어려울 때
덜 맞는 편
grep·ssh·systemctl이 아직 어색하면—먼저 셸·권한·패키지 쪽에 손을 익히는 게 낫다.- LKM·드라이버 작성이 목표면 이 시리즈는 동작 이해·운영 쪽이고, 개발 루트는 따로 잡는 게 맞다.
처음 서버 터트렸을 때
초보 때였다. 테스트 서버였지만, “백업은 당연히 있겠지” 수준이었고, 디스크가 빡빡한 상태에서 find로 잡다가 rm 파이프를 한 방에 쏴 버렸다. 권한·경로·대상 디렉터리를 끝까지 확인 안 한 채 말이다. 잠시 뒤 서비스가 조용해졌고, 그때서야 journalctl이 아니라 빈 셸부터 봤다. 복구는 남의 백업 덕에 티 안 나게 끝났다. “운 좋은 사고”였지, 실력이 아니었다.
그때 남은 건 튜닝 팁이 아니라 습관이었다. 가정 → 한 번 읽기 → 느리게라도 되돌릴 수 있는가. 대량 I/O·대량 삭제·대역폭·inode는 캐주얼하게 만지지 말 것. 그 뒤로 systemctl·cgroup·df -i를 읽는 이유는 “멋”이 아니라 다시는 그때 같은 헛발질을 덜 하려는 쪽에 가깝다.
이 시리즈를 읽는 사람에게도, 딱 맞는 도구보다 “왜 터지는지”를 커널·블록·메모리 쪽 말로 붙잡는 연습이 더 오래 남는다고 본다.
이 글에 대한 솔직한 쪽지
systemd 논쟁은 이제 그만 보고 싶다. 2020년대에 들어서도 “init 철학”만 밤새 싸울 바에는, systemctl·유닛·journalctl·Restart 정책을 운영에서 끝까지 쓰는 쪽이 낫다. sysvinit이 그리울 땐 그 환경에서 돌리면 되고, 싫으면 정책으로 “표준은 systemd”밖에 없는 조직이 많다는 것도 사실이다. “진영”이 아니라 장애 때 로그·타임스탬프·depend가 실제로 도움 되느냐로 보는 게 이 인덱스의 기준이다.
시리즈 본문(내가 쓰는 목차)
파일시스템(고급)
#03 파일·inode 내부
읽는 데 대략 30분 안팎(본문 기준), 고급이다. ext4·XFS 온디스크 inode, extent, VFS, 하드 링크, 블록 주소 쪽.
훑을 때: ext4/XFS의 inode가 실제로 어떻게 데이터와 이어지는지, extent가 예전 직접/간접 블록과 뭐가 다른지, df와 df -i로 용량 full vs inode full을 나누는 법. “디스크는 남는데 파일이 안 만들어진다”를 inode·디렉터리·extent로 설명할 수 있으면 이 편의 목적은 달성이다. 사전으로는 POSIX 모델, stat, ls -i, 링크 차이 정도를 두면 읽기 편하다.
프로세스(고급)
#05 프로세스·스케줄러
30분 대, 고급. task_struct, CFS, vruntime, 런큐, NUMA, cgroup CPU.
훑을 때: 커널이 프로세스/스레드를 어떤 구조로 잡는지, CFS vruntime이 “공정”과 지연 사이에서 어떤 트레이드오프를 만드는지, NUMA·친화성, cgroup으로 CPU 쿼터 둘 때 throttling이 지표에 어떻게 찍히는지. top의 load average가 I/O wait인지 CPU 병목인지 cgroup 제한인지 말로 갈라낼 수 있으면 충분하다. ps, nice, chrt, taskset 개략, K8s requests/limits가 cgroup에 붙는다는 감만 있어도 된다.
메모리(고급)
#06 메모리·가상 메모리
30분 대, 고급. MMU, 다단계 페이지 테이블, TLB, Page Fault, ZONE, SLUB, kswapd, OOM, THP, swappiness.
훑을 때: MMU·페이지 테이블·TLB가 성능·격리 둘 다에 왜 쓰이는지, minor/major page fault, COW가 fork·컨테이너·공유에 어떤 의미인지, ZONE·버디·SLUB, kswapd·direct reclaim·OOM, THP·vm.swappiness의 호불호. free -h·/proc/meminfo로 캐시·anon·file을 나눌 수 있으면 OK. 가상/물리 주소, mmap 틀, 컨테이너 memory 제한 측정감 정도.
디스크·블록(고급)
#09 디스크·블록 계층
30분 대, 고급. ext4/XFS journal, blk-mq, I/O scheduler, iostat, blktrace.
훑을 때: 저널·트랜잭션 복구(정전 뒤 일관성), 할당기·단편화, blk-mq·I/O 스케줄러(none, mq-deadline 등)가 지연/처리량에 끼치는 힘, iostat·blktrace로 큐·지연 읽기. iostat -x의 %util·await 등을 “디스크가 나빠서” 한 줄로 못 끊는다는 것까지 이해하면 된다. lsblk, ROTA, NVMe vs SATA의 뉘앙스 정도.
주제를 어디에 꽂을지(개인 색인)
시리즈 본문은 네 편(파일·inode, 프로세스, 메모리, 디스크)에 못 박았다. 아래는 같은 맵에서 IPC·TCP·systemd·SELinux를 어느 축에 붙이는지, 내가 메모로 쓰는 수준의 분류다.
기초: 파일·프로세스
- VFS·inode·경로 → #03 + OS 개론의 dentry
- 스케줄·스레드 → #05 + 사용자 공간
clone/pthread(라이브러리 따라 다름) - 셸·스크립트는 별도 축—자동화는 아래 도구 가이드로
시스템 프로그래밍: 메모리·IPC·시그널
- 가상 메모리·COW → #06
- 파이프·소켓·공유 메모리 → fd·복사 비용·블로킹(본문은 압박·
mmap쪽이 두껍다) - 시그널 → #05 맥락과 겹쳐 읽기
네트워크
- TCP는 블록 I/O와 지연의 문법이 다르다.
ss·tcpdump·conntrack·bpftrace쪽이 자주 붙는다. “언제 sleep 하느냐”는 #05·#06와 교차가 잘 먹힌다.
성능
- CPU →
perf, flame, CFS/throttling·#05 - 메모리 →
vmstat, OOM, cgroup memory, THP·#06 - 디스크 →
iostat,pidstat -d·#09 - eBPF →
bpftrace—고정 지표가 모자를 때
보안
- DAC·capabilities·ns = “뭘 열 수 있나”
- SELinux/AppArmor = “어떤 라벨이 어떤 타입에 닿나”—로그는
audit쪽 - KASLR·SMEP 같은 이야기는 #06이 있으면 왜 경계가 중요한지 말이 쉬워진다(보안 전문 시리즈는 아님).
운영
- 배포·
systemd·이미지 레이어 → 결국 I/O·inode·cgroup - “지연”은 CPU / 메모리 / 디스크 / 네트워크 / 락으로 먼저 쪼갠 뒤, 해당 본문을 연다
내가 돌릴 때 쓰는 순서(참고만)
초·중·고를 따로 표로 나누지 않는다. 대신 첫 바퀴는 보통 #03 → #05 → #06 → #09다. “저장이 어떻게 짜이는가”(#03)에서 “실행/스케줄”(#05), “주소/회수”(#06), “블록 경로”(#09)로 간다. 둘째 바퀴는 장애 유형으로 섞는다: OOM → #06 + cgroup, I/O wait 잦음 → #09, load 높은데 CPU 낮음 → I/O/락/throttling(#05) 쪽.
시스템 프로그래밍으로 깊이 파고 싶으면 C의 open/mmap/epoll을 errno·부분 쓰기까지, Go·Rust는 시스콜·뮤텍 비용이 #05랑 이야기가 통한다. strace로 시스콜을 보며 #06의 “언제 read가 막히나”를 확인해 보는 식.
동일 주제는 관련 시리즈의 C/Go/Rust 인덱스랑 병행해도 좋다.
시리즈에서 반복하는 톤
- 자료구조·경로(
task_struct,mm_struct틀)가/proc같은 데 어떻게 번역돼 찍히는지 - 장애 티켓에서 자주 돌아오는 질문(inode,
%util해석, OOM, throttling)에 맥락을 붙이는 쪽 sysctl·cgroup·THP·스케줄·큐—효과는 워크로드 따라 다르다는 말을 반복해도 싫지 않다- x86/ARM·컨테이너 오버헤드는 같은 말이 다른 H/W에선 다르게 보인다는 전제
실전에서 떠올리는 갈래(고정 루틴 아님)
“디스크 30%인데 작은 파일이 안 붙는다”
inode·dentry 쪽, 할당기/마운트 옵션/쿼터, 컨테이너 overlay의 다른 df 해석. df -h·df -i·(환경 따라) tune2fs·xfs_info, fd 폭주는 lsof—#03 쪽.
“API가 튀는데 CPU는 낮다”
디스크 I/O(iostat·pidstat·#09), 메모리 압박(vmstat·dmesg·#06), cgroup throttling(#05), 락·스케일은 사용자 공간+perf off-cpu.
“빌드/배치 후 OOM”
dmesg의 killed process, OOM score, cgroup, THP/스왑. drop_caches는 튜닝이 아니라 잠깐 실험용—운영에 상시 쓰지 말자는 쪽.
“DB 디스크 latency가 기준을 넘는다”
스케줄러/큐(NVMe+mq에서 none vs mq-deadline 등), 저널 모드와 내구성-성능 트레이드(리스크 감수 수준), 가상화 stall·IOPS cap—iostat만으론 “디스크 나쁨”으로 못 끊는다.
각 글에서 다시 찾는 명령(압축)
옵션은 배포·권한에 따라 다르다. 본문이 본다.
#03 파일·inode
df -hT
df -i
stat /path/to/file
ls -li
# tune2fs -l /dev/sdXN
# xfs_info /mount/point
#05 프로세스·스케줄러
ps auxf
ps -L -o pid,tid,psr,comm
taskset -pc <pid>
mpstat -P ALL 1
# find /sys/fs/cgroup -maxdepth 2 -type f -name cpu.stat
#06 메모리
free -h
vmstat 1
dmesg -T | egrep -i "oom|oom-kill|out of memory|reclaim" || true
head -n 40 /proc/meminfo
sysctl vm.swappiness
#09 디스크·블록
lsblk -o NAME,ROTA,TYPE,SIZE,FSTYPE,MOUNTPOINT
iostat -xz 1
pidstat -d 1 -p <pid>
# blktrace — 테스트·정책 맞을 때만
도구 가이드(bash, vim, systemd, docker)
bash(또는 POSIX 셸)
파이프·리다이렉트·set -euo pipefail—운영 사고 꽤 많이 실패를 삼킨 스크립트에서 온다. find·xargs는 -print0·이스케이프 익힌 다음 대량 rm 자동화. set -x·PS4로 재현 남기기.
vim(또는 표준 편집기)
서버엔 GUI가 없는 경우가 많다. sudoedit로 권한 실수를 줄이는 쪽.
systemd
systemctl·journalctl·Restart=·LimitNOFILE—유닛 경계에서 fd·리소스. 장애 때 status의 Tasks, coredump, OOM—유닛과 커널을 같이 본다. (위 쪽지 참고: 논쟁보다 로그가 도움 되는가.)
docker(OCI)
이미지·overlay2·빌드 캐시 → inode·용량·#03·#09. memory/cpu limit은 같은 cgroup 말투—값 의미는 v1/v2·런타임에 좌우.
실무 쪽 눈높이(한 줄씩)
DevOps/SRE — SLO의 지연이 CPU·메모리·디스크·네트워크·락 중 어디서 오느냐가 1호. 릴리스가 시스콜·힙·스레드를 바꾸면 같은 H/W에서 병목이 바뀐다. 메트릭 + (필요 시) eBPF로 한 번 잡는 지연.
시스템 관리자 — RAID·LVM·스냅·백업이 #03·#09와 맞닿는다. sudo·audit·SELinux—거절은 앱이 아니라 정책·라벨·로그로 끝날 때가 많다. 커널 채널·재부팅·livepatch는 조직 정책 플러그.
“4주·8주” 대신: 내 캘린더에 쓰는 수준
표로 주차·과제를 박아 두지는 않는다. 시간 있을 때 한 편을 읽고, 한 가지만이라도 df -i나 dmesg로 손에 익힌다. 여유 있으면 8주에 가깝게 늘려서 #03+셸, #05+C·Go, #06+perf, #09+bpftrace처럼 가로로 한 번씩 겹쳐 본다. 목표는 “다 읽기”가 아니라, 한 번 재현한 병목에 가설→완화를 메모에 남기는 것.
FAQ
Q. 이 시리즈 누가 봄?
A. SRE, DevOps, 백엔드/인프라, 시스템 쪽 관심 있으면 와도 됨. 프로덕션에서 장애·성능이 진짜 KPI일 때 더 맞음.
Q. 선수 필요해?
A. C는 포인터·구조체 틀 정도, Linux 명령이랑 OS 개론 있으면 덜 헤맴. 셸이랑 /proc 읽기만 먼저 익혀도 체감 큼.
Q. 실무에서 바로 씀?
A. ㅇ. df -i, vmstat, iostat 같은 현장 도구랑 sysctl/cgroup 맥락 같이 감. 다만 “한 방 튜닝”은 워크로드 따라 박살 나기 쉬워서 쟁여 보라는 쪽.
Q. 커널 소스 봐야 돼?
A. 필수는 아님. 구조·함수 집어주는 건 이해용. 직접 패치는 빌드·테스트 별도 루트.
Q. 번호가 03·05·06·09만 있어?
A. 이 블로그에 올라온 본문이 그 네 개로 정리돼 있어서 그럼. 번호 비연속일 수 있음—주제로 인덱스 쓰면 됨.
Q. 네트워크·쿠버·보안은?
A. 직접 깊이 파는 축은 커널·스토리지·스케줄·메모리 쪽. 쿠베는 cgroup·ns·네트워크·CSI로 투영됨. 네트워크는 I/O랑 지연 말투가 달라서 위 색인 쪽 “네트워크”만 보조로 쓰면 됨.
Q. ARM(Graviton 같은 거) 같냐?
A. 큰 틀(MMU, TLB, 스케줄, blk-mq)은 비슷. perf 이벤트·캐시·드라이버는 다름—그 머신에서 perf list·문서로 확인 ㄱ.
Q. 습관 하나만 고르라면?
A. 튜닝·지우기·대량 I/O는 가정→재고→(가능하면) 롤백 같이. “안 커밋한 시도”가 사고 원인인 경우 많음.
관련 시리즈
- C 언어 시리즈 — 시스템 프로그래밍·POSIX API
- Rust 시리즈 — 메모리·FFI 대비
- Go 시리즈 — 고루틴·사용자 공간 스케줄 vs 커널
추천 자료(참고)
책
- 리눅스 커널 내부구조 — 국내 번역 개론~중급
- Understanding the Linux Kernel — (영어) 옛 버전이어도 개념 맵에 씀
온라인
- Linux Kernel Documentation — 공식
- Brendan Gregg’s Blog — 성능·관측
도구
시작은 파일·inode (#03)에서 메타데이터·저장 축을 잡고, #05·#06·#09로 깊이를 더하면 된다. 이 페이지는 교과서가 아니라, 다시 열기 쉬운 개인용 북마크다.
부록: 자주 쓰는 짧은 도구
df -hT, df -i, du --max-depth=1, (환경) tune2fs·xfs_info / uptime, mpstat, pidstat·ps -L / free -h, vmstat 1, dmesg -T / iostat -xz 1, pidstat -d, (고급) blktrace / strace -f -c -p <pid>, (허가 시) perf.
이 짧은 나열만으로도 “어느 축”으로 갈지 첫 10분은 잡는다. 원인-근거-완화는 위 본문·갈래를 차례로 연다.
품질·갱신
- updatedDate — frontmatter
updatedDate는 편집 흐름에 따라 수동 갱신. - readingMinutes — frontmatter 기존 값 유지. 실제로는 실습·되돌아 읽기까지 합치면 더 걸릴 수 있음.
- 링크 —
/blog/...는 빌드 기준. 로컬에선 라우트 확인.
배포 전에는 팀 루틴(git add → commit → push → npm run deploy 등)에 맞추면 됨.