Skip to content

필사 모드: [운영체제] 18. 가상 머신: 하이퍼바이저부터 컨테이너까지

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

가상 머신: 하이퍼바이저부터 컨테이너까지

가상화 기술은 하나의 물리 머신 위에 여러 독립적인 실행 환경을 만들어

자원 활용도를 높이고 격리를 제공합니다.

이 글에서는 전통적인 하이퍼바이저 기반 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)

가상화 기술은 하나의 물리 머신 위에 여러 독립적인 실행 환경을 만들어

작성 글자: 0원문 글자: 7,401작성 단락: 0/293