번역 거부한 FX 아지매에게 무한한 감사.

하드웨어 가상화 : 너트와 볼트

1페이지

개론

첫번째 듀얼 코어가 2005년에 나오고, 쿼드코어는 2007년에 나왔다. : 멀티코어라는 눈덩이는 계속 굴러가면서 덩치를 키우고 있다. 데스크탑 시장은 여전히 이 위력을 어떻게 써야 할지를 모색하고 있는 중이다. ; 한편, 서버 마켓에서는 2009년의 옥탈 코어를 애타게 기다리고 있다. 차이점이라면 서버 시장은 확실한 킬러 어플리케이션을 갖고 있다는 것인데, 이것은 CPU의 위력에 전적으로 의존한다. : 가상화가 그것이다.

(통합, hosting legacy applications, 자원 균형 배분, 빠른 대처 등)가상화가 갖고 오는 점들에 대해 쓸 기회가 많았는데, 대부분의 관련 발행물들은 가상화에 대해 "너트와 볼트" 로 비유하곤 한다. 우리는 VMWorld2008에서 몇몇 hypervisor 설계자들과 이야기를 나누었었다. 이 기사에서, 우리는 성능적인 관점에서 가상화가 영향을 끼치는 것을 이해하기 위해 좀 더 깊히 탐구할 것이다.

성능?그게 문제가 됐었나? 현대의 가상화 솔류션들은 성능 상에서 고작 몇 퍼센트도 안되는 저하가 되지 않나? 우리는 당신이 믿고 싶어하는 스폰서 받은 백서에서와는 약간 다른 답안을 보여줄 것이다. 우리는 오늘 가상화의 기본에 대해 보기 시작할 것이며, 우리는 다음 몇달동안 계속적으로 이 주제에 대해 탐험을 계속할 것이다.

이 첫 기사에서 우리는 "하드웨어 가상화"를 논할 것인데, 예를들어 VMware의 ESX, Xen, 그리고 Windows 2008의 Hyper-V 같은 몇몇 가상화된 서버에서 제공이 가능한 것이다. 우리는 최근 it.anandtech.com이라는 우리의 새 IT 포탈에서 Thinstall, SoftGrid, 그리고 다른 소프트웨어 패키지를 사용한 어플리케이션 가상화를 소개받았었다. 이들 기사들은 모두 가상화된 서버의 성능을 수치화 하고 가상화 기술을 좀 더 많이 이해하려는 것이었다.

하드웨어/머신 가상화 vs. "모든" 가상화

모든 것에서 우리는 가상화를 이미 몇몇 각도에서 사용하고 있다. 사실, 대부분 우리는 현대의 OS가 우리에게 제공하는 것은 가상화가 없다면 그렇게 능률적이지 않았을 것이다. 현대의 OS에서 "가상화를 쓰지 않고 순수하게 동작하는" 서버나 워크스테이션은 이미 약간의 자원을 가상화 하고 있다. : 메모리, 디스크, 그리고 CPU들이 일례가 될 수 있다. 예를들어, Windows 2003 Server 에서 4GB의 RAM 만을 사용할 수 있는 반면, 동작하는 어플리케이션중 몇몇은 사용자용 주소 영역에서의 최대 용량인 2GB(아니면 3GB) 를 사용할 수 있다는 착각을 주기도 한다. RAID-5 배열에서 사용 가능한 디스크는 3개밖에 안되지만, 당신이 10개 볼륨(이나 LUN) 을 생성한다면, 머신 내에 10개의 디스크가 있는 것처럼 보이기도 한다. 비록 서버에 2개의 CPU가 있다고 하더라도, 당신은 작동하는 다섯개의 어플리케이션이 병렬로 전속으로 작동하는 것을 볼 수도 있다.

그러면 우리가 쓰는 현대의 OS에서도 가상화가 이미 쓰이고 있다면 왜 우리가 hypervisor(나 VMM) 을 설치하여 완벽히 가상화된 서버를 만들어야 하는가? OS는 각개 프로세스에 잘 정리된 메모리 영역, 명령어에서 분리된 데이터를 부여 함으로써 약하게 어플리케이션을 분리한다. 동시에, 프로세스들은 같은 파일을 공유하고, 몇몇 공유된 메모리에 접근하기도 하며, 같은 OS 설정을 공유한다. 많은 상황에서, 이런 종류의 격리는 그렇게 충분한 대책이 아니다. 현대의 OS들이 선점형 멀티태스킹을 사용한다는 사실에도 불구하고, 한개의 프로세스가 100%의 CPU 시간을 차지한다면 다른 어플리케이션은 굼벵이 기어가듯 느리게 동작되는 것이 좋은 예이다. 완벽한 하드웨어 가상화의 경우, 당신은 그들 고유의 OS (손님 OS) 가 완벽하게 가상 서버를 분리시키고, 통신은 오직 가상 네트워크만을 통해 가능하게 된다.

2페이지

권한의 문제

한개의 물리 머신에서 몇몇개의 가상 서버를 생성하기 위해, 새로운 소프트웨어 계층이 필요하다. : 이것이 hypervisor로, 가상 머신 감시자(Virtual Machine Monitor, VMM) 라고도 불린다. 이것의 가장 중요한 역할은 기반한 하드웨어의 접근을 적당하게 조율하는 것으로, 이것으로 인해 손님 OS들이 머신을 공유할 수 있게 된다. VMM이 가상 머신을 관리하는 것은 (손님 OS + 어플리케이션) OS가 프로세스와 스레드를 관리하는 것 과 비슷하다고 말할 수 있다.

VMM이 어떻게 실제적으로 작동하는지를 이해하기 위해서는, 먼저 현대의 OS가 어떻게 작동하는지를 이해하는 것이 먼저이다. 대부분의 현대 OS는 두가지 형태로 작동한다.

- kernel 모드는 거의 모든 CPU 명령어들을 작동시키도록 허락하는데, 인터럽트, 메모리 관리 등등에 관여하는 "특권" 명령어를 포함한다. 이것은 당연히 OS가 동작하는 형태이기도 하다.
- user 모드는 데이터를 연산하고 수행하는 데에 필요한 명령어만을 허락한다. 어플리케이션들이 이 형태로 동작하며 하드웨어를 사용할 수 있게 하는 방법이라곤 커널에 작업을 하기 위한 요청을 하는 것 뿐이다. (시스템 호출)

이 모든 user/kernel 모드 에 대한 정리는 RAM이 페이지로 나뉘어져 있다는 사실에 기반한 것이다. (이것은 또한 세부 레지스터와 테이블에서도 적용될 수 있지만, 다른 기사에서 논의할 것이다.) 특권 명령어가 실행되기 전에, CPU는 첫번째로 명령어가 있는 페이지가 정확한 2비트 코드를 가지고 있는지를 확인하게 된다. 대부분의 특권 명령어들은 00으로 "특권 코드" 를 필요로 한다. 이 2비트 코드는 4개 레벨의 코드를 갖게 되는데, "11" 은 가장 낮은 레벨이 된다.

이것을 도시하자면, 이 2비트 코드는 화면상으로 네 개의 "양파링" 으로 많은 간행물에서 표시된다. (이 기사물에서도 볼 수 있다. http://en.wikipedia.org/wiki/Image:Priv_rings.svg ) Ring 0 은 가장 권한이 높은 계층으로, ring 1은 약간 권한이 적고, ring 3은 사용자 어플리케이션이 있는 곳으로 하드웨어 자원을 전부 관리 할 권한은 없다.

1.gif
소프트웨어 가상화에서의 Ring 형태를 가진 권리 분할 : 손님 OS들은 ring 0에서 동작할 수 없지만, ring 1에서 동작할 수 있다.

모든 (소프트웨어 기반의) 가상화 솔류션 기술은 ring 분할법을 사용한다. : OS는 원래 ring 0에서 동작하나 약간 권한이 줄어든 ring 1 같은 곳에서 동작하게 된다. 이것으로 하여금 VMM이 손님 OS가 자원에 접근하는 것을 제어할 수 있게 한다. 이것으로 하여금 한개의 손님 OS가 다른 손님 OS를 메모리 영역 밖으로 내치는 것이나, 손님 OS가 하드웨어를 직접적으로 제어하는 것 같은 일을 방지하게 된다.

3페이지

가상화의 도전과제

IBM S/370 같은, 가상화의 시조는, 가상 머신을 제어하기 위한 hypervisor에 대해 아주 엄격한 시스템을 사용하였었다. 모든 가상화 머신에서의 특권 명령어들은 "덫" 을 만들게 되는데, 이것은 권한이 더 적은 ring에서 "자원 관리" 명령어를 동작시키려 실행하려 할 때 나오는 오류이다. VMM은 이 모든 덫을 차단하며 이 명령어를 에뮬레이션 하는데, 동시에 다른 손님 OS들의 무결성을 위험에 빠트리지 않게 한다. 성능을 향상시키기 위해, 손님 OS와 VMM 의 개발자들은 (IBM에서의 개발자도) 이 덫의 숫자를 최소화 시키고 다양한 덫을 관리하는데 걸리는 시간을 줄이고 있다.

이런 종류의 가상화는 x86에서는 불가능한데 32/64 비트 Intel ISA는 VMM 개입이 이끌어야 하는 모든 사건에 대한 덫을 치지 않기 때문이다. 일례로 POPF는 인터럽트를 사용하거나 중지하는 명령어이다. 이 문제는 만약 이 명령어가 ring 1에서의 손님 OS에서 실행이 된다면, x86 CPU는 이것에 대해 왈가왈부 하지 않고, 간단히 무시해버린다. 이 결과로 만약 손님 OS가 인터럽트를 중지 시키려 한다면, 인터럽트는 모두 중지되지가 않으며, VMM은 뭘 어떻게 해야할지 갈피를 잡지 못하게 된다. 변함없이, 좋은 오래된 x86 ISA는 약간 정신줄을 놓고 있다. : 이들은 17개의 "인터셉트 불가능하고, VMM을 그대로 통과해버리는" 명령어를 갖고 있다.[1] 결론은 x86은 오래된 메인프레임이 가상화되었던 방법으로 가상화하지 못한다는 것이다. 우연하게도, PowerPC와 Alpha의 ISA들은 이런 고전적인 방법으로 가상화를 완벽하게 충분히 할 수 있다.

이 위의 글들은 지금까지의 역사를 아주 빠르게 간략화 한 것이다. 우리가 Intel과 AMD가 VT-x와 AMD-V에 대해 논하고 있을 때 이것을 참고해서 읽도록.

4페이지

이진 변환

VMware는 Intel이나 AMD가 "x86에서 무시하는 명령어" 를 해결하기를 기다리지 못하였으며 이전 세기 말에 (1999년) 그들의 솔류션을 발표하였다. 이 무시하는 x86 명령어를 드러내게 하기 위해, VMware는 이진 변환을 사용하였다. (불행하게도, a Tachyon detection grid가 이것의 댓가가 너무 크다고 증명하였다, http://memory-alpha.org/en/wiki/Tachyon_detection_grid ) VMware의 이진 변환은 Intel Itanium (x86->IA64), Transmeta(x86 ->VLIW), Digital FX!32(Alpha ->x86) 이나 Rosetta 소프트웨어가 사용하는 이진 변환보다 훨씬 가볍다. 이것은 한개의 명령어 셋 구조(Instruction Set Architecture , ISA) 를 다른 명령어 셋 구조로 변환은 못하더라도 이것은 x86에서 x86 변환에 기반을 두고 있었다. 사실, 몇몇 경우 이것은 원래 명령어와 똑같은 명령어 사본을 만들어내기도 하였다.

VMware는 손님 OS의 커널이 동작중 실행하기를 원하는 이진 코드를 변환하며 변환된 x86 코드를 변환 캐시(Translator Cache, TC) 에 저장하게 된다. 사용자 어플리케이션은 VMware의 이진 변환기에 구애받지 않는데 이미 이것은 사용자 코드가 안전하다는 것을 알거나 가정해놓기 때문이다. 사용자모드 어플리케이션은 그들이 변환없이 실행되었었다면 직접적으로 실행된다.

2.gif
사용자 어플리케이션은 변환되지 않으며, 바로 실행된다. 이진 변환은 손님 OS가 호출을 받았을 때만 일어난다.

커널 코드는 "x86에서 약간 더 길어진 x86" 코드 변환법으로 나아가게 된다. 이 때 당신은 손님 OS의 커널은 동작하지 않을 것이라 말할 것이다. 메모리 내의 커널 코드는 이진 변환기에 대한 입력 밖에 되지 않기에 ; 이진 변환기로 변환된 커널은 ring 1에서 동작하게 된다.

대부분의 경우, 변환된 커널 코드는 완벽한 사본이 된다. 그러나, 몇몇 경우 이진 변환기가 원래 코드에서 좀 더 길어지게 "변환된" 커널 코드를 만들어야 할 때가 있다. 만약 손님 OS의 커널이 특권 명령어를 실행시켜야 할 때, 이진 변환기는 이런 종류의 코드를 "안전한" 사용자 모드 코드로 바꾸어야 한다. 만약 커널이 물리 하드웨어의 제어권을 필요로 한다면, 이진 변환기는 가상 하드웨어를 조작하는 코드로 이진 코드를 교체할 것이다.

3.gif
x86에서 가상화된 x86으로의 이진 변환 동작 (그림 :VMware[2])

이진 변환은 손님 OS의 커널이 특정 시간에 실행해야 하거나 동작중 (가상화된) 안전한 무언가로 교체해야 할 모드 코드를 검색하게 된다. 이 "안전" 이라는 것은, 다른 손님 OS와 VMM에 대한 안전을 의미한다. VMware는 또한 변환에 대한 오버헤드를 가능한한 낮게 유지한다. 이진 변환기는 이진 변환 흐름과 변환되어 캐시에 저장되는 명령어 흐름을 최적화하지 않는다. 반복하는 경우에는, 변환을 한번만 하면 일이 끝난다는 것을 의미한다.

이 TC는 변환 캐시(Translator Cache) 만을 의미하는 것이 아니라 추적 캐시(Trace Cache) 라는 뜻도 내포되어 프로그램의 제어 흐름을 추적하기도 한다. 때마다 커널은 다른 주소 영역으로 넘어가는데, 이진 변환기는 이것의 사본을 정확히 만들 수 없다. 원래 코드가 예를들어 100바이트를 뛰어넘게 된다면, TC 내의 커널의 변환된 부분은 같은 수의 바이트를 뛰어 넘을 확률이 아주 희박하다. 이진 변환기는 코드 "사이를" 좀 더 길게 만드는 것으로 대신하게 된다.

코드를 "안전한" 코드로 바꾸는 것은 덫을 사용하여 후에 덫을 조종하는 특권 명령어를 처리하는 것보다 훨씬 덜 댓가를 치르게 된다. 그럼에도 불구하고, 이것은 이런 종류의 가상화의 오버헤드가 항상 느리다는 것을 의미하는 것이 아니다. 이 "변환 오버헤드" 는 훨씬 적으며, 이것의 효과는 시간이 지날수록 점점 적어지는데, 변환 캐시의 효과 때문이다. 그러나, 이진 변환기는 몇몇 문제를 완벽하게 해결하지 못한다.

1. 시스템 호출
2. 칩셋과 I/O, 인터럽트와 DMA의 접근
3. 메모리 관리
4. 괴상하고 복잡한 코드 (자가 변조, 간점 흐름 제어 등)

특히 첫번째부터 세번째 까지는 관심을 갖게 한다. 마지막 한가지는 OS가 "실제 모드" 에서 동작할 때도 어려운 것이므로, 이것은 당신이 한개 이상의 OS를 동작할 때에는 어떠한 성능 향상도 노릴 수 없다.

5페이지

시스템 호출

커널에 대해 많은 글이 쓰여졌지만, 가장 혼란스러운 과제 중 하나는 남아있다. 몇몇 글에서는 커널이 "군주" 같은 프로세스의 개념을 주어 항상 뒤에서 지켜보고 있다고 한다. 이것은 당연히 틀린 것인데, 왜냐면 이것은 현대의 멀티태스킹 OS가 싱글 스레드 싱글 코어 CPU에서는 작동을 하지 않는다는 것을 의미한다. 주어진 시간에 한개의 스레드만이 활성될 때, OS가 제어하는 스레드는 어떻게 되는건가?

커널은 멀티태스킹 CPU에서 시간을 쪼개어 들어가는 또다른 프로세스이다. 다른 프로세스와의 차이점이라곤 다른 프로세스들이 갖지 못하는 CPU 명령어에 접근할 수 있는 특권을 가졌다는 것이다. 그러므로, "일반적인" (사용자) 프로세스들은 하드웨어로의 접근권을 따기 위한 것 같은 특정 작업을 수행하기 위해 커널모드로의 전환을 해야 한다. 이렇게 하지 않는다면, CPU는 예외 상황을 일으키며 커널은 정신줄을 놔버릴 것이다. 동시에, 커널의 스케쥴러는 매 시간마다 개입하여 타이머 인터럽트를 사용하는데, 프로세스 하나가 CPU를 너무 길게 독점하는 것을 막도록 할 수 있게 하는 것이다. 또한 이것은 CPU가 강제적으로 매 시간마다 OS 스케줄러를 강제적으로 로드하는 것이라고도 말할 수 있다.[5]

그러므로 시스템 호출은 커널의 서비스 호출을 요청하는 사용자 어플리케이션의 결과로 볼 수 있다. x86은 시스템 호출 완료에 대하여 아주 낮은 지연시간을 제공한다. : SYSENTER (나 SYSCALL) 과 SYSEXIT 가 그것이다. 시스템 호출은 Virtual Machine Monitor에 이진 변환을 부여하여, 약간 더 추가적인 일까지 떠맡게 된다. 우리가 이전에 언급했던 것과 같이, (이진 변환 같은) 소프트웨어 가상화 기술은 (32비트) OS를 특권층을 가진 ring보다 약간 더 하향인 레벨로 떨어트리게 된다. (0 대신 1 정도) 문제는 (커널의 서비스를 요청하는) SYSENTER 가 특권 레벨 0이 있는 페이지로 보내진다는 것이다. 이것은 OS를 찾으려 하겠지만 이것은 다시 VMM으로 돌아오게 된다. 그러므로 VMM은 모든 시스템 호출을 에뮬레이트 하고, 코드를 변환하며, ring 1에서 동작하는 변환된 커널 코드로 제어권을 넘기게 된다.[3]

4.gif
시스템 호출은 가상화된 머신에서 일어나면 훨씬 복잡하게 된다.

이진 변환된 손님 OS 코드가 끝날 때, 이것은 SYSEXIT를 사용하여 사용자 어플리케이션으로 돌아가게 된다. 그러나, 손님 OS는 ring 1에서 동작하며 SYSEXIT를 수행하기에 필요한 특권을 갖고 있지 않으므로, CPU는 ring 0 레벨의 오류를 내며 VMM은 손님 OS가 끝마쳐야 하는 것을 에뮬레이트 해야한다. 시스템 호출은 아주 많은 오버헤드를 낸다는 것은 자명하다. 가상화된 머신 상에서의 시스템 호출은 대충 실제 모드 머신보다 10배 정도의 댓가를 더 지불한다. VMware의 엔지니어들은 3.8Ghz Pentium 4에서 측정하기를 ;[4]

- 실제모드 시스템은 시스템 호출에 242사이클 정도를 소비한다.
- ring 1에 있는 이진 변환이 사용된 32비트의 손님 OS에서는 2308사이클을 소비한다.

만약 당신이 몇몇개의 가상화된 머신을 쓰고 있다면, 시스템 호출은 요즘 OS를 사용하는 실제 모드의 머신에서의 백그라운드 작업보다 훨씬 더 많은 작업을 한다는 말이 된다.

6페이지

I/O 가상화

I/O는 어떠한 형태의 가상화에서도 가장 큰 문제이다. 만약 가상화된 서버의 CPU가 성능이 떨어진다면, 당신은 CPU나 코어를 추가하면 된다. (예를들어, 듀얼 코어 CPU를 쿼드코어로 바꾸는 것 정도로 가능하다.) 그러나, 메모리 대역폭, 칩셋, 그리고 저장 HBA들은 대부분 모든 가상 머신에서 공유하고 있으며 이로 인해 "업그레이드" 하기에 아주 어렵다. 게다가, CPU와는 반대로, 대부분의 가상화 소프트웨어 내에서 다른 하드웨어들은 에뮬레이트 된다. 이것은 가상 하드웨어 컴포턴트의 드라이버로의 접근마다 실제 드라이버로의 변환이 필요하다는 말이다.

5.jpg
실제 3.46Ghz의 Intel Xeon 프로세서들이 에뮬레이트된 BX 칩셋에서 동작하고 있다. :우리는 VM 내에서 동작시키는 중이다.

만약 예를들어 ESX 내에서 가상 머신의 하드웨어를 조사한다고 할 때, 여기서 요즘의 CPU들이 나온지 9년이나 됐지만 탁월한 BX 칩셋과 같이 동작하는 것을 볼 수 있으며, 당신의 HBA도 항상 낡은 버스 회로나 LSI 카드에 상주해 있게 된다. 이것은 또한 이 최신의 속임수를 써서 당신의 하드웨어로, 사용할 수 없는 성능을 낼 수 있다는 것을 의미한다.

7페이지

메모리 관리

OS는 물리 메모리 주소 내로 가상 메모리 페이지를 페이지 테이블로 변환하여 관리한다. 모든 현대의 x86 CPU들은 하드웨어 내에 가상 메모리 지원을 제공한다. 가상에서 물리 주소로의 변환은 메모리 관리 유닛, MMU에서 수행된다. 현재의 주소는 (하드웨어 페이지 테이블 포인터인) CR3 레지스터에 들어가게 되며, 페이지 테이블에서 대부분 사용된 부분들은 TLB들 안으로 캐시되게 된다.

가상 머신 상에서 동작하는 손님 OS가 실제 페이지 테이블에 접근할 수 없다는 것은 당연하다. 대신, 손님 OS는 MMU가 에뮬레이트한 페이지 테이블 상에서 동작한다. 이들 테이블은 손님 OS로 하여금 가상 손님 OS의 주소들을 실제 물리 주소들로 변환할 수 있다는 착각을 주게 되지만, 실제로는 VMM이 이들 사이에서 "보이지 않게" 활동하고 있어서, 손님 OS에서는 신경을 쓰지 못하게 된다. 이 실제 페이지는 숨겨진 VMM으로 관리되어 있으며 여전히 실제 MMU 상에서 동작한다. 그러므로 실제 페이지 테이블은 손님 OS의 가상주소를 실제 물리 페이지로 변환하는데 쓰이는 "그림자 페이지 테이블"로 구성되어 있다.

매번 손님 OS는 그들의 페이지 매핑을 변화시키는데, 가상 MMU 모듈은 이 변화를 잡아내며 이에 따라 그림자 페이지 테이블을 조정하게 된다. 당신이 추측할 수 있듯, 이것은 아주 많은 CPU 사이클을 소모하게 된다. 가상화 기술과 페이지 테이블 내에서 만드는 변화에 따라, 이 과정은 실제 모드 상황에서 보다 3배~400배(!) 정도의 사이클을 더 소모하게 된다.[3] 이것은 격렬한 메모리 사용을 하는 어플리케이션에서는, 가상화로 인해 치뤄야 할 댓가는 그 중 메모리 관리에 관한 부분이 가장 큰 성능상의 약점으로 야기된다.

8페이지

Paravirtualizaion(이상가상화)

이상가상화는 이진 변환과 다르지 않다. 이진 변환은 동작 중 "치명적"이거나 "위험한" 코드를 무해한 코드로 바꾼다. ; 이상가상화는 같은 일을 하지만, 원본 코드에서 일을 하게 된다. 물론, 원본 코드를 바꾸는 것은 동작 중에 모든 것을 바꾸는 것보다 조금 더 유연하게 되는 것을 가능케 하는데, 이진 변환은 또한 빠르게 처리해야 하기도 한다. 이상가상화의 한가지 장점은 이진 변환보다 더 많이, VMM(이나 hypervisor) 으로 인해 수많은 불필요한 "덫" 들을 없앤다는 것이다.

hypervisor는 메모리 관리, 인터럽트 조정, 시간 관리 같은 치명적인 커널 수행에 hypercall 인터페이스를 제공한다. 이들 hypercall은 필요할 때만 일어나게 된다. 예를들어, 대부분의 메모리 관리는 각기 다른 손님 OS들로 인해 이루어 진다. hypervisor는 페이지 테이블 갱신과 DMA 접근 같은 "호출된" 것들에게서만 일어난다.

6.gif
프론트 엔드 드라이버 인터페이스부터 "일반적인" 리눅스 백엔드 드라이버들의 단순도식화

이 가상화의 Xen 도입에서의 최상의 특징은 I/O가 조종되는 방법이다. VM 내에서의 I/O 기기는 인터페이스가 단순화되어 특권 VM 내에서 (Xen에서는 Domain 0이라고 부른다.) 실제 본래 드라이버로 연결이 된다. 이것은 여기에는 에뮬레이션이 없다는 것을 의미하며, 이로 인해 오버헤드는 확실히 줄어들게 된다. 이것은 Xen 에서의 광고보다 VMware ESX에서 도시된 것이 더 효율적이었다. : VM들이 초기 ESX 버젼 상에서 동작 하였을때 훨씬 낮은 네트워크 성능을 가졌었는데, ESX 3.x 상에서 동작한 VM들은 훨씬 용납할만한 네트워크 성능을 내주었는데, 이것이 바로 이상가상화된 vmxnet 네트워크 드라이버를 도입한 덕분이었다.

계속 하자면, 이상가상화는 아주 훌륭한 개념인데, (이진) 변환의 오버헤드,를 완벽하게, I/O 드라이버의 오버헤드를 눈에 띄게, 그리고 시스템 호출 오버헤드를 약간 없애게 되었다. 아주 자주 쓰이는 인터럽트와 시스템 호출은 여전히 오버헤드를 일으킨다. 우리는 나중의 기사에서 Xen을 좀 더 자세하게 공부할 것이다. 가장 큰 단점들은 :

1. 변조되지 않은 손님 OS를 사용할 수 없다. (이상가상화만 사용한다면)
2. 64비트 손님 OS는 특권이 없는 상태로 동작시켜야 한다.(ring 3)[6]

7.gif
소프트웨어 이상가상화는 64비트 OS들을 잘 조종하지 않는다.

두번째 문제는 그렇게 큰 문제로 보이지 않지만, OS를 보호하기 위해서는, 페이지 테이블 전환이 필요하게 된다. 이 결과 두개의 시스템 호출과 TLB 폐기는 아주 큰 댓가를 지불하게 된다. 이제 Intel의 VT-x와 AMD-V가 우리에게 제공할 수 있는 것이 무엇인지 알아보자.

9페이지

하드웨어 가속 가상화 : Intel VT-x와 AMD SVM

하드웨어 가상화는 모든 오버헤드를 최소한으로 줄이게 된다. 맞나? 불행하게도, 꼭 그렇지는 않다. 하드웨어 가상화는 이진 변환이나 이상가상화의 향상된 버젼이 아니다. 정말 아니다. 하드웨어 가상화 이면에 숨어 있는 처음 생각으로는 가상화될 수 없는 x86 명령어 아키텍쳐에 대한 문제를 고치기 위한 것이었다. 이것은 하드웨어 가상화가 "VMexit"라고 불리우는 손님 OS로부터 VMM으로의 강제 전이에 관한 모든 예외 상황과 특권 명령을 모두 잡으려는 철학에 기반한다. 이것은 IBM S/370 가상화 형태의 향상된 버젼이라고 부르면 된다.

한가지 가장 큰 이점은 손님 OS가 그들이 의도한 특권 레벨 (ring 0) 에서 동작한다는 사실과, VMM은 이것보다 더 높은 특권 레벨이라는 새로운 ring에서 동작한다는 것이다. (ring -1 아니면 "root mode"라고 부른다.) 시스템 호출은 VMM 개입에 따른 결과로 자동적으로 나오지 않는다. : 시스템 호출은 치명적인 명령어를 포함하지 않으며, 손님 OS는 사용자 어플리케이션으로 커널 서비스를 제공할 수 있게 된다. 이것이 하드웨어 가상화의 큰 이점이다.

8.jpg
하드웨어 가상화로 인해, 손님 OS는 원래 있던 ring 0으로 되돌아온다.

-하드웨어로 도입이 되었음에도 불구하고 - 문제는 VM에서 VMM(VMexit)와 back(VMentry)로의 전이에서 고정된(그리고 큰) 숫자의 CPU 사이클을 요구 한다는 것이다. 이런 특정한 수의 이들 "오버헤드 사이클들" 은 내부 CPU 설계에 의존하게 된다. (VMexit, VMentry, VMread 등의) 정확한 명령어에 의존하면, 이들 종류의 상황은 몇백에서 최고 몇천 CPU 사이클을 소비할 수도 있다!

하드웨어 가상화에서의 VM/VMM 과정은 그러므로 훨씬 더 부하가 걸리는 상황이다. Intel VT-x나 AMD SVM(또는 AMD-V) 가 (많은 CPU 사이클을 조종해야 하는) 시스템 호출 같은 확실히 복잡한 수행을 조종해야 할 때, VMexit/VMentry의 전환에 대한 페널티는 그렇게 많지 않다. 한편, VMM이 가로채거나 에뮬레이트를 하는 등의 실제 명령 수행에서는 이것이 좀 더 단순해지는데, VMM에서의 여러 종류의 앞뒤 전환을 할 때의 오버헤드는 엄청나게 된다!

프로세스 생성, 상황 전환, 적은 페이지 테이블 갱신 등의 간단한 명령 수행은 가상모드가 아닌 일반적으로 수행할 때에는 약간의 사이클만을 소비하므로, "VMM으로의 전환 후 백엔드로의 전환" 에서의 시간 낭비는 무시할 수 없는 엄청난 양의 사이클이 된다. (가상화가 아닌 일반 적인 상황과 비교한 것이다.) 이진 변환에서, 변환기는 단순하게 VMM이 조종하는 것보다 약간 더 긴 코드로 교체를 하게 된다. 이상가상화에서도 이것은 같은데, 이런 종류의 상황을 조종할 때에 하드웨어 가상화보다 훨씬 빠르게 된다.

9.gif
VMM과 exit VMM 지연시간은 각기 다른 Xeon 제품군이 나올 때마다 계속적으로 줄고 있다.

첫번째 방법으로 Intel과 AMD는 이 문제를 VT-x 명령어가 소비하는 사이클의 숫자를 줄임으로써 해결하려 했다. 예를들어, VMentry 지연시간은 (Xeon Paxville이나 Xeon 70xx에서의) 634 사이클에서 (Xeon 51xx) Woodcrest, (Xeon53xx) Clovertown, 그리고 (Xeon 73xx) Tigerton에 와서는 352 사이클로 줄어들었다. 위의 그래프에서도 볼 수 있듯이, 2005년에서의 첫 VT-x의 도입은 가상화된 머신에서의 속도 증가에 대해 그리 도움이 되진 않았다. 가장 최신의 Xeon 54xx("Harpertown") 은 12~25%의 VMM 지연시간을 줄였다는 것이 가장 중요한 것으로써, 그렇게 중요치 않은 명령어에서는 최대 75% 까지 줄일 수 있게 되었다. 우리는 더욱 정확한 숫자를 알아내었는데, 바로 아래 나온다.

10.jpg
각기 다른 Intel 제품군에서의 진출입하는 VMM 갯수(ns단위)

두번째 전략은 VMM 상황의 갯수를 줄이는 것이었다. 이것으로 인해, 전체 가상화 오버헤드는 상황의 갯수와 상황의 댓가를 곱한 것과 동등하게 되었다. 방정식 형태로 나타내면 :

모든 VT 오버헤드 = ("VMM에서 VM"으로의 상황의 빈도 * 상황의 지연시간)의 합

 - 메모리(캐시) 내에 위치한 테이블로 분류되며 VT-x와 AMD SVM의 한 부분인 - 가상 머신 제어 블럭이 도움이 된다. 이것은 각기 손님 OS에 대한 가상 CPU들의 상태를 포함하게 된다. 이것으로 하여금 손님 OS들은 VMM에서의 간섭 없이 직접적으로 동작할 수 있게 된다. VMCB에 설정된 제어 비트에 따라서, VMM은 손님 OS로 하여금 몇몇 하드웨어 부분, 인터럽트, 그리고 페이지 테이블 수행의 약간 부분을 수행할 수 있게 된다. 그리하여 VMM은 VMCS를 설정하여 VM(손님 OS) 으로 하여금 특정 상황에서 빠져 나오도록 시킬 수 있는데, 반면, VMM은 손님 OS로 하여금 다른 것은 계속적으로 수행하게 한다. 이것은 CPU가 손님 OS에게 강제적으로 정지(VMexit)를 실행시켜야 하는 횟수를 잠재적으로 줄일 수 있게 되며, 그 후 CPU는 VMX root 모드(ring -1) 로 전환하며 VMM이 이 권한을 떠맡게하게 된다.

10페이지

2세대 : Intel의 EPT와 AMD의 NPT

우리가 "메모리 관리" 부분에서 논의 하였을 때에, 각기 다른 손님 OS의 가상 메모리 관리와 이것을 물리 페이지로 변환하는 것은 극도로 CPU에 의존하게 된다고 하였었다.

11.gif

그림자 페이지들이 없다면 우리는 (파란색의) 가상 메모리를 (회색의) "손님 OS의 물리 메모리"로 변환하여 넣어야 하며 이 후 이 변환된 것을 다시 (녹색의) 참 물리 메모리 영역으로 넣어야 한다. 행운스럽게도, "그림자 페이지 테이블" 트릭으로 인해 이중 예약을 피할 수 있는데 MMU로 하여금 (손님 OS의 파란색) 가상 메모리에서 (녹색의) 실 물리 메모리 페이지 테이블로의 작업을 함으로써, 효과적으로 중간의 "손님 OS 물리 메모리" 단계를 지나칠 수 있게 된다. 그러나 이것은 한가지 난관에 부딪히는데 : 손님 OS의 페이지 테이블의 갱신 때마다 "그림자 페이지 테이블으로" 약간의 예약을 요구하게 된다는 것이다. 이것은 소프트웨어 기반의 가상화 솔류션 (이진 변환과 이상가상화) 에서는 성능상에 악재가 되나, 초기 하드웨어 가상화 솔류션에서는 성능을 더욱 사정없이 황폐하게 만들어 버린다. 이유는 이것으로 인해 엄청나게 많은 VMexit와 VMentry 호출이 생겨나게 되기 때문이다.

2세대 하드웨어 가상화에서, AMD의 nested 페이징과 Intel의 EPT 기술은 이 문제를 엄청난 하드웨어 위력으로 약간이나마 풀게 되었다.

12.gif
EPT나 Nested 페이지 테이블은 "뛰어난" TLB에 기반을 두어 손님 OS와 VMM 메모리 관리 모두를 추적하게 된다.

위의 그림에서 볼 수 있듯이, 격리된 페이징은 하드웨어적으로 지원하는 CPU에서 (손님OS의) 가상 메모리에서 (손님 OS의) 물리 메모리화 시키는 것을 (손님 OS의) 물리 메모리에서 참 물리 메모리로의 전이같이 하여 TLB에서 캐싱하게 된다. TLB는 새로운 주소 영역 식별자 (Address Space IDentifier, ASID) 라는 새로운 VM 특정 태그를 가지게 된다. 이것으로 하여금 TLB가 어떤 TLB엔트리가 어떤 VM에 소속되었는지를 추적할 수 있게 한다. 이것으로 인해 VM 스위치는 TLB를 폐기하지 않게 된다. 각기 다른 가상 머신에서의 TLB 엔트리들은 모두 TLB 내에서 평화롭게 공존하게 된다. 이 제공된 TLB는 당연히 충분히 크다!

이것은 VMM으로 하여금 훨씬 단순하고 완벽히 정기적인 그림자 페이지 테이블의 갱신에 대한 필요성을 불식시켜 버린다. 만약 우리들이 Hypervisor가 (VM이 동작할때마다 1번씩) 그림자 페이지 테이블의 갱신 마다 개입해야 한다고 고려 한다면, 격리된 페이징이 확실히 성능 향상에 일조한다는 것은 당연하다.(AMD에 따르면 최대 23% 의 성능 향상이 있다.) 격리된 페이징은 특히 당신이 VM당 1개 이상의 (가상) CPU를 쓸 때 중요하다. 다수의 CPU들은 종종 페이지 테이블을 동기 시켜야 하는데, 이 결과로 인해 그림자 페이지 테이블은 훨씬 더 갱신을 자주 해주어야 한다. 그림자 테이블의 성능상의 약점은 VM당 더 많은 (가상의) CPU를 쓸 때마다  더 커지게 된다. 격리된 페이징으로 인해, CPU는 간단히 TLB를 동기화 시키는데, 가상화 되지 않은 환경에서 끝마치기 때문이다.

여기에서는 한가지 단점만이 있다. 격리된 페이징이나 EPT는 TLB가 정확한 엔트리에 주소를 갖고 있지 않다면 가상 주소를 참물리 주소로 전이 시키는데 훨씬 복잡해지게 된다. 각기 단계마다 하늘색 영역에서 나아갈 떄마다, 우리는 또다시 오렌지색 영역에서 한단계씩 나아가야 한다. 그러므로, "가상화되지 않은 상황" 에서 4개의 테이블 검색자는 16개의 검색자로 늘어나게 된다. (파란색에서 4개, 오렌지 에서 4개)

이것을 보상하기 위해, CPU는 이전보다 훨씬 큰 TLB를 필요로 하게 되었으며, TLB 미스로 하여금 이제는 아주 큰 댓가를 치르게 한다. 만약 TLB 미스가 가상화되지 않은 실제 상황에서 일어난다면, 우리는 메인 메모리에서 4개의 검색자를 가동시켜야 된다. TLB 미스는 이때 성능 하락을 가져오게 된다. 이제 "가상화된 OS에서의 격리된 페이징" 에서의 TLB 미스 상황을 보도록 하자. : 우리는 높은 지연시간을 가진 시스템 램에 위치한 테이블 내에서 16개의 검색자를 구동시켜야 한다. 우리의 성능 하락은 성능 재난으로 바뀌게 된다! 다행스럽게도, TLB가 더욱 커짐으로 해서 극소수의 어플리케이션만이 수많은 TLB미스를 야기하게 되었다.

11페이지

표준화 해주세요!

AMD와 Intel은 전철을 밟고 있다. : 호환되지 않은 x86 확장자를 말하는 것이다. 특수화된 하드웨어 가상화 확장자는 표준화되질 않았다. 이것은 소프트웨어 개발자가 Intel의 VT-x와 AMD의 SVM을 지원하기 위해 분리된 모듈을 개발하고 지원해야 함을 의미한다. Xen 3.0.2는 두 기술 모두를 지원하는데, Xen 3.0.2의 9500개의 라인/8%의 코드가 이것을 지원하기 위한 코드이다. AMD와 Intel의 표준화에 대한 부족이 Xen의 VMM을 4%정도 팽창시켜놓게 되었는데, 여전히 관리 가능하긴 하다. 아직 이것이 통제 불능 정도는 아닌데, AMD와 Intel의 확장자 사이의 차이점은 아주 작아 당신은 실제로 이 두 다른 확장자에 대한 요점이 무엇인지 물어야 할 필요가 생길 것이다.

그러면 어떤 CPU가 지원을 하는가? 아래 표는 가장 중요한 서버 CPU들이다.

가상화를 지원하는 CPU
프로세서 가상화 종류 지원 등급
Xeon 50xx, Xeon 70xxx 와 Xeon 71xx 하드웨어 가상화 지원
(HVT 만)
좀 느리다.
Opteron Socket-F, Xeon 53xx 하드웨어 가상화 지원
(HVT 만)
중간정도
Xeon 54xx 하드웨어 가상화 지원
(HVT 만)
꽤 빠름
Nehalem, Quad-core Opteron HVT and Nested paging
(EPT/NPT)
알려지지 않음

DDR메모리를 지원하는 AMD Opteron의 8xx와 2xx가 HVT를 지원하지 않는다는 것은 중요하게 봐야 한다. ; 그러나, 이들은 초기 HVT를 지원하는 Xeon과 비교하여 약간 더 빨랐었다.

12페이지

벤치마크

성능은 가상화의 복음을 전도하는 사람들 사이에서는 그렇게 인기있는 분야가 아니며 광택지에 인쇄된 소책자에서도 세부적인 사항은 나오지 않는다. 대부분 나온 벤치마크의 개략적인 것만 봐도 이것은 흥미 유발의 부재를 합당화 시킬 수 있을 정도이다. : 요즘 시대에 위력적인 쿼드코어 CPU에서 3~10%의 성능 하락을 걱정하겠는가? 실제로, hypervisor나 VMM 기반의 가상화 -ESX, Xen 같은 - 의 성능은 아주 괜찮은데, 특히 만약 VMware Server 버젼이나 microsoft의 Virtual Server 2005 같은 호스트 기반 솔류션에 비교할 때 두드러진다. 후자는 그들의 가상화 레이어를 호스트 OS의 최상위층에서 동작시키므로, 이것으로 하여금 더 낮은 성능을 내게 만든다.

아래의 그래프를 보자.[6] 이것은 Cambridge 대학에서 수행된 벤치마크이다. 벤치마크는 가상화되지 않은 Linux 성능(L) 과 Xen 성능에서와 (X) VMware Workstation 에서(V) 그리고 사용자모드 Linux를 보여주고 있다. 후자는 호스트 OS 가상화에 기반하고 있다. : 가상화 계층은 호스트 OS의 최상위층에서 동작한다.

14.jpg
호스트 OS에서의 최상위층에서의 가상화는 많은 보통의 기업형 어플리케이션에서는 좋지 않은 생각이다.

가상화 벤더(http://blogs.xensource.com/rogerk/wp-content/uploads/2007/03/hypervisor_performance_comparison_1_0_5_with_esx-data.pdf) 에서 많이 인용된 벤치마크(http://www.vmware.com/pdf/hypervisor_performance.pdf) 는 SPEC CPU 2000 integer이다. 당신이 이들 링크에서 볼 수 있듯, 모든 종류의 가상화 기술의 점수가 아주 잘 나오는 것을 볼 수 있다. 이들 점수에 따르면, Xen은 가상화가 되지 않은것 같이 성능이 잘 나오나, Linux 커널 컴파일 같은 메모리에 부하를 많이 주는 벤치마크를 시작하면, OS 호스트를 이용하는 가상화 솔류션은 성능이 급락하는 것을 볼 수 있다. OLTP와 웹 어플리케이션으로 가면 성능은 간단히 나락으로 떨어지는 것을 볼 수 있다.

이것이 왜 SPEC CPU 2000 integer가 아주 유명한지를 입증한다. 이것은 CPU 의존적인 벤치마크로써 다른 하드웨어에 접근을 하는 일이 희귀하여, 그러므로 이것은 OS 커널을 사용하는 시간을 상당부분 피할 수 있게 된다. 또한 두드러진 것은 "2000" 버젼이 사용된다는 것이다. 2006 버젼은 메모리에 대한 의존성이 더 커졌기 때문에, 가상화되었을 때 더욱 성능 하락을 가져오기도 한다.

하여간, 가상화된 머신에서의 SPEC CPU 2000 integer 수치는 아주 적은 것만을 증명한다. 이런 종류의 소프트웨어는 완벽하게 VMM이 처리하는 도전적인 코드를 피하게 된다. Specjbb2005는 무엇인가? 이 서버 벤치마크는 또한 가상화 벤더에서 성능 수치를 언급 하는 데에 많이 쓰였었다. 이것들이 몇몇 결과를 보여주는 것은 사실이지만, 대부분 Specjbb 2005 벤치마크는 한개의 CPU에서 동작하며, 만약 1개 이상의 가상 CPU에서 동작한다면, 한개의 VM만이 활성화되게 된다. 이것은 물론 아주 비현실적이다. : 오직 한개의 VM만을 돌리려면 당신의 서버를 가상화 하진 않을 것이다.

다음 기사에서 완전한 벤치마크 보도를 할 것이지만, 우리가 지금까지 한 몇몇 벤치마크를 한번 맛보기로 보도록 하자. 우리는 쿼드 Xeon MP Intel SR6850HW4 (4x 3.2Ghz 듀얼 코어 Xeon 7130M, http://www.anandtech.com/IT/showdoc.aspx?i=2872&p=5) 과 우리가 설정한 것(http://www.anandtech.com/IT/showdoc.aspx?i=2872&p=7) 과 같은 방법으로 Specjbb2005를 동작 시켰다. 벤치마크에서 모순을 피하기 위해 Hyper threading을 사용하지는 않았다.

가상화 성능 테스트
VM 갯수 VM당 CPU갯수 SUSE SLES 10
Xen 3.0.3
VMware ESX 3.0.2
1 1 1% 3%
1 4 3% 7%
4 2 5% 15%
4 4 7% 19%

우리의 참을성 없는 독자들을 위해 : 그래, 가장 최근의 Xeon, Opteron, 그리고 hypervisor가 들어 있는 (ESX 3.5 등) 완벽하게 갱신된 보도가 여기 있다. 우리는 이들 수치가 가상화라는 풍경에 대해 알맞은 사진을 주지 않는 다는 것을 십분 인식하고 있지만, 포괄적인 개념 이라는 것은 아니다. 이것은 맛보기에 불과하니까.

그러나, 심지어 이런 약간 유통기한 지난 결과까지도 매우 흥미롭다. 만약 주의를 기울이지 않는다면, "한개 VM에 한개 CPU" 라는 벤치마크는 당신에게 가상화가 성능상의 하락이 전혀 없이 된다고 말하는 것 같이 보일 것이다. 그러나, 훨씬 더 현실적인 설정인 4개의 가상 머신을 동작 시키고 각기 가상머신에 2개의 가상 CPU를 지정할 수 있는데, 8개의 코어가 사용 가능하기 떄문이다. 성능 저하는 그렇게 두드러지진 않지만, 왠만큼 비교는 가능해진다.

마지막 줄에서, (VM당 4개 가상 CPU) 우리는 여전히 2-2-2-2 설정으로 정확히 같은 부하량을 사용하였다. 가장 고부하일 때, 우리는 8개 스레드만 동작시켰다. 평균적으로 성능 하락은 좀 더 높았지만, 위의 표가 모든것을 말해주진 않는다. 아래 그래프를 보라.

13.gif

갖고 있는 CPU보다 더 많은 가상 CPU를 지정하면, 각기 실제 CPU당 한개의 가상 CPU를 지정했을 때 보다 가상화된 성능에서는 낮아진 성능이 더 낮아질 수 있다는 것이 중요하다.

오해하지 말라 : 현대의 가상화 제품은 대부분 아주 좋은 성능을 제공한다. 그럼에도 불구하고, 가상화를 하더라도 어떠한 눈에 띄는 성능상의 하락이 거의 모든 상황에서 없다는 것도 정확한 것이 아니다. 예를들어, 간단한 OLTP sysbench 를 로드하는 것만으로도 아주 위력적인 Xeon 5472 서버에서 20% 이상의 성능 하락을 가져옴을 알게 되었다. 몇몇 경우에서는 40% 대역까지 성능이 떨어지는 것을 보았다. 테스트에 대한 노력이 계속적으로 진행되어 있으므로 이것을 분석하기엔 너무 이르지만, 더 많은 성능상의 연구는 몇몇 흥미로운 결과를 내놓을 것으로 기대된다.

http://it.anandtech.com/IT/showdoc.aspx?i=3263&p=1

Bibliography

[1] Robin/Irvine, 9th USENIX Security Symposium Paper 2000: "Analysis of Pentium's Ability to Support a Secure VMM"

- http://www.usenix.org/events/sec00/full_papers/robin/robin_html/index.html

[2] Scott Devine, Co-Founder & Principal Engineer VMware, Inc., "Introduction to Virtual Machines Introduction to Virtual Machines"

[3] Ole Agesen, VMware, "Performance aspects of x86 virtualization", VMWorld 2008

[4] Keith Adams, Ole Agesen, VMware "A Comparison of Software and Hardware Techniques for x86 Virtualization"

[5] Daniel P. Bovet, Marco Cesati, "Understanding the Linux Kernel 3rd Edition" , O'Reilly

November 2005, ISBN: 0-596-00565-2, section 1.6

[6] Paul Barham , Boris Dragovic, Keir Fraser, Steven Hand, Tim Harris, Alex Ho, Rolf Neugebauer , Ian Pratt, Andrew Wareld, "Xen and the Art of Virtualization", University of Cambridge Computer Laboratory

기글하드웨어(http://gigglehd.com/zbxe)에 올라온 모든 뉴스와 정보 글은 다른 곳으로 퍼가실 때 작성자의 허락을 받아야 합니다. 번역한 뉴스와 정보 글을 작성자 동의 없이 무단 전재와 무단 수정하는 행위를 금지합니다.