서비스 하나가 메모리를 폭주시켜 OOM 킬러가 엉뚱한 프로세스를 죽이고 서버 전체가 흔들린 경험, 운영하다 보면 한 번쯤 만납니다. systemd는 모든 유닛을 cgroup으로 감싸기 때문에, 별도 도구 없이 MemoryMax·CPUQuota 한 줄로 서비스별 자원 상한을 걸 수 있습니다.
진단 — 어떤 유닛이 얼마나 먹나
먼저 유닛별 자원 사용을 봅니다. systemd-cgtop은 cgroup 단위로 실시간 사용량을 보여줍니다.
로컬 터미널
systemd-cgtop # cgroup별 CPU·메모리 실시간
systemctl status myapp.service # 현재 Memory: 항목 확인
OUTPUT
CGroup Tasks %CPU Memory
/system.slice/myapp.service 24 180.0 3.2G
%CPU가 코어 수 곱한 만큼 치솟거나 Memory가 계속 우상향이라면 상한을 거는 게 안전합니다.
개념 — 제한 속성 세 가지
| 속성 | 의미 | 예시 |
|---|---|---|
MemoryMax | 하드 상한. 넘으면 cgroup 내에서 OOM | MemoryMax=512M |
MemoryHigh | 소프트 상한. 넘으면 강한 회수 압박(즉사 아님) | MemoryHigh=400M |
CPUQuota | CPU 사용률 상한(코어 환산 %) | CPUQuota=50% |
실무 권장은 MemoryHigh(완충)와 MemoryMax(최후 방어선)를 함께 거는 것입니다. MemoryHigh로 먼저 회수 압박을 주면 갑작스러운 OOM 없이 부드럽게 눌립니다.
적용 — 즉시 vs 영구
1. 즉시 적용 (런타임, 재시작 불필요)
set-property는 실행 중인 서비스에 곧바로 반영됩니다. 장애 대응 중 급할 때 유용합니다.
서버 터미널
systemctl set-property myapp.service MemoryMax=512M CPUQuota=50%
기본적으로 이 변경은 영구(드롭인 파일 생성)지만, 재부팅 후 유지를 원치 않으면 --runtime을 붙입니다.
2. 영구 적용 (드롭인 파일)
유닛 본체를 건드리지 않고 오버라이드를 만듭니다. systemctl edit가 드롭인 디렉터리를 자동 생성합니다.
서버 터미널
systemctl edit myapp.service
INI
[Service]
MemoryHigh=400M
MemoryMax=512M
CPUQuota=50%
저장 후 적용합니다.
서버 터미널
systemctl daemon-reload
systemctl restart myapp.service
확인 체크리스트
서버 터미널
systemctl show myapp.service -p MemoryMax -p MemoryHigh -p CPUQuota
systemctl status myapp.service # Memory: 항목이 상한 아래인지
systemd-cgtop # 상한 적용 후 실제 사용량
set-property로 급한 불을 끄고, 안정화되면 드롭인 파일로 못 박는 순서가 깔끔합니다.
systemd 유닛 관리와 cgroup 자원 제어를 직접 실습해보고 싶다면 회원가입 없이 무료로 리눅스 트랙에서 시작할 수 있습니다.