운영체제 학습 노트 목차

가상화·컨테이너 — OS를 통째로 나누다

지금까지 OS가 하드웨어를 추상화해 여러 프로그램이 공유하게 하는 걸 봤다. 그런데 한 걸음 더 나아가 — 하나의 물리 머신에서 여러 개의 격리된 "컴퓨터"나 "환경"을 통째로 돌리고 싶을 때가 있다. 클라우드가 한 서버를 수십 고객에게 나눠 팔고, MSA가 서비스마다 독립된 환경을 원하는 게 그것이다. 이걸 푸는 두 방식 — **가상 머신(VM)**과 컨테이너 — 는 무엇을 어디까지 가상화하느냐가 다르고, 그 차이가 곧 무게와 격리의 트레이드오프다.

하드웨어를 통째로 — 가상 머신

**가상 머신(VM)**은 하드웨어 자체를 가상화한다. 하이퍼바이저라는 소프트웨어 층이 — 가짜 CPU·메모리·디스크·네트워크 카드를 만들어, 그 위에 게스트 OS를 통째로 올린다. 그래서 한 물리 서버에 리눅스 VM과 윈도우 VM서로를 전혀 모른 채 돌 수 있다.

다이어그램 로딩 중…

장점은 강한 격리다 — 각 VM이 자기 커널을 가지니, 한 VM이 커널째 망가져도 다른 VM은 멀쩡하다. 단점은 무게다 — OS를 통째로 올리니 메모리·디스크를 많이 먹고, 부팅도 느리다(07편의 ring -1에서 하이퍼바이저가 돈다).

커널을 공유한다 — 컨테이너

컨테이너는 발상을 바꾼다 — OS를 새로 올리는 대신, 호스트의 커널을 공유하고 프로세스 수준에서만 격리한다. "각 컨테이너는 자기만의 세상인 줄 알지만, 사실 같은 커널 위의 격리된 프로세스"인 것이다. 이 격리를 만드는 게 리눅스의 두 기능이다 — namespace보는 것을 격리한다(프로세스 목록·네트워크·파일 마운트·호스트명을 각자 따로 봐서, 컨테이너가 서로를 못 본다). cgroup쓰는 것을 제한한다(CPU·메모리·I/O를 컨테이너별로 상한과 할당을 둔다). (출처: namespaces & cgroups.)

다이어그램 로딩 중…

커널을 새로 안 올리니 가볍고 빠르다수 MB에 수십 ms 부팅이라, 한 서버에 수백 개도 띄운다. 대신 커널을 공유하니 — VM만큼 강한 격리는 아니다(커널 취약점은 공유된다).

왜 알아야 하나 — 오늘날 서비스를 컨테이너로 배포하는 게 바로 이것이다 — *프로세스 격리(02편)*를 namespace+cgroup으로 강화한 것이다. 특히 cgroup의 자원 제한이 — 한 작업이 CPU·메모리를 독식하지 못하게 격벽을 치는 발상이고, 컨테이너에 메모리 상한을 두면 그 안에서 도는 프로그램도 그 한도를 인식해야 한다(상한을 모르면 한도를 넘겨 강제 종료된다). 그리고 VM vs 컨테이너의 트레이드오프(강한 격리·무거움 vs 가벼움·약한 격리)는 — *"안전이냐 가벼움이냐"*라는, 시스템 설계에 늘 등장하는 선택의 또 다른 얼굴이다.

정리하면, 가상화는 한 물리 머신을 여러 격리된 환경으로 나눈다 — VM하이퍼바이저로 하드웨어를 가상화해 게스트 OS를 통째로 올려 강한 격리를 주지만 무겁고, 컨테이너는 *호스트 커널을 공유하고 namespace(뷰 격리)+cgroup(자원 제한)*으로 프로세스만 격리해 가볍지만 격리가 약하다. 이 cgroup 자원 격리가 컨테이너가 자원을 독식하지 않게 막는 토대다.


이로써 운영체제 노트를 마친다. 추상화(프로세스·가상 메모리·파일·소켓)·관리(스케줄링·메모리)·보호(모드·격리)·동시성(락·데드락)·I/O·가상화 까지 — OS는 결국 한정된 하드웨어를 수많은 프로그램이 안전하게 공유하게 하는 거대한 관리자였다. 우리가 쓰는 언어·프레임워크·시스템이 왜 그렇게 동작하고 어디서 막히는가의 답은 — 거의 언제나 한 계층 아래, OS와 하드웨어에 있다.

I/O — 폴링/인터럽트·DMA·blocking/async