여는 글

기업의 비즈니스적인 측면에서 하드웨어 비용을 낮게 유지하고 그 리소스를 낭비하지 않기 위하는 것이 기술 사용의 목표 중 하나라고 생각합니다. 특히, MSA(Micro Service Architecture)에서 쿠버네티스(Kubernetes)를 사용하지 않고 각 서비스에 자체 VM을 구성한다면 각 VM을 개별적으로 구성하고 관리해야 하겠죠. 서비스가 늘어나면 늘어날수록 인력과 시간이 비례해서 더 복잡한 자동화 시스템이 필요해지게 됩니다. 시스템이 수백 개의 배포된 애플리케이션 인스턴스로 구성되는 마이크로서비스 아키텍처로 전환함에 따라 VM에 대한 대안으로 컨테이너(Container)로 등장하게 되었습니다.

컨테이너와 가상 머신 비교

마이크로서비스들의 환경을 격리하기 위해 각각의 가상 머신(VM)을 사용하는 대신에 컨테이너 사용을 선호합니다. 이를 통해 동일한 호스트 컴퓨터에서 여러 서비스를 실행하면서 서로 격리된 상태로 유지할 수 있습니다. VM과 비슷하지만 오버헤드가 훨씬 적습니다.

별도의 운영 체제를 실행하는 VM과 달리 컨테이너에서 실행되는 프로세스는 호스트의 운영 체제 내에서 실행됩니다. 컨테이너의 애플리케이션 프로세스는 동일한 운영 체제에서 실행되고 그 환경은 격리되게 되는 것이죠.

컨테이너와 가상 머신의 오버헤드 비교

가상 머신(VM)의 경우, 각 VM은 독립적인 운영체제를 실행하고, 이 운영 체제는 자체적인 시스템 프로세트를 가지고 있습니다. 이러한 시스템 프로세스들은 파일 시스템 관리, 네트워크 관리, 메모리 관리 등 다양한 OS 레벨의 작업을 수행하며, 이는 사용자 애플리케이션의 프로세스가 소비하는 자원 외에 추가적인 컴퓨팅 자원을 필요로 하게 됩니다. 결과적으로, VM을 사용하는 환경에서는 이러한 오버헤드로 인해 전체 시스템의 효율성이 감소할 수 있습니다.

반면에, 컨테이너는 격리된 프로세스로서 호스트 OS내에서 직접 실행됩니다. 컨테이너는 호스트 OS의 기존 시스템 프로세스와 서비스를 공유하기 때문에, VM과 같이 독립적인 운영 체제 인스턴스를 실행할 필요가 없습니다. 이는 컨테이너가 사용자 애플리케이션의 프로세슷가 실제로 필요로 하는 자원만을 소비하게 해주어, 거의 오버헤드 없이 효율적으로 작동할 수 있게 해줍니다. 이러한 특성 덕분에 컨테이너는 가볍고 빠르며, 시스템 자원을 효율적으로 사용할 수 있는 방식입니다.

vm-container drawio * 그림 1.1

가상 머신(VM)들은 리소스를 상당히 많이 사용하기 떄문에, 개별 애플리케이션을 각각의 VM에 단독으로 배치하는 것은 자원적으로 비효율적일 수 있습니다. 이 때문에 개발자나 시스템 관리자들은 서로 다른 애플리케이션들을 하나의 VM 안에서 함께 실행시키는 방법을 택하기도 합니다. 이렇게 함으로써 하드웨어 자원을 좀 더 효율적으로 사용하고자 한 것이죠.

하지만, 컨테이너의 경우는 VM에 비해 훨씬 가볍고 리소스 오버헤드가 ‘거의’ 없기 때문에, 각 애플리케이션을 별도의 컨테이너에 담아서 실행하는 것이 가능합니다. 물론, 한 컨테이너 안에서 여러 애플리케이션을 실행하는것이 가능합니다. 하지만, 이런 선택을 하는 것은 권장 되지 않습니다. 프로세스 관리를 복잡하게 만들 뿐만 아니라, 쿠버네티스(Kubernetes)와 같은 컨테이너 오케스트레이션 도구들이 컨테이너 당 하나의 애플리케이션을 전제로 설계되어 있기 때문입니다.

컨테이너와 가상 머신의 격리 비교

가상 머신(VM)에서 애플리케이션을 실행하면 각 VM은 자체 운영 체제와 커널(Kernel)을 실행합니다. 이러한 VM 아래에는 하이퍼파이저(Hypervisor)가 위치해 있으며, 이 하이퍼바이저는 물리적 하드웨어 리소스를 각 가상 머신의 운영체제가 사용할 수 있는 작은 세트의 가상 리소스로 분할합니다. 쉽게 말해, 하이퍼바이저가 물리적 컴퓨터의 자원을 여러 가상 머신들이 사용할 수 있도록 나누어주는 것입니다.

아래 [그림 1.2]를 보면 가상 머신들에서 실행되는 애플리케이션은 게스트 OS커널에 시스템 호출(sys-calls)를 하며, 그 후 커널이 가상 CPU에서 실행하는 기계 명령은 하이퍼바이저를 통해 호스트의 물리적 CPU로 전달됩니다.

주요 포인트는, 가상 머신 내에서 실행되는 애플리케이션의 명령이 최종적으로 물리적하드웨어에서 실행되기까지 여러 단계를 거친다는 것입니다. 이러한 추가적인 단계들로 인해 오버헤드를 발생시키고, 이는 가상 머신이 컨테이너에 비해 리소스를 더 많이 사용하게 만듭니다. 컨테이너의 경우는 이러한 추가적인 단계가 없거나 훨씬 적어서 리소스 사용 효율이 더 높습니다.

vm-container2 drawio * 그림 1.2

컨테이너와 보안

가상 머신(VM)을 사용하는 것이 컨테이너를 사용하는 것에 비해 가지는 주요한장점은 완전한 격리를 제공한다는 점입니다. 이는 각 가상 머신이 자신만의 Linux커널을 가지고 있기 때문이며, 반면에 모든 컨테이너는 동일한 커널을 사용합니다. 동일한 커널을 사용한다는 것은 보안 리스크가 존재하는데요. 커널에 버그가 있을 경우, 한 컨테이너의 애플리케이션이 그 버그를 이용하여 다른 컨테이너들의 메모리를 읽을 가능성이 있습니다. 만약 애플리케이션이 서로 다른 가상 머신에서 실행되어 하드웨어 자원만 공유한다면, 이러한 공격이 일어날 확률은 훨씬 낮습니다. 물론, VM의 경우도 서로 다른 물리적 기계에서 실행할 때의 일이겠지만요.

추가적으로, 컨테이너들은 메모리 공간을 공유하는 반면, 각 가상 머신은 자신만의 독립된 메모리 영역을 사용합니다. 따라서, 컨테이너가 사용할 수 있는 메모리 양을 제한하지 않는다면, 이는 다른 컨테이너들이 메모리 부족 현상을 겪거나 데이터가 디스크로 스왑(swap)되는 상황을 초래할 수 있습니다.

컨테이너와 VM을 활성화하는 요소

가상 머신(VM)은 CPU의 가상화 지원과 호스트의 가상화 소프트웨어를 통해 활성화되는 반면, 컨테이너는 Linux 커널 자체에 의해 활성화됩니다.


다음 포스팅에서는 Docker를 통해 컨테이너 기술을 이해해보도록 하겠습니다.