가상머신(Virtual Machine, VM)은 물리적 하드웨어 시스템에 구축되어 자체 CPU , 메모리, 네트워크 인터페이스 및 스토리지를 갖추고 가상 컴퓨터 시스템으로 작동하는 가상 환경입니다. 하이퍼바이저(혹은 가상머신 모니터, VMM)라 불리는 소프트웨어는 하드웨어세서 가상 머신의 리소스를 분리하고, 적절히 프로비저닝해서 가상머신에서 사용 할 수 있도록 합니다.
KVM(커널기반 가상 머신), VirutalBox , VMWare 같은 하이퍼바이저가 탑재된 물리적 머신을 호스트 머신, 호스트 OS, 호스트 등으로 부릅니다. 리소스를 사용하는 여러 VM 을 게스트 머신, 게스트 OS, 게스트 등으로 부릅니다.
가상머신을 사용하기 위해서는 하이퍼바이저가 필요합니다. 하이퍼바이저는 호스트 머신의 리소스를 각 게스트 머신에 할당하고 분리하는 소프트웨어입니다. 하이퍼바이저에는 크게 2가지 유형이 있습니다.
물리적 컴퓨터에 직접 실행되고, 물리적 컴퓨터의 모든 리소스에 액세스 할 수 있기 때문에 베어메탈 하이퍼바이저라고도 부릅니다. 시스템 하드웨어와 직접 상호작용합니다. 즉 베어메탈 하이퍼바이저는 운영체제를 통하지 않고 호스트 시스템의 물리적 하드웨어에 직접 설치됩니다. 베어메탈 하이퍼바이저는 매우 효율적이고, 서버 가상화, 데스크톱 가상화 및 앱 가상 환경 생성등에 자주 사용됩니다. KVM(커널 기반 하이퍼바이저)의 경우 자체 커널이 없는 유형2 하이퍼바이저와 다르게 자체 커널을 포함한다는 의미입니다.
Type 1 하이퍼바이저에는
KVM (Kernal-Based-Virtual Machine)
Red Hat Enterprise Virtualization (RHEV)
Hyper-V (windows)
VMware vSphere
등이 있습니다.
유형2 하이퍼바이저 또는 호스트형 하이퍼바이저는 이미 자체 운영체제(OS)가 실행 중인 호스트 머신에 설치됩니다. 이 기존 OS가 리소스 할당을 담당하며, 호스팅된 하이퍼바이저는 특정 기능이나 작업을 위해 생성된 환경에만 집중합니다. 호스팅 하이퍼바이저는 개발자가 애플리케이션을 빌드하고 테스트 할 수 있는 가상 환경을 만드는 데 자주 사용됩니다.
Type 2 하이퍼바이저에는
Oracle Virtual Box
VMWare Workstation / Fusion
QEMU
Microsoft Virtual PC
등이 있습니다.
유형 1 하이퍼바이저는 일반적으로 데이터 센터, 엔터프라이즈 컴퓨팅 워크로드, 웹 서버, 기타 고정된 애플리케이션에 사용됩니다. 클라우드 컴퓨팅 환경은 베어메탈 하이퍼바이저(유형 1)를 사용하여 가장 성능이 뛰어난 가상 머신을 제공합니다. 즉 우리가 쓰는 EC2 인스턴스와 같은 것들은 유형 1 하이퍼바이저를 통해 제공되는 가상 머신을 사용하는 것입니다.
유형 2 하이퍼바이저는 주로 워크로드가 리소스 집약적이지 않거나, 운영에 중요하지 않은 데스크탑 및 개발 환경에서 가장 자주 사용됩니다. 또한 사용자가 두 개 이상의 운영 체제를 동시에 사용하고 싶지만, 하나의 머신에 액세스 할 수 있는 경우에도 선호됩니다.
가상 머신에는 두 가지 기본 유형이 있습니다. 시스템 가상 머신과 프로세스 가상 머신입니다.
시스템 가상 머신 : 시스템 가상 머신은 완전히 설치된 OS를 수용합니다. 이를 통해 여러 가상 머신이 호스트 머신과 다른 운영체제를 실행 할 수 있습니다.
프로세스 가상 머신 : 프로세스 가상 머신은 애플리케이션 기능에 중점을 두며, OS 의 전체 설치를 허용하지 않습니다. 대신 특정 앱이나 프로그램을 실행하는 동안 OS 의 가상 환경을 생성한 다음 앱이나 프로그램이 종료되면 OS 환경을 파괴합니다.
시스템 가상 머신은 CPU/GPU/램 등의 물리적인 리소스를 할당받아서 호스트 머신에 설치되지않은 운영체제 환경을 에뮬레이션 합니다. 유형 1 또는 유형 2 하이퍼바이저(VMM)이 설치되어서 사용되는 형태로 vShere, Hyper-v, KVM, Virtual Box, UTM 등이 여기에 포함됩니다.
프로세스 가상 머신은 시스템 가상 머신과 다르게 가상 운영체제를 완전히 설치 할 수 있는 기능을 제공하지 않습니다. 대신 특정 애플리케이션, 프로그램을 사용하는동안 호스트 머신의 OS 내에 가상 환경을 생성하고, 해당 애플리케이션/프로그램이 종료되는 즉시 가상 환경도 제거됩니다. Linux Wine , JVM(Java Virtual Machine), .NET Framework 등이 여기에 포함됩니다.
완벽한 격리 보안
가상 머신은 완전 독립 실행형 시스템으로 격리되어 실행됩니다. 따라서 가상 컴퓨터는 호스트 머신에 있는 다른 가상 컴퓨터에 영향을 주기 어렵습니다. 각각의 개별 가상 머신은 악용되거나 공격당할 수 있지만, 같은 호스트머신에 있는 인접한 가상 머신에 영향을 줄 수 없습니다.
대화형 개발
컨테이너는 일반적으로 컨테이너를 실행하는데 필요한 예상되는 종속성 및 구성을 정적으로 정의한 것인 반면, 가상 머신은 좀 더 동적이기 때문에 대화형으로 개발 할 수 있습니다. 가상 머신에 소프트웨어를 수동으로 설치 할 수 있으며, 가상 머신의 스냅샷을 통해 현재 구성 상태를 캡쳐하고, 해당 스냅샷을 통해 추가적인 머신을 구동 할 수 있습니다. → Hashicorp packer 의 등장으로 가상머신의 이미지 또한 컨테이너처럼 정적으로 구성이 가능하긴 합니다.
비용 절감 (하나의 머신에서 여러 가상 머신 구동함으로서 얻는)
다운타임 감소
확장성
반복 속도
스토리지 크기 비용 (이미지의 크기가 일반적으로 수십GB 수준임)
실제 머신보다 떨어지는 효율성 (하이퍼바이저)
제대로 보안을 구축하지 않는다면, 같은 호스트 머신의 다른 가상머신에도 영향을 줄 수 있음.
컨테이너는 애플리케이션과 해당 종속성(라이브러리, 바이너리 및 추가 구성 파일)을 포함한 전체 런타임 환경을 캡슐화하여 애플리케이션의 이식성, 확장성, 보안 및 민첩성을 향상시키는 경량 독립형 패키지입니다.
리눅스의 chroot, cgroup, namespace 등의 기술을 사용해 구현합니다.
컨테이너는 호스트머신의 커널을 공유하며, 컨테이너 엔진을 통해 컨테이너를 띄우게 됩니다.
컨테이너 엔진에는
Docker
Containerd
CRI-O
Podman
Linux Containers(LXC)
RKT
등이 있습니다.
가상 머신과 컨테이너의 가장 큰 차이점은 가상 머신은 컴퓨터 전체를 하드웨어 계층까지 가상화 하는 반면에, 컨테이너는 운영체제 수준 위의 소프트웨어 계층만 가상화 한다는 것입니다. 따라서 컨테이너는 OS를 부팅하거나, 라이브러리를 로드 할 필요가 없기 때문에 훨씬 더 효율적이고 가벼워집니다. 또한 컨테이너화된 에플리케이션은 몇 초 만에 시작 할 수 있으며, 가상 머신에 비해 더 많은 인스턴스를 머신에 수용 할 수 있습니다.
컨테이너는 동일한 운영 체제 커널을 공유하고, 시스템의 나머지 부분으로 부터 애플리케이션 프로세스를 격리합니다. 예를들어 ARM Linux 시스템은 ARM Linux 컨테이너를 실행하고, x86 Linux 시스템은 x86 Linux 컨테이너를 실행합니다. 즉, 컨테이너는 이식성이 있지만, 정의된 운영 체제에 제약을 받습니다. Linux용 컨테이너는 Windows 에서 실행 할 수 없습니다.
컨테이너는 크게 시스템 컨테이너와 애플리케이션 컨테이너로 나뉩니다.
시스템 컨테이너
시스템 컨테이너는 컨테이너 기술을 사용해 운영체제 위에 하드웨어 가상화 없이 운영체제를 실행합니다. 시스템 컨테이너를 지향하는 컨테이너 런타임으로는 LXC, LXD가 있습니다. 쉽게 설명하자면, 컨테이너를 이용해 운영체제를 실행하고(e.g CentOS, Ubuntu, Debian, Alpine Linux 등) 해당 컨테이너 내에 여러 애플리케이션과 라이브러리, 종속성을 추가로 설치해서 사용하는 컨셉이라고 볼 수 있습니다.
애플리케이션 컨테이너
우리가 주로 많이 쓰게 될 유형입니다. 컨테이너 기술을 활용해 하나의 애플리케이션(프로세스)를 실행하는 것을 목표로 합니다.
시스템 컨테이너와 애플리케이션 컨테이너로 유형을 나누긴 했지만, 실제로 현재 시점에서는 둘을 나누는게 사실상 무의미합니다. Docker / Containerd / CRI-O 등을 사용해도, LXD / LXC 가 지향하고자 했던 시스템 컨테이너를 충분히 구축하고 구현 할 수 있기 때문입니다. 사실상 나누는 의미는 무의미합니다.
민첩성 및 경량화
개발자의 생산성이 향상되고, 앱 개발 속도가 빨라집니다. 컨테이너는 CI/CD 파이프라인을 간소화하며, DevOps 팀과 마이크로 서비스 배포에 이상적입니다. 컨테이너 이미지를 빌드하는데 드는 시간은, 가상머신의 이미지를 생성(Packer 같은 툴로 이미지를 Bake 하거나, 그것이 아니더라도)하는데 드는 시간보다 적으며, 이미지의 크기 자체도 컨테이너는 수십MB ~ 수백MB 수준이지만, 가상머신의 이미지는 수GB ~ 수십GB에 이릅니다. 또한 부팅되는 시간또한 컨테이너는 수초~수십초에 불과합니다.
확장성
쿠버네티스와 같은 컨테이너 오케스트레이션 툴을 사용하거나, 그것이 아니더라도 워크로드 요구 사항의 변화에 따라 컨테이너 배포를 확장하거나 축소하여 앱의 가용성을 높이기 수월합니다.
강력한 에코시스템
대부분의 컨테이너 런타임 시스템은 사전 제작된 컨테이너의 호스팅된 공개 레포지토리를 제공합니다. 이것을 Base Layer 로 하여 이미지를 빌드하거나, 개발하는경우 많은 시간을 아낄 수 있습니다.
책임 분리
컨테이너화를 통해 단일 애플리케이션을 단일 컨테이너에 패키징하면서, 책임을 분리 할 수 있습니다. 개발자는 애플리케이션의 로직과 종속 항목에 집중하고, 운영팀/DevOps 팀은 배포 및 관리에 집중 할 수 있습니다.
공유 호스트 악용
컨테이너는 모두 운영 체제 계층 아래의 동일한 기본 하드웨어 시스템을 공유하므로, 한 컨테이너가 악용되면 컨테이너에서 벗어나 공유 하드웨어애 영향을 미칠 수 있습니다. 따라서 컨테이너에 대한 각종 보안대책을 잘 적용해야 합니다.
스토리지
컨테이너는 데이터나 상태를 저장하지 않는 비저장형으로 설계되었습니다. 따라서 컨테이너 환경에서 데이터 및 상태를 저장하기 위해서는 별도의 볼륨을 마운트해서 사용해야 합니다.
애플리케이션이 성장함에 따라 컨테이너를 수동으로 생성, 관리, 삭제하는 것이 어려워 질 수 있습니다. 컨테이너 오케스트레이션은 컨테이너 가용성, 프로비저닝, 스케줄링, 배포를 자동화 하고 컨테이너 전체 수명 주기를 관리합니다.
컨테이너 배포
컨테이너 관리
리소스 할당
스케일링
로드 밸런싱
네트워킹 (서비스 디스커버리)
스케줄링
모니터링
위와 같은 컨테이너에 대한 전반적인 관리를 위해 필요한것이 컨테이너 오케스트레이션 툴이며, 대표적으로 그리고 사실상의 표준인 Kubernetes 가 있습니다. (Docker-compose , Docker-Swarm, Apache Mesos 도 여기에 포함)
가상머신과 컨테이너는 동일한 개념이 아닙니다. 과거 컨테이너의 초기 등장 시절에는 경량화된 가상머신 등의 이름으로 업계에서 사용되거나, 비즈니스를 하는 경우가 있었지만 2023년 말 현재 지금 시점에서는 명확하게 분리되어서 사용됩니다.
가상머신이 낫냐, 컨테이너가 낫냐는 각 사용사례, 환경에 따라서 달라지고 서로 상호 보완적인 존재입니다.
단적으로 예를들자면 ec2 인스턴스를 활용해 사용되는 AWS의 EKS 서비스를 볼 수 있습니다.
ec2 인스턴스는 Type-1 하이퍼바이저를 통해 생성되어서 유저에게 제공되는 가상머신입니다. 이 가상머신에 쿠버네티스가 설치되고 거기에는 여러 컨테이너를 사용자가 띄우게 됩니다.