1. 개요
“컨테이너는 가벼운 VM 이다” 라는 설명을 자주 본다. 틀린 말은 아니지만 이 비유 때문에 “그럼 컨테이너 안에서도 커널을 새로 부팅하나?” 같은 오해가 생긴다. 결론부터 말하면 컨테이너는 VM 과 격리를 만드는 층 자체가 다르다. 이번 시리즈에서는 인프라를 다루며 당연히 쓰지만 원리는 잘 안 짚어보는 개념들을 8편에 걸쳐 정리한다. 1편은 그중에서도 가장 기본인 컨테이너와 VM 의 차이다.
2. 핵심 내용
2-1. VM: 하드웨어를 가상화한다
VM 은 하이퍼바이저(KVM, Hyper-V 등)가 CPU, 메모리, 디스크 같은 하드웨어 자원을 흉내 내서 여러 개의 “가짜 컴퓨터”를 만드는 방식이다. 각 VM 은 자기만의 커널을 갖고 완전히 독립적으로 부팅한다. 그래서 격리 수준은 높지만, VM 하나를 띄우려면 커널이 부팅하는 시간(보통 수십 초)과 커널 자체가 쓰는 메모리(수백 MB)가 고정비로 들어간다.
2-2. 컨테이너: 커널은 하나, 보이는 것만 다르다
컨테이너는 하이퍼바이저도, 별도 커널도 없다. 호스트 커널을 그대로 공유하면서, 리눅스 커널의 네임스페이스(namespace) 기능으로 프로세스가 “보는 세계”를 분리한다. 네임스페이스 종류는 여러 개다.
PID— 컨테이너 안에서는 자기 프로세스가 PID 1 이다. 호스트에는 다른 PID 로 보인다.NET— 컨테이너마다 독립된 네트워크 인터페이스, 라우팅 테이블, 포트 공간을 가진다.MNT— 파일시스템 마운트 지점이 분리된다. 컨테이너가/를 봐도 실제로는 이미지 레이어 위다.UTS— 호스트명이 분리된다.IPC,USER— 프로세스 간 통신 채널과 UID/GID 매핑이 분리된다.
즉 컨테이너 안 프로세스는 자기가 독립된 머신에서 돌고 있다고 “착각”하지만, 실제로는 호스트 커널 위에서 도는 일반 프로세스다. ps aux 를 호스트에서 치면 컨테이너 프로세스들이 그냥 보인다.
2-3. cgroup: 얼마나 쓸 수 있는지 제한한다
네임스페이스가 “무엇이 보이는가” 를 결정한다면, cgroup(control group) 은 “얼마나 쓸 수 있는가” 를 결정한다. CPU 코어 수, 메모리 상한, 디스크 I/O 대역폭 같은 자원에 상한선을 긋는다. 쿠버네티스 매니페스트에 쓰는 resources.limits.memory 가 바로 이 cgroup 설정으로 변환된다. 메모리 제한을 넘기면 OOM killer 가 그 cgroup 안의 프로세스를 죽인다. VM 이었다면 게스트 OS 안에서 스왑을 쓰거나 멈추는 식으로 반응했겠지만, 컨테이너는 커널이 훨씬 직접적으로 개입한다.
2-4. 그래서 실무에서 뭐가 달라지나
- 부팅이 없다: 새 프로세스를 fork/exec 하는 수준의 비용이라 컨테이너는 초 단위가 아니라 밀리초~초 단위로 뜬다.
- 커널 취약점을 공유한다: 호스트 커널에 구멍이 있으면 모든 컨테이너가 영향권이다. VM 은 하이퍼바이저 탈출이 훨씬 어렵다. 그래서 신뢰할 수 없는 코드를 완전히 격리하려면 gVisor, Kata Containers 처럼 VM 수준 격리를 흉내 낸 런타임을 쓰기도 한다.
- 이미지는 레이어의 합이다.
MNT네임스페이스 덕분에 여러 컨테이너가 같은 베이스 이미지 레이어를 읽기 전용으로 공유하고, 컨테이너별로 얇은 쓰기 레이어만 따로 갖는다. 이게 이미지 크기와 배포 속도에 직결된다.
3. 마무리
요약
- VM 은 하이퍼바이저가 하드웨어를 가상화하고, 컨테이너는 커널을 공유하며 네임스페이스로 “보이는 것”만 분리한다.
- cgroup 은 네임스페이스와 별개로 “쓸 수 있는 자원”의 상한을 긋는다. 쿠버네티스 리소스 제한이 여기로 이어진다.
- 컨테이너는 부팅이 없어 가볍지만, 커널을 공유하는 만큼 VM 보다 격리 경계가 얇다.
다음은 2편: 리버스 프록시는 왜 필요한가 다.