본문 바로가기
IT/Linux

[Linux] cgroup vs namespace: 컨테이너 격리의 핵심 비교 분석

by 수누다 2026. 6. 26.

[리눅스 커널] cgroup vs namespace: 컨테이너 격리 핵심 비교

컨테이너 기술을 조금만 깊게 파보면 결국 cgroup vs namespace 이야기로 귀결되더라고요. 저도 처음 Docker를 쓸 때는 그냥 "컨테이너는 가볍고 빠르다" 정도로만 이해했었는데, 실제로 장애를 따라가다 보니 왜 어떤 프로세스는 CPU를 독식하고, 왜 어떤 프로세스는 다른 프로세스 목록을 못 보는지 여기서 갈리더라고요. 쉽게 말해 namespace(네임스페이스, 리소스를 보이는 범위로 분리)는 "무엇을 볼 수 있느냐"를 나누고, cgroup(컨트롤 그룹, 자원 사용량을 제어하는 기능)은 "얼마나 쓸 수 있느냐"를 관리합니다. 이 차이를 이해하면 컨테이너 기술, 격리, 리눅스 커널의 구조가 한 번에 정리됩니다.

실제로 홈랩에서 테스트 환경을 만들다가, 프로세스는 잘 분리됐는데 메모리 제한이 안 먹어서 삽질 좀 했습니다 ㅎㅎ 그때 확실히 느꼈어요. 컨테이너 격리는 한 가지 기능으로 되는 게 아니라, 여러 커널 기능을 조합해서 만들어지는 거였거든요.

cgroup vs namespace 기반 컨테이너 격리 구조를 보여주는 리눅스 커널 아키텍처 이미지

namespace와 cgroup이 각각 어떤 역할로 컨테이너 격리를 만드는지 보여주는 개요 이미지입니다.

1. 왜 cgroup과 namespace를 같이 봐야 할까요?

여기서 중요한 게 있어요. 많은 분들이 컨테이너를 "가벼운 VM"처럼 이해하시는데, 엄밀히 보면 다릅니다. VM은 하이퍼바이저 위에 게스트 OS가 따로 올라가고, 컨테이너는 호스트의 리눅스 커널을 공유합니다. 그러니 격리도 커널 기능에 의존할 수밖에 없죠.

  • namespace: 프로세스가 보는 세계를 분리합니다.
  • cgroup: 프로세스가 쓰는 자원을 제어합니다.
  • capabilities(리눅스 권한 비트 분리), seccomp(시스템 콜 필터링), LSM 계열 기능은 추가 보안 계층으로 붙습니다.

즉, 컨테이너 기술에서 격리는 한 방에 끝나는 개념이 아니라 층층이 쌓이는 구조예요. 저도 처음엔 namespace만 알면 다 되는 줄 알았는데, 운영 환경에서는 cgroup 쪽을 훨씬 자주 보게 되더라고요. 특히 CPU 폭주나 메모리 OOM(Out Of Memory) 이슈는 거의 cgroup 쪽에서 원인을 찾게 됩니다.

2. namespace(네임스페이스) 쉽게 이해하기

쉽게 말해 namespace는 "같은 커널 위에 있지만 서로 다른 방에 들어가 있는 상태"를 만드는 기능입니다. 같은 호스트인데도 프로세스마다 보이는 PID, 네트워크 인터페이스, 마운트 포인트가 달라질 수 있어요.

대표적인 namespace 종류

  • PID namespace: 프로세스 번호 공간을 분리합니다.
  • NET namespace: 네트워크 인터페이스, 라우팅 테이블, 포트를 분리합니다.
  • MNT namespace: 마운트 지점을 분리합니다.
  • UTS namespace: 호스트명, 도메인명 같은 시스템 식별 정보를 분리합니다.
  • IPC namespace: 프로세스 간 통신 자원을 분리합니다.
  • USER namespace: 사용자와 그룹 ID 매핑을 분리합니다.

예를 들어 PID namespace 안에서는 프로세스가 자기 자신을 PID 1로 볼 수도 있어요. 컨테이너 안에서 <code>ps를 쳤을 때 호스트 전체 프로세스가 안 보이는 이유가 바로 이겁니다. 실제로 써보니까 이 개념 하나만 이해해도 "왜 컨테이너 안에서는 세상이 작아 보이는지"가 확 들어오더라고요.

3. cgroup(컨트롤 그룹)은 뭐가 다를까요?

namespace가 시야를 나눈다면, cgroup은 행동 한도를 정합니다. CPU를 얼마나 쓸지, 메모리를 얼마나 먹을지, I/O를 어느 정도까지 허용할지를 관리하는 쪽이죠. 그래서 cgroup은 격리라기보다 제어와 회계(accounting) 관점이 훨씬 강합니다.

운영에서 흔히 보는 상황이 이거예요. 애플리케이션 하나가 메모리를 계속 먹습니다. namespace만 있으면 자기 공간 안에서만 보일 뿐이지, 호스트 메모리는 그대로 압박할 수 있거든요. 반대로 cgroup으로 제한을 걸어두면 그 프로세스 그룹은 정해진 범위를 넘기기 어려워집니다. 장애 대응할 때 이 차이가 꽤 크더라고요.

항목 namespace cgroup
주요 목적 리소스 가시성 분리 자원 사용량 제어 및 계측
핵심 질문 무엇을 볼 수 있나? 얼마나 쓸 수 있나?
예시 다른 PID/네트워크를 못 봄 CPU, 메모리 사용량 제한
영향 범위 프로세스 관점의 논리적 격리 호스트 자원 배분 정책
컨테이너에서의 역할 독립된 환경처럼 보이게 함 과도한 자원 사용을 막음

한 줄 정리: namespace만 있으면 "따로 있는 것처럼 보이는 상태"이고, cgroup까지 있어야 "민폐를 덜 끼치는 상태"가 돼요. 이거 진짜 중요합니다.

4. 실전 구현: namespace부터 직접 확인해보겠습니다

제가 직접 해보니 추상 개념으로만 볼 때보다 unshare로 눈으로 확인하는 게 훨씬 빠르더라고요. 아래 예시는 리눅스에서 새로운 UTS, PID, mount namespace를 만들어보는 흐름입니다.

  1. 현재 호스트 이름과 프로세스 상태를 확인합니다.
  2. unshare로 새 namespace를 만듭니다.
  3. 새 환경 안에서 hostname과 프로세스 목록이 어떻게 달라지는지 봅니다.
hostname
ps -ef | head

sudo unshare --uts --pid --mount --fork bash

hostname container-lab
mount -t proc proc /proc
ps -ef
hostname

여기서 --fork를 주는 이유는 새 PID namespace 안에서 새 프로세스를 시작하기 위해서예요. 그리고 mount -t proc proc /proc를 안 하면 ps 출력이 기대와 다를 수 있거든요. 저도 처음엔 이걸 빼먹어서 "왜 분리 안 됐지?" 하고 한참 봤었습니다.

cgroup vs namespace 실습 중 namespace 분리 셸 구성을 표현한 이미지

namespace 실습 흐름과 분리된 셸 진입 과정을 보여주는 이미지입니다.

현재 시스템의 namespace 확인

lsns

lsns를 보면 현재 시스템에 어떤 namespace가 잡혀 있는지 확인할 수 있어요. 컨테이너 런타임이 떠 있는 서버에서는 생각보다 다양한 namespace가 보이더라고요.

5. 실전 구현: cgroup으로 자원 제한 걸어보기

이제 cgroup입니다. 최근 리눅스 배포판은 보통 cgroup v2 기준으로 보는 게 편해요. 시스템마다 마운트 구조가 조금 다를 수는 있지만, 기본 개념은 비슷합니다. CPU와 메모리 제한을 설정할 수 있고, 프로세스를 특정 cgroup 디렉터리 아래로 넣어 관리하죠.

mount | grep cgroup
cat /sys/fs/cgroup/cgroup.controllers

sudo mkdir /sys/fs/cgroup/demo-limit
echo $$ | sudo tee /sys/fs/cgroup/demo-limit/cgroup.procs

위처럼 현재 셸을 특정 cgroup에 넣을 수 있어요. 다만 실제 제한을 적용하려면 컨트롤러 활성화와 권한 구조를 이해해야 해서, 운영 서버에서는 systemd 기반 도구를 쓰는 편이 안전합니다.

systemd-run으로 메모리 제한 테스트

systemd-run --user --scope -p MemoryMax=200M -p CPUQuota=50% bash

cat /sys/fs/cgroup/$(systemctl --user show --property=ControlGroup --value)/memory.max

환경에 따라 사용자 세션에서 안 될 수도 있어요. 그런 경우는 시스템 범위에서 실행하거나 테스트 VM에서 보는 쪽이 낫습니다. 핵심은 cgroup이 프로세스를 안 보이게 만드는 기능이 아니라, 자원 사용 정책을 강제하는 기능이라는 점이에요.

Docker로 보면 훨씬 익숙해요.

docker run --rm -it --memory=256m --cpus=1 alpine sh

cat /sys/fs/cgroup/memory.max 2>/dev/null || true
cat /sys/fs/cgroup/cpu.max 2>/dev/null || true

컨테이너 런타임은 이런 옵션을 받아 내부적으로 cgroup 설정과 namespace 구성을 함께 처리해요. 우리가 편하게 docker run 한 줄로 쓰는 뒤에서 리눅스 커널이 꽤 많은 일을 하는 셈이죠.

6. cgroup vs namespace 비교를 실무 관점에서 정리해보면

혹시 이런 경험 있으신가요? 컨테이너는 분명 분리돼 있는데, 한 컨테이너가 CPU를 잡아먹어서 같은 노드의 다른 워크로드까지 느려지는 상황 말이에요. 이럴 때 namespace를 아무리 잘 나눠도 해결이 안 됩니다. 반대로 cgroup만 있고 namespace가 약하면 프로세스 시야가 너무 넓어서 격리 체감이 떨어져요.

  • namespace가 강한 상황: 프로세스, 네트워크, 파일시스템 관점에서 독립된 환경처럼 보입니다.
  • cgroup이 강한 상황: noisy neighbor(시끄러운 이웃, 자원 독식 워크로드) 문제를 줄이기 좋습니다.
  • 둘 다 필요: 컨테이너 기술에서 실용적인 격리는 대부분 둘의 조합이에요.

제가 홈랩 쿠버네티스 환경을 만질 때도 결국 보는 건 두 가지였어요. "이 파드는 무엇을 볼 수 있지?" 그리고 "이 파드는 얼마나 먹지?" 질문이 딱 namespace와 cgroup으로 나뉘더라고요.

7. ⚠️ 주의사항과 트러블슈팅

여기서부터는 제가 실제로 많이 헷갈렸던 부분입니다. 처음엔 개념보다 환경 차이 때문에 더 막히더라고요.

1) ps 결과가 기대와 다를 때

PID namespace를 만들었는데도 프로세스가 그대로 보이는 경우가 있어요. 보통 /proc를 새로 마운트하지 않아서 그렇습니다.

mount -t proc proc /proc

2) cgroup 디렉터리는 있는데 제한이 안 걸릴 때

cgroup v1과 v2 차이, systemd 관리 방식, 권한 문제 때문일 수 있어요. 특히 배포판마다 기본 구성이 다르니 무작정 예전 블로그 예제를 복붙하면 안 맞는 경우가 있습니다. 저도 예전 자료 따라 했다가 파일 이름이 달라서 한참 헤맸습니다.

3) 컨테이너 보안과 자원 제어를 같은 문제로 보면 꼬여요

이건 실무에서 꽤 중요한 부분이에요.

  • namespace는 보이는 범위를 줄이는 쪽입니다.
  • cgroup은 성능 안정성과 자원 관리 쪽입니다.
  • seccomp, AppArmor, SELinux 같은 보안 계층은 또 별개입니다.

즉, 보안 사고를 막는 이야기와 리소스 폭주를 막는 이야기를 한 덩어리로 보면 판단이 흐려집니다.

4) USER namespace는 특히 신중하게 봐야 해요

USER namespace는 루트 권한 매핑 문제와 연결되기 때문에 환경에 따라 정책 차이가 커요. 실습은 가능하지만, 운영 서버에서는 배포판 기본 정책과 런타임 설정을 반드시 같이 봐야 합니다.

cgroup vs namespace 비교 중 cgroup v2 자원 제어 구조를 설명하는 이미지

cgroup v2 구조와 자원 제한이 적용되는 핵심 지점을 시각화한 이미지입니다.

8. 검증과 결과 확인

설정은 했는데 실제로 격리가 됐는지 확인을 안 하면 의미가 없죠. 저는 보통 아래처럼 확인합니다.

  1. namespace 분리 여부 확인
  2. cgroup 제한 값 확인
  3. 실제 워크로드를 넣어 동작 확인
lsns

cat /proc/self/cgroup

cat /sys/fs/cgroup/cpu.max 2>/dev/null || true
cat /sys/fs/cgroup/memory.max 2>/dev/null || true

Docker 환경이라면 다음도 자주 봐요.

docker inspect <container_id>
docker stats

검증 포인트는 단순합니다.

  • 프로세스 목록이 호스트와 다르게 보이는가?
  • 호스트명이나 네트워크 인터페이스가 분리되어 보이는가?
  • 메모리/CPU 제한이 파일 시스템이나 런타임 정보에 반영되는가?
  • 부하를 줬을 때 제한 정책이 실제로 동작하는가?

실제로 써보니까, 격리는 "설정했다"보다 "증명했다"가 더 중요하더라고요. 특히 장애 분석 문서 남길 때 이 확인 단계가 있어야 나중에 팀원과 같은 그림을 볼 수 있어요.

cgroup vs namespace 검증 결과를 운영 화면처럼 보여주는 이미지

격리 검증 결과를 확인하는 장면을 담은 이미지입니다.

9. 정리: 컨테이너 기술에서 둘 중 뭐가 더 중요할까요?

제 답은 늘 같습니다. 둘 중 하나가 아니라 둘 다예요. namespace는 컨테이너를 컨테이너답게 보이게 만들고, cgroup은 컨테이너를 운영 가능한 상태로 만들어줍니다. 하나는 시야를 분리하고, 다른 하나는 자원을 통제하죠.

질문 봐야 할 기능 실무 해석
왜 다른 프로세스가 안 보일까? namespace 격리된 실행 환경
왜 메모리가 256MB 이상 못 올라갈까? cgroup 자원 제한 정책
왜 한 컨테이너가 노드 전체를 먹지 못할까? cgroup 멀티테넌시 안정성
왜 컨테이너 안 hostname이 다를까? namespace 독립된 시스템처럼 보이기

저도 처음엔 cgroup vs namespace를 경쟁 관계처럼 외웠었는데, 실제로는 역할 분담에 더 가깝거든요. 그래서 컨테이너 기술을 공부할 때는 둘을 따로 암기하기보다, 하나의 워크로드가 커널 위에서 어떻게 분리되고 제한되는지 흐름으로 보는 게 훨씬 이해가 잘 됩니다.

다음 글에서는 seccomp(시스템 콜 필터링)capabilities(권한 비트 세분화)까지 이어서, 왜 "컨테이너는 격리되지만 완전한 보안 경계로 보면 안 된다"는 말이 나오는지 다뤄볼 예정입니다. 이전 글에서 다룬 Docker 기본 구조와 함께 보시면 더 잘 연결되실 겁니다.

cgroup vs namespace 차이를 한눈에 정리한 비교 인포그래픽 이미지

cgroup과 namespace의 핵심 차이를 요약한 비교 인포그래픽 이미지입니다.

자주 묻는 질문(FAQ)

Q1. namespace만 있으면 컨테이너가 완성되나요?

아니에요. namespace만으로는 자원 제한이 부족합니다. 실무에서는 cgroup, capabilities, seccomp 같은 요소가 함께 들어갑니다.

Q2. cgroup은 보안 기능인가요?

주된 목적은 자원 제어와 계측이에요. 보안에 간접적으로 도움이 될 수는 있지만, 보안 격리 그 자체로 보기엔 부족합니다.

Q3. 리눅스 커널을 공유하면 위험하지 않나요?

맞아요. 그래서 컨테이너는 VM과 다른 보안 모델을 가져요. 격리 수준과 운영 목적을 구분해서 설계해야 합니다.

Q4. 쿠버네티스에서도 결국 같은 원리인가요?

네, 상위 오케스트레이션이 붙어도 아래에서는 리눅스 커널의 namespace와 cgroup 같은 기능을 활용합니다.