가상 머신: 하이퍼바이저부터 컨테이너까지
가상화 기술은 하나의 물리 머신 위에 여러 독립적인 실행 환경을 만들어
자원 활용도를 높이고 격리를 제공합니다.
이 글에서는 전통적인 하이퍼바이저 기반 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을 짧게 정지하고 나머지를 전송한 뒤 대상에서 재개합니다.
이를 통해 다운타임을 수십 밀리초 수준으로 줄일 수 있습니다.
현재 단락 (1/293)
가상화 기술은 하나의 물리 머신 위에 여러 독립적인 실행 환경을 만들어