- Authors

- Name
- Youngju Kim
- @fjvbn20031
가상 머신: 하이퍼바이저부터 컨테이너까지
가상화 기술은 하나의 물리 머신 위에 여러 독립적인 실행 환경을 만들어 자원 활용도를 높이고 격리를 제공합니다. 이 글에서는 전통적인 하이퍼바이저 기반 VM부터 현대적인 컨테이너까지 살펴봅니다.
1. 가상 머신의 이점
┌──────────────────────────────────────────┐
│ VM의 주요 이점 │
│ │
│ 격리 (Isolation): │
│ - VM 간 완전한 격리 │
│ - 하나의 VM 장애가 다른 VM에 영향 없음 │
│ │
│ 통합 (Consolidation): │
│ - 여러 서버를 하나의 물리 머신에 통합 │
│ - 하드웨어 활용률 향상 (15% → 70%+) │
│ │
│ 이식성 (Portability): │
│ - VM 이미지를 다른 호스트로 이동 가능 │
│ - 하드웨어 독립적 │
│ │
│ 개발/테스트: │
│ - 다양한 OS 환경 동시 운영 │
│ - 스냅샷으로 빠른 복원 │
│ │
│ 보안: │
│ - 의심스러운 소프트웨어를 VM에서 실행 │
│ - 침해 시 VM만 폐기 │
└──────────────────────────────────────────┘
2. Type 1 하이퍼바이저 (Bare-Metal)
물리 하드웨어 위에 직접 실행되는 하이퍼바이저입니다.
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Guest OS 1 │ │ Guest OS 2 │ │ Guest OS 3 │
│ (Linux) │ │ (Windows) │ │ (FreeBSD) │
├────────────┤ ├────────────┤ ├────────────┤
│ 가상 HW │ │ 가상 HW │ │ 가상 HW │
└──────┬─────┘ └──────┬─────┘ └──────┬─────┘
│ │ │
┌──────┴──────────────┴──────────────┴──────┐
│ Type 1 하이퍼바이저 │
│ (VMware ESXi, Xen, Hyper-V, KVM) │
├───────────────────────────────────────────┤
│ 물리 하드웨어 │
│ (CPU, 메모리, 디스크, NIC) │
└───────────────────────────────────────────┘
대표 Type 1 하이퍼바이저
| 이름 | 개발사 | 특징 |
|---|---|---|
| VMware ESXi | VMware | 엔터프라이즈 시장 선두 |
| KVM | Linux 커널 | Linux 커널 모듈 기반, 오픈소스 |
| Xen | Linux Foundation | 반가상화 선구자, AWS 초기 사용 |
| Hyper-V | Microsoft | Windows Server 통합 |
3. Type 2 하이퍼바이저 (Hosted)
기존 운영체제 위에서 실행되는 하이퍼바이저입니다.
┌────────────┐ ┌────────────┐
│ Guest OS 1 │ │ Guest OS 2 │
│ (Ubuntu) │ │ (Windows) │
├────────────┤ ├────────────┤
│ 가상 HW │ │ 가상 HW │
└──────┬─────┘ └──────┬─────┘
│ │
┌──────┴──────────────┴───────────┐
│ Type 2 하이퍼바이저 │
│ (VirtualBox, VMware Workstation)│
├─────────────────────────────────┤
│ 호스트 OS (macOS 등) │
├─────────────────────────────────┤
│ 물리 하드웨어 │
└─────────────────────────────────┘
Type 1 vs Type 2 비교
| 특성 | Type 1 | Type 2 |
|---|---|---|
| 실행 위치 | 하드웨어 직접 | 호스트 OS 위 |
| 성능 | 높음 (오버헤드 적음) | 보통 (호스트 OS 경유) |
| 용도 | 서버 가상화, 클라우드 | 개발/테스트, 데스크톱 |
| 격리 수준 | 높음 | 보통 |
| 관리 | 전용 관리 도구 | 호스트 OS 내 애플리케이션 |
4. 하드웨어 지원 가상화
VT-x (Intel Virtualization Technology)
하드웨어 수준에서 가상화를 지원하여 효율성을 높입니다.
소프트웨어 가상화 (바이너리 변환):
┌─────────────────────────────────┐
│ Guest OS가 특권 명령어 실행 │
│ ↓ │
│ 하이퍼바이저가 가로채기 (Trap) │
│ ↓ │
│ 바이너리 변환으로 에뮬레이션 │
│ ↓ │
│ 변환된 코드 실행 │
│ │
│ → 오버헤드 큼 │
└─────────────────────────────────┘
하드웨어 지원 가상화 (VT-x):
┌─────────────────────────────────┐
│ VMX root mode (하이퍼바이저) │
│ VMX non-root mode (Guest OS) │
│ │
│ Guest OS가 특권 명령어 실행 │
│ ↓ │
│ VM Exit → 하이퍼바이저로 전환 │
│ ↓ │
│ 하이퍼바이저 처리 │
│ ↓ │
│ VM Entry → Guest OS로 복귀 │
│ │
│ → 하드웨어가 전환 처리, 빠름 │
└─────────────────────────────────┘
메모리 가상화 - EPT (Extended Page Tables)
소프트웨어 방식 (Shadow Page Table):
Guest 가상 주소 → Guest 물리 주소 (Guest 페이지 테이블)
Guest 물리 주소 → Host 물리 주소 (하이퍼바이저 관리)
→ 두 번의 변환 필요, 하이퍼바이저가 섀도 테이블 유지
하드웨어 방식 (EPT / AMD NPT):
Guest 가상 주소 → Guest 물리 주소 → Host 물리 주소
↑ CPU가 자동 변환
→ 하이퍼바이저 개입 없이 하드웨어가 직접 처리
5. 반가상화 (Paravirtualization)
Guest OS의 커널을 수정하여 하이퍼바이저와 직접 통신하는 방식입니다.
전가상화: 반가상화:
Guest OS (수정 없음) Guest OS (수정됨)
│ │
├→ 특권 명령어 실행 ├→ 하이퍼콜(Hypercall) 호출
│ │ (시스템 콜과 유사)
├→ Trap (하드웨어) ├→ 직접 하이퍼바이저 호출
│ │
└→ 하이퍼바이저 에뮬레이션 └→ 하이퍼바이저 처리
반가상화 장점: 더 빠름 (Trap 오버헤드 없음)
반가상화 단점: Guest OS 커널 수정 필요
// Xen 반가상화 하이퍼콜 예시 (의사 코드)
// Guest OS 커널에서 직접 하이퍼바이저 호출
// 기존 (전가상화): 특권 명령어 사용
// cli (인터럽트 비활성화 - Trap 발생)
// 반가상화: 하이퍼콜 사용
void disable_interrupts_paravirt() {
// 하이퍼바이저에 직접 요청
HYPERVISOR_event_channel_op(EVTCHNOP_mask, &mask_params);
}
// 페이지 테이블 업데이트도 하이퍼콜로
void update_page_table_paravirt(pte_t *pte, pte_t new_val) {
// 직접 메모리 쓰기 대신 하이퍼콜
HYPERVISOR_mmu_update(&mmu_update, 1, NULL, DOMID_SELF);
}
6. 컨테이너 (Containers)
컨테이너는 OS 수준의 가상화로, 커널을 공유하면서 프로세스를 격리합니다.
VM vs 컨테이너
VM: 컨테이너:
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│App A │ │App B │ │App C │ │App A │ │App B │ │App C │
├──────┤ ├──────┤ ├──────┤ ├──────┤ ├──────┤ ├──────┤
│Bins/ │ │Bins/ │ │Bins/ │ │Bins/ │ │Bins/ │ │Bins/ │
│Libs │ │Libs │ │Libs │ │Libs │ │Libs │ │Libs │
├──────┤ ├──────┤ ├──────┤ └──┬───┘ └──┬───┘ └──┬───┘
│GuestOS│ │GuestOS│ │GuestOS│ │ │ │
└──┬───┘ └──┬───┘ └──┬───┘ ┌──────┴───────┴───────┴──────┐
│ │ │ │ 컨테이너 런타임 │
┌──┴────────┴────────┴──┐ │ (Docker Engine) │
│ 하이퍼바이저 │ ├──────────────────────────────┤
├───────────────────────┤ │ 호스트 OS │
│ 호스트 OS │ │ (커널 공유) │
├───────────────────────┤ ├──────────────────────────────┤
│ 물리 하드웨어 │ │ 물리 하드웨어 │
└───────────────────────┘ └──────────────────────────────┘
VM: 전체 OS 포함 (GB 단위) 컨테이너: 앱 + 라이브러리만 (MB 단위)
부팅: 분 단위 시작: 초 단위
Docker 기본 사용
# Docker 이미지 빌드
# Dockerfile 예시
# FROM ubuntu:22.04
# RUN apt-get update && apt-get install -y nginx
# COPY index.html /var/www/html/
# EXPOSE 80
# CMD ["nginx", "-g", "daemon off;"]
# 이미지 빌드
docker build -t my-nginx .
# 컨테이너 실행
docker run -d -p 8080:80 --name web my-nginx
# 실행 중인 컨테이너 확인
docker ps
# 컨테이너 로그 확인
docker logs web
# 컨테이너 중지 및 삭제
docker stop web
docker rm web
컨테이너의 격리 기술 (Linux)
┌──────────────────────────────────────────────┐
│ Linux 컨테이너 격리 기술 │
│ │
│ Namespaces (격리): │
│ ┌────────────┬───────────────────────────┐ │
│ │ PID │ 프로세스 ID 격리 │ │
│ │ NET │ 네트워크 스택 격리 │ │
│ │ MNT │ 파일 시스템 마운트 격리 │ │
│ │ UTS │ 호스트이름 격리 │ │
│ │ IPC │ IPC 자원 격리 │ │
│ │ USER │ 사용자/그룹 ID 격리 │ │
│ │ CGROUP │ cgroup 뷰 격리 │ │
│ └────────────┴───────────────────────────┘ │
│ │
│ Control Groups (cgroups - 자원 제한): │
│ ┌────────────┬───────────────────────────┐ │
│ │ CPU │ CPU 사용량 제한 │ │
│ │ Memory │ 메모리 사용량 제한 │ │
│ │ I/O │ 디스크 I/O 대역폭 제한 │ │
│ │ Network │ 네트워크 대역폭 제한 │ │
│ └────────────┴───────────────────────────┘ │
└──────────────────────────────────────────────┘
// 네임스페이스를 이용한 프로세스 격리 (의사 코드)
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define STACK_SIZE (1024 * 1024)
int child_func(void *arg) {
// 새로운 PID 네임스페이스에서 실행
// 이 프로세스는 PID 1로 보임
printf("Child PID (in namespace): %d\n", getpid());
// 새로운 호스트이름 설정
sethostname("container", 9);
// 프로그램 실행
execl("/bin/bash", "bash", NULL);
return 0;
}
int main() {
char *stack = malloc(STACK_SIZE);
// 새로운 네임스페이스에서 자식 프로세스 생성
int flags = CLONE_NEWPID // PID 네임스페이스
| CLONE_NEWUTS // 호스트이름 네임스페이스
| CLONE_NEWNS; // 마운트 네임스페이스
pid_t pid = clone(child_func, stack + STACK_SIZE, flags, NULL);
printf("Child PID (in parent): %d\n", pid);
waitpid(pid, NULL, 0);
free(stack);
return 0;
}
Kubernetes 개요
컨테이너 오케스트레이션 플랫폼으로, 대규모 컨테이너 배포와 관리를 자동화합니다.
┌──────────────────────────────────────────────────┐
│ Kubernetes 클러스터 │
│ │
│ Control Plane (마스터): │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ API │ │ Scheduler│ │ Controller│ │
│ │ Server │ │ │ │ Manager │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ ┌──────────┐ │
│ │ etcd │ ← 클러스터 상태 저장소 │
│ └──────────┘ │
│ │
│ Worker Nodes: │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Node 1 │ │ Node 2 │ │
│ │ ┌─────┐ ┌─────┐│ │ ┌─────┐ ┌─────┐│ │
│ │ │Pod A│ │Pod B││ │ │Pod C│ │Pod D││ │
│ │ └─────┘ └─────┘│ │ └─────┘ └─────┘│ │
│ │ kubelet kube- │ │ kubelet kube- │ │
│ │ proxy │ │ proxy │ │
│ └─────────────────┘ └─────────────────┘ │
└──────────────────────────────────────────────────┘
7. 애플리케이션 격리 (Application Containment)
보안 강화를 위한 다중 격리 계층
┌─────────────────────────────────────┐
│ 격리 수준 비교 │
│ │
│ VM: 강한 격리 │
│ │ (하이퍼바이저 경계) │
│ │ │
│ gVisor: 중간 격리 │
│ │ (사용자 공간 커널) │
│ │ │
│ 컨테이너: 기본 격리 │
│ │ (네임스페이스/cgroups)│
│ │ │
│ 프로세스: 최소 격리 │
│ (동일 커널 공유) │
└─────────────────────────────────────┘
8. VM 마이그레이션
실행 중인 VM을 다른 물리 호스트로 이동하는 기술입니다.
라이브 마이그레이션 과정
소스 호스트 대상 호스트
┌──────────────┐ ┌──────────────┐
│ VM (실행 중) │ │ │
│ │ │ │
│ 1. 메모리 페이지 │ │
│ 전송 시작 │───────────────→│ 수신 │
│ │ │ │
│ 2. 더티 페이지│ │ │
│ 반복 전송 │───────────────→│ 수신 │
│ │ │ │
│ 3. VM 일시 정지 │ │
│ 나머지 전송│───────────────→│ 수신 │
│ │ │ │
│ 4. VM 중지 │ │ 5. VM 재개 │
│ │ │ │
└──────────────┘ └──────────────┘
다운타임: 수십~수백 ms (거의 무중단)
9. 유니커널 (Unikernels)
애플리케이션과 필요한 OS 기능만을 하나의 단일 주소 공간 이미지로 컴파일하는 경량 VM입니다.
일반 VM: 유니커널:
┌───────────┐ ┌───────────┐
│ App │ │ App │
├───────────┤ │ + 필요한 │
│ 라이브러리│ │ OS 기능 │
├───────────┤ │ (단일 바이│
│ 전체 OS │ │ 너리) │
│ (커널 + │ └─────┬─────┘
│ 유틸리티)│ │
└─────┬─────┘ 하이퍼바이저
하이퍼바이저
크기: GB 단위 크기: MB 단위
부팅: 초 단위 부팅: ms 단위
공격 표면: 넓음 공격 표면: 매우 좁음
10. 정리
- Type 1 하이퍼바이저: 하드웨어 직접 실행, 서버/클라우드 환경에 적합
- Type 2 하이퍼바이저: 호스트 OS 위에서 실행, 개발/테스트 환경에 적합
- 하드웨어 가상화: VT-x, EPT 등으로 오버헤드 최소화
- 반가상화: Guest OS 수정으로 하이퍼바이저와 효율적 통신
- 컨테이너: 경량 격리, 빠른 시작, Docker/Kubernetes 생태계
- VM 마이그레이션: 라이브 마이그레이션으로 거의 무중단 이동
- 유니커널: 극도로 경량화된 특수 목적 VM
퀴즈: 가상 머신
Q1. Type 1과 Type 2 하이퍼바이저의 차이점은 무엇인가요?
A1. Type 1은 물리 하드웨어 위에 직접 실행되어(bare-metal) 오버헤드가 적고 성능이 우수합니다. Type 2는 기존 운영체제 위에서 애플리케이션으로 실행되어 설치가 쉽지만, 호스트 OS를 경유하므로 추가 오버헤드가 있습니다.
Q2. 컨테이너가 VM보다 가벼운 이유는 무엇인가요?
A2. VM은 각각 완전한 Guest OS를 포함하지만, 컨테이너는 호스트 커널을 공유하고 애플리케이션과 라이브러리만 패키징합니다. 따라서 컨테이너 이미지는 MB 단위로 가볍고, 시작 시간도 초 단위로 빠릅니다.
Q3. 라이브 마이그레이션에서 다운타임을 최소화하는 방법은?
A3. 사전 복사(Pre-copy) 방식에서는 VM이 실행되는 동안 메모리 페이지를 전송하고, 변경된(dirty) 페이지를 반복 전송합니다. 변경량이 충분히 줄어들면 VM을 짧게 정지하고 나머지를 전송한 뒤 대상에서 재개합니다. 이를 통해 다운타임을 수십 밀리초 수준으로 줄일 수 있습니다.