 |
|
난이도 : 중급 M. Tim Jones, 컨설턴트 엔지니어, Emulex Corp.
옮긴이: 박재호 이해영 dwkorea@kr.ibm.com
2008 년 5 월 20 일 리눅스(Linux®)와 유연성은 손에 손을 잡고 함께 하는데, 가상화에 대한 옵션도 예외는 아닙니다. 하지만 최근에, KVM(Kernel Virtual Machine)이 등장하면서 리눅스 가상화 지형에 변화가 일어나기 시작했습니다. KVM은 리눅스 주류 커널(2.6.20)의 일부로 등장한 첫 번째 가상화 해법입니다. KVM은 리눅스 게스트 운영체제 가상화를 지원하며, 가상화를 지원하는 하드웨어에서 심지어 윈도우까지도 돌릴 수 있습니다. 리눅스 KVM 아키텍처와 KVM을 커널과 통합할 경우에 리눅스 활용 방법이 바뀔지도 모르는 이유에 대해 살펴보겠습니다.
소개
가상화(Virtualization)는 상당히 오랜 시간에 걸쳐 우리에게 낯익은 개념이다. 간략하게 설명하면, 가상화는 뭔가를 집어내어 다른 뭔가처럼 보이도록 만드는 과정이다. 이런 개념을 컴퓨터 시스템에 적용하면, 단일 시스템을 여러 사용자가 여러 각도로 바라보게 만든다(예를 들어, 단일 컴퓨터에서 리눅스와 마이크로소프트 윈도우를 동시에 돌리는 경우를 생각해보자). 이는 일반적으로 완벽한 가상화라고 부른다.
 |
KVM과 kvm
이 기사에서 커널 가상 기계(Kernel Virtual Machine)에 대해 이야기할 때는 KVM을 쓰고, (새로운 가상 기계를 생성할 때 사용되는) 하이퍼바이저 유틸리티를 논할 때는 kvm을 쓴다.
|
|
가상화는 또한 단일 컴퓨터가 여러 아키텍처로 나타나는 곳에서(어떤 사용자에게는 표준 x86 플랫폼으로 보이고, 어떤 사용자에게는 IBM PowerPC® 플랫폼으로 보인다) 형태가 좀 더 복잡하게 보일지도 모른다. 이런 가상화 형태는 흔히 하드웨어 에뮬레이션이라고 알려져 있다.
마지막으로 좀 더 단순한 가상화 형태는 운영체제 가상화다. 단일 컴퓨터에서 동일한 유형의 여러 운영체제를 돌린다. 이런 가상화 유형은 단순히 단일 운영체제에서 여러 서버를 격리한다(따라서 운영체제 유형과 버전이 모두 같아야 함을 의미한다). 가상화 메서드에 대한 정보는 참고자료를 참조한다.
가상화와 의사 가상화
가장 일반적인 가상화 접근 방식에는 완벽한 가상화(full virtualization)와 의사 가상화(para-virtualization)가 있다. 완벽한 가상화에서는 가상화된 운영체제와 하드웨어 사이에 층이 있어서 접근을 중재한다. 이런 층을 하이퍼바이저(hypervisor)나 가상 기계 모니터(VMM)라고 부른다. 의사 가상화도 이와 비슷하긴 하지만, 하이퍼바이저는 좀 더 협력적인 방식으로 움직인다. 이렇게 협력적으로 동작하는 이유는 각자 가상화되어 있다고 인식하는 각 게스트 운영체제가 하이퍼바이저와 협력해 기반 하드웨어를 가상화하기 때문이다.
완벽한 가상화 예는 상용으로 판매 중인 IBM zSeries 컴퓨터를 위한 IBM 시스템 z9 가상 기계(z/VM) 운영체제를 비롯하여 상용 가상화 해법인 VMWare 등이 있다. 의사 가상화는 Xen과 UML(User-Mode-Linux)이 제공한다. KVM은 완벽한 가상화 해법으로 볼 수 있는데, 잠시 후 설명을 진행하겠다.
가상화 동작 원리
가상화와 관련 구성 요소에 대해 잠깐 살펴보면서 시작하자. 가상화 해법 아래쪽에는 가상화될 기계가 있다. 이 기계는 하이퍼바이저라는 다음 층이 요구하는 직접 가상화를 지원할 수도 있고 그렇지 않을 수도 있다. 하이퍼바이저나 VMM은 플랫폼 하드웨어와 운영체제 사이에 추상화로 서비스를 제공한다. 몇몇 경우에는 하이퍼바이저가 운영체제다. 이 경우에는 그림 1에 나타나듯이 호스트 운영체제로 불린다.
그림 1. 가상화의 계층적인 추상화 구조
하이퍼바이저 위에는 게스트 운영체제가 있는데, VM(가상 기계)이라 한다. 이 VM은 격리된 운영체제로 기반 하드웨어를 독점한다고 생각한다. 하지만 현실에서는 하이퍼바이저가 이런 착각을 불러일으킨다.
 |
가상화를 위한 프로세서 지원
플랫폼 가상화의 장점은 너무나 현실적이므로, 프로세서 제조사는 실리콘 칩을 변경해 이런 메서드를 직접 지원한다. 이렇게 하면 프로세서가 게스트 운영체제와 다르게 하이퍼바이저를 직접 지원할 수 있게 된다. VMM과 VM이 제각기 관리하는 프로세서 상태(레지스터 등)와 더불어, 프로세서는 I/O와 인터럽트 가상화도 지원한다. 좀 더 많은 정보가 필요하면 참고자료를 참조한다.
|
|
오늘날 가상화 해법에 나타나는 문제점은 모든 하드웨어가 깨끗하게 가상화를 지원하는 상황이 아니라는 데 있다. 오래된 x86 프로세서는 실행 도메인에 따라 특정 명령어에 대한 결과가 다른 식으로 나타난다. 이렇게 할 경우 문제가 생기는 이유는 하이퍼바이저는 단지 가장 보호받는 도메인에서만 동작해야 하기 때문이다. 이런 이유 때문에 VMware와 같은 가상화 해법은 실행 대상 코드를 미리 검색해 트랩 명령으로 문제가 되는 명령을 대체하는 방법으로 하이퍼바이저가 적절히 처리하도록 만든다. 가상화 중에서도 협력적인 메서드를 지원하는 Xen에서 변경이 필요하지 않는 이유는 게스트는 자신이 가상화되었음을 알고 자신을 변경하기 때문이다. KVM은 단순히 이런 문제를 무시하며 가상화를 원할 때 새로운 하드웨어에서 돌려야 한다고 못을 박는다.
처음 보기에는 이런 정책이 다소 고압적으로 보일지 모르겠지만, (인텔 VT와 AMD SVM 같은) 오늘날 가상화를 지원하는 새로운 기계를 고려해볼 때, 오래 지나지 않아 가상화 지원은 예외가 아니라 일반적인 조류가 될 것이다. 가상화를 지원하는 프로세서에 대한 정보가 필요하다면 참고자료와 "가상화를 위한 프로세서 지원" 보충 설명을 읽어본다.
KVM 하이퍼바이저
가상화 기술 연표를 바라보면 KVM은 상대적으로 신참이다. 두각을 나타내는 Xen, Bochs, UML, 리눅스-V서버, co리눅스와 같은 여러 오픈 소스 메서드가 오늘날 존재하지만, KVM은 언론에 놀랍도록 많이 노출되었다. 또한 KVM은 실제로는 자체로 완벽한 가상 기법이 아니라 더 큰 해법의 일부다.
KVM이 사용하는 접근 방식을 보면, 커널 모듈을 메모리에 올리는 방법으로 리눅스 커널을 간단히 하이퍼바이저로 탈바꿈하게 만든다. 커널 모듈은 (전통적인 커널과 사용자 모드 이외에 새롭게 추가된) 커널의 게스트 모드를 활성화하는 /dev/kvm이라는 디바이스를 외부에 공개한다. /dev/kvm을 사용해, VM은 커널이나 동작 중인 다른 VM에서 분리된 독자적인 주소 공간을 확보한다. 디바이스 트리(/dev)에 있는 디바이스는 모든 사용자 영역 프로세스에게 공통으로 보인다. 하지만 /dev/kvm은 이 디바이스를 여는 각 프로세스마다 (VM 격리를 지원하기 위해) 다른 내용을 보여준다는 점에서 차이가 있다.
 |
리눅스 커널에서 KVM 원시 코드
KVM 원시 코드를 ./linux/drivers/kvm(2.6.20 이상)에서 찾을 수 있다. 이 디렉터리는 인텔과 AMD 확장을 위한 프로세서 지원 파일과 함께 KVM을 위한 원시 파일을 담고 있다.
|
|
그리고 나서 (kvm 커널 모듈을 설치할 때) KVM은 리눅스 커널을 하이퍼바이저로 바꾼다. 표준 리눅스 커널이 하이퍼바이저이므로 (메모리 지원, 스케줄러 등) 표준 커널에 일어나는 변경이 그대로 반영된다. 이런 리눅스 구성 요소에 대한 최적화(예를 들어 2.6 커널에 탑재된 신형 O(1) 스케줄러와 같은)는 (호스트 운영체제인) 하이퍼바이저와 리눅스 게스트 운영체제 모두에게 이익을 준다. 하지만 KVM이 1번 타자는 아니다. UML은 리눅스 커널을 하이퍼바이저로 변환하는 작업을 상당히 오래 전부터 진행했다. 커널이 하이퍼바이저로 동작하면, 또 다른 리눅스 커널이나 여타 운영체제를 시작할 수 있게 된다.
KVM
KVM이 설치되면 사용자 영역에서 게스트 운영체제를 시작할 수 있다. 각 게스트 운영체제는 호스트 운영체제(또는 하이퍼바이저) 입장에서 단일 프로세스다. 그림 2는 KVM으로 가상화를 한 모습을 보여준다. 하단에는 (현재 인텔 VT나 AMD-SVM 프로세서가 지원하는) 가상화 기능을 제공하는 하드웨어 플랫폼이 있다. 이런 하드웨어 위에서 동작하는 구성요소는 하이퍼바이저다(KVM 모듈로 동작하는 리눅스 커널). 이 하이퍼바이저는 다른 응용 프로그램을 돌릴 수 있는 평범한 리눅스 커널처럼 보인다. 하지만 이 커널은 추가로 kvm 유틸리티를 통해 메모리에 올리는 게스트 운영체제를 지원한다. 마지막으로 게스트 운영체제는 호스트 운영체제가 지원하는 동일한 응용 프로그램을 지원할 수 있다.
그림 2. KVM에서 가상화 구성 요소
KVM은 가상화 해법의 일부임을 기억하자. 프로세서는 가상화 기능을 직접 지원한다(다중 운영체제 시스템을 위해 프로세서를 가상화하는 기능). kvm을 통해 메모리를 가상화한다(다음 절에서 다룰 내용이다). 마지막으로 조금 변경된 (각 게스트 운영체제 프로세스로 실행하는 복사본인) QEMU 프로세스를 통해 I/O를 가상화한다.
KVM은 리눅스에 현존하는 커널과 사용자 모드에 새로운 프로세스 모드를 추가한다. 이 새로운 모드는 게스트라고 부르며, 이름이 의미하는 바와 같이 (최소한 일부만이라도) 게스트 운영체제 코드 수행에 사용된다. 커널 모드는 코드 수행에 있어 특권 모드를 대표하며, 사용자 모드는 (커널 외부에서 동작하는 프로그램을 위한) 비 특권 모드를 대표한다는 사실을 기억하자. 실행 모드는 무엇이 동작하고, 목적이 무엇이냐에 따라 다양한 목적을 위해 정의된다. 게스트 모드는 I/O가 없는 게스트 운영체제 코드를 수행하기 위해 존재한다. 게스트 모드 내부에 표준 모드가 두 가지 존재하므로 게스트 모드로 동작하는 게스트 운영체제는 커널과 사용자 영역 응용 프로그램을 위해 표준 커널과 사용자 모드를 지원한다. 게스트 운영체제의 사용자 모드는 독립적으로 관리되는 I/O를 수행한다.
게스트 운영체제에서 I/O 수행은 QEMU가 제공한다. QEMU는 (디스크, 그래픽 카드, 네트워크 디바이스를 포함하여) 전체 PC 환경의 가상화를 허용하는 플랫폼 가상화 해법이다. 게스트 운영체제가 요청한 I/O를 가로채어 QEMU 프로세스가 에뮬레이션하도록 사용자 영역으로 전달한다.
KVM은 /dev/kvm 디바이스를 통해 메모리 가상화를 제공한다. 각 게스트 운영체제는 게스트를 새로 하나 생성할 때 사상된 독자적인 주소 영역을 확보한다. 게스트 운영체제에 사상된 물리적인 메모리는 실제로 프로세스 내부로 사상된 가상 메모리다. 게스트 물리 주소에서 호스트 물리 주소로 변환을 지원하기 위해 그림자 페이지 테이블 집합을 관리한다. 프로세서는 또한 사상되지 않은 메모리 위치에 접근할 때 하이퍼바이저(호스트 커널)를 사용하도록 메모리 변환 프로세스를 지원한다.
새로운 게스트 생성하기
새로운 게스트 운영체제 생성은 kvm이라는 유틸리티가 맡는다. 이 유틸리티는 kvm 모듈과 함께 동작해 /dev/kvm을 사용해서 게스트를 메모리에 올리고, 가상 디스크(호스트 운영체제에 있는 일반 파일)를 붙인 다음 동작을 개시한다.
/dev/kvm 디바이스에 수행하는 ioctl 집합을 통해 제어 기능을 지원한다. 디바이스 파일이 처음으로 열리면, 새로운 VM 객체가 생성되어 가상 CPU와 연결된다. 그리고 나서 여러 ioctl을 사용해 가상 CPU를 생성하고, kvm 버전을 점검하고, 메모리 영역을 생성하고, 그리고 나서 가상 CPU를 시작한다. 명령어 kvm으로 이런 작업을 할 수 있다. 다음에 이어지는 절에서 kvm 명령어를 살피고 지원되는 몇 가지 ioctl 예제를 보여주겠다.
KVM 활용
하드웨어가 지원하기만 하면 KVM 활용은 상당히 단순하다. 가상화를 지원하는 프로세서가 필요하다. /proc/cpuinfo를 살펴보면 시스템이 가상화를 지원하는지 확인할 수 있다. 이 파일은 vmx(인텔), svm(AMD) 확장을 지원하는지 알려준다.
다음으로 KVM 지원을 활성화한 리눅스 커널이 필요하다. 'Device Driver > Virtualization' 커널 환경 설정에서 활성화가 가능하다. 또한 환경을 위한 프로세서 지원을 활성화한다. 또한 kvm과 qemu 사용자 영역 응용 프로그램도 필요하다. 세부 사항은 참고자료 항목을 참조하기 바란다.
가상화 지원이 활성화된 커널을 사용해서, 다음 단계로 게스트 운영체제를 위한 디스크 이미지 생성 과정을 밟는다. 다음에 소개하듯이 qemu-img로 이미지를 만든다. 이미지 크기는 4GB이지만 QEMU에서 제공하는 qcow(copy-on-write format)를 사용하므로, 파일은 완전히 4GB를 가득 채우는 대신 필요한만큼 용량이 늘어난다.
$ qemu-img create -f qcow vm-disk.img 4G
|
가상 디스크를 만들었다면, 여기에 게스트 운영체제를 올리자. 다음 예제는 게스트 운영체제가 CD-ROM에 담겨있다고 가정한다. CD-ROM ISO 이미지로 가상 디스크를 만들었다면, 완료 후에 만들어진 이미지로 부팅해야 한다.
$ kvm -no-acpi -m 384 -cdrom guestos.iso -hda vm-disk.img -boot d
|
Ari Kivity는 완벽한 디바이스 모델 없이도 KVM을 테스트하는 테스트 도구 집합을 만들었다. (kvm-12/user/main.c에서 따온) 다음 코드 조각은 VM을 시작하는 고차원적인 코드 개요를 보여준다(Listing 1 참조). 제어 기능은 커널에서 ioctl이 제공한다(특히 ./linux-2.6.20/drivers/kvm/kvm_main.c 파일을 살펴본다).
kvm_init를 호출하면 /dev/kvm 디바이스를 열고, (KVM 커널 모듈이 외부에 공개한) 버전 번호를 점검하고, 그리고 나서 KVM 문맥 객체를 할당하고 몇 가지 콜백 함수를 채운다. kvm_create 함수는 두 메모리 영역을 설정하고 사상한 다음에 ioctl(KVM_CREATE_VCPU)로 가상 CPU(VCPU)를 생성한다.
load_file 함수는 이미지를 주어진 VM을 위한 주소 영역으로 올리고, (ioctl KVM_RUN으로) kvm_run을 호출해서 실행한다. 단순하지만, 이런 과정은 새로운 게스트 운영체제를 KVM으로 생성하는 방법을 보여준다.
Listing 1. KVM 하이퍼바이저 테스트를 위한 응용 프로그램 일부
int main()
{
void *vm_mem;
kvm = kvm_init(&test_callbacks, 0);
if (!kvm) {
fprintf(stderr, "kvm_init failed\n");
return 1;
}
if (kvm_create(kvm, 128 * 1024 * 1024, &vm_mem) < 0) {
kvm_finalize(kvm);
fprintf(stderr, "kvm_create failed\n");
return 1;
}
if (ac > 1)
if (strcmp(av[1], "-32") != 0)
load_file(vm_mem + 0xf0000, av[1]);
else
enter_32(kvm);
if (ac > 2)
load_file(vm_mem + 0x100000, av[2]);
kvm_show_regs(kvm, 0);
kvm_run(kvm, 0);
return 0;
}
|
마무리
KVM은 가상화 문제를 해결하는 흥미로운 해법이며, 처음으로 리눅스 커널에 들어간 가상화 기법이기에 서버 가상화를 위해 급속도로 지지 세력을 얻을 것임을 상상하기란 어렵지 않다. 다른 메서드는 (UML과 Xen처럼) 상당히 오랜 기간 동안 커널로 들어가려고 팽팽하게 밀고 당기기를 했지만, 다른 메서드를 제치고 KVM이 선택된 이유는 상당히 명확하다. 변경을 최소로 하고 표준 커널을 하이퍼바이저로 변환하는 특성 때문이다.
KVM을 채택함으로써 얻는 또 다른 장점은, KVM이 커널 자신이므로 커널 최적화와 개선을 활용할 수 있다. 이는 다른 독립적인 하이퍼바이저 해법과 비교해서 미래를 내다보는 접근 방법이다. KVM에는 새로운 가상화 기능을 탑재한 프로세서와 I/O 가상화를 제공하기 위한 사용자 영역 QEMU 프로세스를 요구한다는 두 가지 커다란 단점이 있다. 하지만 좋든 나쁘든 KVM은 커널에 들어갔으며, 현존하는 다른 가상화 기법과 비교해서 한발짝 앞서나가게 되었다.
참고자료 교육
제품 및 기술 얻기
- KVM에 필요한 응용 프로그램을 내려받으려면 데비안을 살펴본다.
-
DB2®, Lotus®, Rational®, Tivoli®, WebSphere®와 같은 최신 IBM 평가판 소프트웨어를 포함하는 두 장짜리 DVD 세트인 SEK for Linux를 주문하자.
-
IBM 평가판 소프트웨어: developerWorks에서 바로 내려받아, 다음번 리눅스 프로젝트 개발에 활용하자.
토론
필자소개  | 
|  | M. Tim Jones는 임베디드 소프트웨어 아키텍트이자 GNU/Linux Application Programming, AI Application Programming, BSD Sockets Programming from a Multilanguage Perspective의 저자이기도 한다. Jones의 공학 배경은 정지 위성을 위한 커널 개발에서 시작해 임베디드 시스템 아키텍처와 네트워크 프로토콜 개발에 이르기까지 다양한 분야를 아우른다. Jones는 콜로라도 주, 롱몬트 소재 Emulex 사에서 컨설턴트 엔지니어로 활약한다. |
기사에 대한 평가
 |
| 이 문서 북마킹 하기
|
|