QEMU, KVM, QEMU-KVM가 뭐야?
2021년 8월 18일최근 QEMU에 공부를 하던 중 KVM과 QEMU-KVM 용어를 알게 되었습니다. QEMU, KVM 둘 다 가상화를 해주는 프로그램으로 두루뭉실하게 알고 있는데 QEMU-KVM는 또 뭔지 감이 잘 오지 않았습니다. 가상화에 가상화를 더블로...? 이런 궁금증은 못 참습니다. 이번에는 가상화에 대해 알아보는 시간을 가져봅시다.
일단 QEMU와 KVM에 대해서 알아봅시다. 이 둘은 수 많은 hypervisor 종류 중 하나입니다. Hypervisor란 컴퓨터 1대에 다수의 운영체제를 동시에 실행할 수 있게 도와주는 가상화 프로그램입니다. Docker, WSL도 hypervisor 기술로 만들어진 프로그램으로 보면 되겠죠? 이 hypervisor는 크게 세 가지 종류로 나뉘어 집니다. 이 중 두 개만 알아봅시다.

하이퍼바이저 가상화 - type1는 native 혹은 bare-metal이라고도 불리며 hypervisor가 OS에 종속되지 않고 하드웨어에 바로 위에 설치되는 구조입니다. Hypervisor가 하드웨어를 직접 컨트롤할 수 있어 성능이 좋고 유연하게 OS들을 관리할 수 있습니다.
호스트 가상화 - type2는 흔히 저희들이 생각하는 가상머신 기술이라고 보면 됩니다. OS위에 virtual box나 vmware와 같은 가상화 프로그램을 설치하고 그 위에 OS를 올리는 방식이라고 생각하면 됩니다.
가상화를 하는 방법에 따라서도 전가상화, 반가상화 두 가지로 나뉘어 집니다. 전가상화 - Full-Virtualization는 가상 머신이 구동할 OS나 드라이버에 특별한 수정을 하지 않고 그대로 쓸 수 있는 경우를 말합니다. Hypervisor가 중간에서 운영체제마다 다른 명령어를 해석하여 하드웨어로 보낸다고 생각하면 됩니다. 하지만 중간의 hypervisor가 모든 일을 처리하므로 성능이 떨어지는 단점이 있습니다. 반가상화 - Para-Virtualization는 전가상화의 성능 저하를 보완하고자 나온 방법으로 있는 그대로의 OS나 드라이버를 쓰는게 아닌 수정된 OS나 드라이버를 쓴다라는 말입니다. 전가상화 처럼 중간의 hypervisor가 명령어를 해석하는 것이 아닌 이미 '해석된' 명령어를 실어 나르기만 하면 됩니다. 따라서 성능이 보장되는 장점이 있지만 '해석된' 명령어를 만들기 위해선 커널 코드를 수정해야하는 진입장벽이 있습니다.
전가상화와 반가상화에 대한 간략한 설명을 하였는데 이 링크를 참고하면 더욱 이해가 될 것 같습니다. 다음 내용으로 넘어가기 전에 가상화에 대해서 간략하게 짚어 보겠습니다. 가상화는 하드웨어 아키텍처 위에 다른 OS를 띄우고 돌리는 역할을 하며 중간에서 명령어 해석, 커널 번역, 자원 분배를 도와주는 프로그램입니다. 참고로 앞서 세 가지 종류로 방식이 나누어 진다고 했는데 나머지 하나는 docker의 컨테이너 가상화입니다.
이제 오늘의 주인공인 QEMU와 KVM에 대해 자세히 알아봅시다. QEMU는 Quick Emulator의 약어이며 호스트 가상화(type2)를 쓰고 에뮬레이터 입니다. 에뮬레이터라는 말이 생소하실 수 있습니다. 쉽게 생각하면 PC에 옛날 게임을 돌리기 위한 GBA(게임보이) 프로그램, 안드로이드 어플을 돌리기 위해 설치한 Nox 프로그램이 에뮬레이터입니다. 보통 x86 환경인 PC에서 ARM 환경에서 동작하는 안드로이드 어플을 돌릴 수 없습니다. 하지만 에뮬레이터는 서비스를 돌리기 위한 하드웨어 환경을 만들어주는 역할을 합니다. 즉, QEMU는 가상화 프로그램이기도 하지만 에뮬레이터 성격이 강한 프로그램 입니다. 따라서 에뮬레이터란 다른 하드웨어에서 돌아가기 위해 가상의 하드웨어 환경을 구현하는 프로그램입니다. 공식 홈페이지는 QEMU에 대해 다음과 같이 소개 하고 있습니다.
QEMU는 하드웨어를 가상화하고 하나의 명령어 세트를 다른 명령어 세트로 변환해주는 [Dynamic Binary Translation 기법[1]을 통해 다양한 아키텍처 위에서 OS 및 프로그램을 돌릴 수 있게 됩니다. 하지만 하드웨어 힘이 아닌 소프트웨어 힘으로만 돌아가서 성능이 매우 떨어집니다. QEMU도 프로세스고! 스레드야!
KVM은 Kernel Virtual Machine의 약어로 리눅스 x86 커널 모듈이고 전가상화 hypervisor 입니다. KVM은 QEMU와 달리 Binary Translation을 수행하지 않고 가상머신이 생성한 명령어를 호스트 하드웨어에서(Intel VT, AMD-V 같은) 처리하기 때문에 같은 아키텍처만 가상화 할 수 있으며 속도가 빠릅니다. KVM이 기본으로 리눅스 커널 모듈로 들어가니 리눅스 자체가 hypervisor 역할을 한다고 볼 수도 있어 하이퍼바이저 가상화 방식이라고도 볼 수 있겠지만 가상 머신외에 다른 프로그램도 구동하기 때문에 호스트 가상화 방식으로 분류하기도 합니다.
그런데 보통 QEMU나 KVM을 단독으로 쓰이지 않고 서로의 단점을 보완하고자 QEMU-KVM으로 묶어서 같이 씁니다. 에뮬레이터와 가상화의 만남이라고 생각하면 편하겠습니다. 가상 머신과 호스트 머신을 동일한 아키텍처에서 작업하여 KVM 단에서 작업을 처리하고 드라이버는 QEMU의 도움으로 에뮬레이팅 하여 가상 머신이 구동할 OS나 드라이버를 수정 없이 전가상화로 쓸 수 있습니다.

따라서 일반적으로 KVM의 도움을 받기위해 동일한 아키텍처 위에서 작업하고 QEMU로 가상 머신을 띄우는 작업 환경이 일반적인 것 같습니다.
이번 주제는 글을 읽고 한 번에 이해하기 힘들꺼라 예상됩니다. 제가 생각한 개념을 글로 쉽게 표현한다고 노력했지만 더욱 개념을 어렵게 만든게 아닌가 하는 걱정도 있습니다. 글 맨 앞의 네이버 클라우드의 글과 두 번 째 이미지 출처 링크를 읽어보면 이해하는데 도움이 될 겁니다. 무거운 주제로 글을 썼는데 QEMU와 KVM이 어떤 물건인지 감만 잡으셔도 필자는 행복할 것 같습니다.
[1] Binary Translation: 하나의 명령어 세트를 다른 명령어 세트로 변환해주는 작업. QEMU는 기본 실행 단위를 블록으로 처리하여 변환하는 Dynamic Binary Translation(DBT) 작업을 합니다.
참고 자료