컨테이너 용어 사전
기초control group · 메모리 제한 · CPU 스로틀링

cgroup

자원 사용량을 제한하는 커널 기능. 메모리는 죽이고 CPU는 느리게 만든다.

얼마나 쓰는가를 제한하는 리눅스 커널 기능(control group).

docker run -d --memory=512m --cpus=1.5 --pids-limit=200 myapp
  • memory — 상한을 넘으면 커널이 프로세스를 죽인다 (OOM Killer)
  • cpu — 주기당 실행 시간을 제한한다
  • pids — 프로세스·스레드 수 제한 (fork 폭탄·좀비 누적 방어)
  • io — 디스크 대역폭 제한

메모리와 CPU 는 증상이 완전히 다르다

  • 메모리 초과 — 죽인다 (하드 리밋)

    • 상태 OOMKilled · 종료 코드 137
    • 커널이 SIGKILL 로 죽여 정리 코드가 안 돈다
    • 애플리케이션 로그에 아무것도 안 남는다
  • CPU 초과 — 죽이지 않는다. 다음 주기까지 재운다 (스로틀링)

    • 안 죽는데 응답이 튄다. p99 만 나빠진다

CPU 제한의 진짜 의미

--cpus=1.0 은 '평균 1코어' 가 아니라 '주기당 상한' 이다

  • 기본 주기 100ms 에 100ms 만 쓸 수 있다

멀티스레드 애플리케이션이 순간적으로 4코어를 쓰려 하면

  • 25ms 만에 할당량을 다 쓰고 나머지 75ms 를 강제로 쉰다
  • 평균 사용률은 낮게 보이는데 지연은 튄다
확인 — cgroup 스로틀 통계
  cat /sys/fs/cgroup/cpu.stat
    nr_throttled     스로틀된 주기 수
    throttled_usec   스로틀된 총 시간

nr_throttled 가 계속 늘면 확정이다 "CPU 사용률은 60% 인데 왜 느리지" 의 정체가 대개 이것이다

애플리케이션이 제한을 알아야 한다

cgroup 은 커널 수준 제한이라, 런타임이 인식하지 못하면 호스트 전체 자원을 기준으로 판단한다

  • 스레드 풀 크기를 호스트 코어 수로 잡는다 → 과도한 병렬 → 스로틀
  • 힙 크기를 호스트 메모리 기준으로 잡는다 → OOMKilled

JVM 은 Java 10+ 에서 컨테이너 제한을 인식한다 (UseContainerSupport) -XX:MaxRAMPercentage=75 로 limit 대비 비율로 잡는다 -Xmx 를 직접 주면 limit 이 바뀌어도 안 따라간다

스왑을 함께 잠근다

docker run --memory=512m --memory-swap=512m myapp

--memory-swap 을 --memory 와 같게 두면 스왑을 안 쓴다 안 그러면 메모리를 넘겨도 스왑으로 버티며 극도로 느려진다

  • 죽는 것보다 나쁜 상태가 될 수 있다 (살아 있는데 응답이 없다)

cgroup v1 과 v2

  • v1 — 자원마다 별도 계층 (memory · cpu · blkio …)
    • 경로: /sys/fs/cgroup/memory/... 처럼 나뉘어 있다
  • v2 — 하나의 통합 계층. 파일 이름도 정리됐다
    • memory.max · cpu.max · pids.max

요즘 배포판은 대부분 v2 다 문서나 블로그의 경로가 안 맞으면 버전 차이를 의심한다

  • 확인 — stat -fc %T /sys/fs/cgroup → cgroup2fs 면 v2

컨테이너 안에서 직접 읽는다

cat /sys/fs/cgroup/memory.max      # 메모리 상한 (v2)
cat /sys/fs/cgroup/memory.current  # 현재 사용량
cat /sys/fs/cgroup/cpu.max         # "150000 100000" = 주기 100ms 중 150ms
cat /sys/fs/cgroup/cpu.stat        # nr_throttled · throttled_usec
cat /sys/fs/cgroup/pids.max

애플리케이션이 자기 제한을 알고 싶으면 이 파일을 읽으면 된다 런타임이 자동으로 안 해 주는 언어에서는 직접 읽어 스레드 풀을 정한다

면접 함정

  • "CPU 제한을 넘으면 컨테이너가 죽는다" → 스로틀될 뿐이다. 죽는 것은 메모리다.
  • "메모리 제한만 걸면 안전하다" → 런타임이 그 값을 인식하지 못하면 그대로 초과한다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 컨테이너는 무엇인가 — 결국 프로세스다