04. Proxmox VE Compute — CPU, Memory, VM & LXC

가상화의 핵심 리소스 — CPU와 메모리가 VM/LXC에 어떻게 할당되고 관리되는가


📌 이 글의 목적

CPU와 메모리는 가상화의 가장 핵심적인 리소스임. “vCPU 4개, 메모리 8GB”로 VM을 만들었을 때, 물리 자원이 어떻게 매핑되고 스케줄링되는지를 이해하면 성능 설계, 오버커밋 전략, 리소스 경합 분석의 기반이 됨.

이 글을 읽고 나면:

  • vCPU가 물리 CPU에 어떻게 매핑/스케줄링되는지 이해할 수 있음
  • NUMA 토폴로지가 VM 성능에 미치는 영향을 설명할 수 있음
  • 메모리 오버커밋과 Ballooning의 동작 원리를 이해할 수 있음
  • KVM VM과 LXC의 리소스 관리 차이를 비교할 수 있음
  • VMware의 CPU/Memory 관리 모델과 구조적 차이를 비교할 수 있음

1. CPU 가상화와 스케줄링

1.1 vCPU와 물리 CPU의 관계

Proxmox에서 VM에 할당하는 vCPU는 물리 CPU 코어와 1:1 고정이 아님. 각 vCPU는 QEMU 프로세스 내의 스레드로 표현되며, Linux CFS(Completely Fair Scheduler)가 이를 물리 코어에 스케줄링함.

flowchart TB
    subgraph Physical["물리 CPU (8코어)"]
        Core0["코어 0"]
        Core1["코어 1"]
        Core2["코어 2"]
        Core3["코어 3"]
        Core4["코어 4"]
        Core5["코어 5"]
        Core6["코어 6"]
        Core7["코어 7"]
    end

    subgraph CFS["Linux CFS 스케줄러"]
        Sched["시분할 스케줄링"]
    end

    subgraph VM_Threads["VM 스레드들"]
        VM1_T0["VM1 vCPU0"]
        VM1_T1["VM1 vCPU1"]
        VM2_T0["VM2 vCPU0"]
        VM2_T1["VM2 vCPU1"]
        VM2_T2["VM2 vCPU2"]
        VM2_T3["VM2 vCPU3"]
        Host_P["호스트 프로세스들"]
    end

    VM_Threads --> CFS
    CFS --> Physical

핵심 포인트:

  • vCPU는 특정 물리 코어에 고정(pin)되지 않는 한, CFS가 자유롭게 스케줄링함
  • 물리 코어 수보다 더 많은 vCPU를 할당할 수 있음 (CPU 오버커밋)
  • 오버커밋 시 CFS의 시분할에 의해 각 vCPU의 실행 시간이 줄어듦

1.2 CPU 토폴로지 설정

Proxmox에서 VM의 CPU 토폴로지를 설정할 때 3가지 요소가 있음.

항목설명예시
Sockets가상 CPU 소켓 수1
Cores소켓당 코어 수4
vCPUs (총합)Sockets × Cores4
# 예시: 2소켓 × 4코어 = 8 vCPU
qm set 100 --sockets 2 --cores 4

소켓 vs 코어 — 어떻게 설정하나?

설정게스트 OS가 보는 것용도
1소켓 × 8코어8코어 1소켓 CPU✅ 일반적 (NUMA 1노드)
2소켓 × 4코어4코어 2소켓 CPUNUMA 매핑, Windows 라이선스 고려 시
8소켓 × 1코어1코어 8소켓 CPU❌ 비추천 (NUMA 비효율)

💡 Windows 라이선스: Windows Server의 일부 에디션은 소켓 수에 따라 라이선스가 달라짐. VM에서 소켓 수를 최소화하면 라이선스 비용을 절약할 수 있음.

1.3 CPU 타입

설정의미성능마이그레이션
host호스트 CPU 기능을 그대로 노출✅ 최고❌ 동일 CPU만
kvm64 / qemu64최소 가상 CPU낮음✅ 어디서든
x86-64-v2-AESx86-64 마이크로아키텍처 레벨 v2 + AES좋음✅ v2 이상
x86-64-v3AVX2 등 포함더 좋음v3 이상
x86-64-v4AVX-512 포함높음v4 이상

추천 전략:

  • 단일 노드 / 동일 CPU 클러스터 → host (최고 성능)
  • 이기종 CPU 클러스터 → x86-64-v2-AES 또는 x86-64-v3 (마이그레이션 호환성 확보)

💡 VMware의 EVC(Enhanced vMotion Compatibility)와 유사한 개념. EVC가 클러스터 수준에서 CPU 기능을 통일하는 것처럼, Proxmox에서는 CPU 타입을 적절히 선택하여 마이그레이션 호환성을 확보함.

1.4 CPU Pinning (affinity)

특정 vCPU를 특정 물리 코어에 고정하는 설정.

# VM 100의 vCPU 0을 물리 코어 2에, vCPU 1을 물리 코어 3에 고정
qm set 100 --affinity 2-3
 
# taskset으로 직접 확인
taskset -cp $(pgrep -f 'kvm.*-id 100')
Pinning장점단점
사용 안 함 (기본)CFS가 유연하게 스케줄링캐시 미스 가능성
사용캐시 지역성 향상, 예측 가능한 성능유연성 감소, 코어 고정으로 다른 VM 사용 불가

💡 NUMA 환경에서 CPU Pinning은 성능에 큰 영향을 미침. VM의 vCPU를 같은 NUMA 노드의 코어에 고정하면 메모리 접근 지연이 줄어듦.

1.5 CPU 오버커밋

물리 코어 수보다 더 많은 vCPU를 할당하는 것.

비율의미적합한 워크로드
1:1오버커밋 없음지연 민감한 DB, 실시간 처리
2:1물리 1코어당 vCPU 2개일반 웹 서버, 개발 환경
4:1물리 1코어당 vCPU 4개유휴 시간이 많은 경량 서비스
8:1+고밀도테스트 환경, VDI(idle 상태 많음)

⚠️ CPU 오버커밋은 “각 VM이 항상 100% CPU를 사용하지 않는다”는 가정에 기반함. 모든 VM이 동시에 CPU를 100% 사용하면 경합이 발생하여 모든 VM의 성능이 저하됨.


2. NUMA — Non-Uniform Memory Access

2.1 NUMA란

현대 멀티소켓 서버에서 각 CPU 소켓은 자체 메모리 컨트롤러와 로컬 메모리를 가짐. 자기 소켓에 연결된 메모리(로컬)에 접근하는 것이 다른 소켓의 메모리(리모트)에 접근하는 것보다 빠름.

flowchart LR
    subgraph Socket0["소켓 0 (NUMA Node 0)"]
        CPU0["CPU 코어 0-7"]
        MEM0["로컬 메모리<br/>64GB"]
    end

    subgraph Socket1["소켓 1 (NUMA Node 1)"]
        CPU1["CPU 코어 8-15"]
        MEM1["로컬 메모리<br/>64GB"]
    end

    CPU0 -->|"빠름<br/>(로컬)"| MEM0
    CPU1 -->|"빠름<br/>(로컬)"| MEM1
    CPU0 -->|"느림<br/>(리모트, QPI/UPI)"| MEM1
    CPU1 -->|"느림<br/>(리모트, QPI/UPI)"| MEM0
접근 유형지연 시간대역폭
로컬 메모리~80ns최대
리모트 메모리130ns+ (1.52배)인터커넥트에 의해 제한

2.2 Proxmox의 NUMA 지원

# VM에 NUMA 활성화
qm set 100 --numa 1
 
# NUMA 노드 수동 정의
qm set 100 --numa0 cpus=0-3,memory=4096
qm set 100 --numa1 cpus=4-7,memory=4096

NUMA를 활성화하면:

  • 게스트 OS가 NUMA 토폴로지를 인식함
  • 게스트 OS 자체의 NUMA 최적화가 동작함 (스케줄러, 메모리 할당)
  • CPU Pinning과 결합하면 최적의 성능을 얻을 수 있음

NUMA 모범 사례:

원칙설명
VM을 NUMA 노드 안에 맞추기VM의 vCPU와 메모리가 하나의 NUMA 노드에 들어가면 리모트 접근이 발생하지 않음
소켓 경계 넘기지 않기8코어/소켓 서버에서 VM에 12 vCPU를 주면 반드시 NUMA 경계를 넘음
대형 VM은 NUMA를 활성화다중 소켓 서버에서 대형 VM은 NUMA를 켜야 게스트 OS가 최적화 가능

💡 VMware의 NUMA 처리: ESXi는 NUMA 스케줄러가 자동으로 VM을 NUMA 노드에 배치하고 최적화함. Proxmox/KVM은 Linux CFS + 수동 Pinning/NUMA 설정으로 유사한 효과를 얻음. ESXi의 자동화 수준이 더 높은 편.


3. 메모리 관리

3.1 메모리 할당 모델

Proxmox에서 VM 메모리를 관리하는 주요 메커니즘:

flowchart TD
    subgraph Normal["정상 상태"]
        Static["정적 할당<br/>(고정 메모리)"]
        Balloon["Ballooning<br/>(동적 조절)"]
    end

    subgraph Pressure["메모리 부족 시"]
        KSM["KSM<br/>(Kernel Same-page Merging)"]
        Swap["스왑<br/>(최후의 수단)"]
    end

    Static --> Balloon -->|"부족"| KSM -->|"더 부족"| Swap

3.2 Memory Ballooning

Ballooning은 VM의 메모리를 동적으로 조절하는 기술임. Balloon Driver가 VM 내부에서 “빈 메모리를 점유”하여 호스트에 반환하거나, 반대로 메모리를 해제하여 VM에 돌려줌.

sequenceDiagram
    participant Host as 호스트 (Proxmox)
    participant Balloon as Balloon Driver (VM 내부)
    participant GuestOS as Guest OS

    Note over Host: 호스트 메모리 부족 감지
    Host ->> Balloon: "메모리 1GB 반환해줘" (inflate)
    Balloon ->> GuestOS: 1GB 메모리 점유 (사용 불가로 만듦)
    GuestOS ->> GuestOS: 사용 가능 메모리 감소
    Balloon ->> Host: 1GB 메모리 반환

    Note over Host: 호스트 메모리 여유 생김
    Host ->> Balloon: "메모리 돌려줄게" (deflate)
    Balloon ->> GuestOS: 점유한 메모리 해제
    GuestOS ->> GuestOS: 사용 가능 메모리 증가

Proxmox Ballooning 설정:

# 최소 2GB, 최대 8GB (Ballooning 활성화)
qm set 100 --memory 8192 --balloon 2048
 
# Ballooning 비활성화 (항상 고정 메모리)
qm set 100 --memory 8192 --balloon 0
설정의미
memoryVM에 할당되는 최대 메모리
balloon최소 보장 메모리. 이 아래로는 줄이지 않음
balloon=0Ballooning 비활성화 (메모리 고정)

⚠️ Ballooning이 동작하려면 VM 내부에 VirtIO Balloon Driver가 설치되어 있어야 함. Linux는 기본 내장, Windows는 VirtIO 드라이버 설치 필요.

3.3 KSM — Kernel Same-page Merging

KSM은 동일한 내용의 메모리 페이지를 여러 VM이 공유하도록 하는 Linux 커널 기능임.

flowchart LR
    subgraph Before["KSM 전"]
        VM1_Page["VM1: 페이지 A<br/>(0xABCD...)"]
        VM2_Page["VM2: 페이지 A<br/>(0xABCD... 동일)"]
        VM3_Page["VM3: 페이지 A<br/>(0xABCD... 동일)"]
    end

    subgraph After["KSM 후"]
        Shared["공유 페이지 A<br/>(0xABCD...)"]
        VM1_Ref["VM1 → 참조"]
        VM2_Ref["VM2 → 참조"]
        VM3_Ref["VM3 → 참조"]
        VM1_Ref --> Shared
        VM2_Ref --> Shared
        VM3_Ref --> Shared
    end

    Before -->|"KSM 스캔"| After
  • 동일한 OS를 실행하는 VM이 많을수록 효과가 큼 (커널 코드, 공유 라이브러리 등)
  • Copy-on-Write로 동작하므로 VM이 해당 페이지를 수정하면 자동으로 분리됨
  • CPU 오버헤드가 있음 (백그라운드 스캔)

💡 VMware의 TPS(Transparent Page Sharing)와 동일한 개념. 다만 VMware는 보안상의 이유로 기본적으로 같은 VM 내에서만 TPS를 적용하고, VM 간 공유는 비활성화함 (CVE-2014-0182).

3.4 Huge Pages

기본 페이지 크기(4KB) 대신 대형 페이지(2MB 또는 1GB) 를 사용하여 TLB 미스를 줄이고 메모리 접근 성능을 향상시키는 기술.

페이지 크기TLB 커버리지 (1024 엔트리 기준)용도
4KB4MB기본
2MB2GB대형 VM, 데이터베이스
1GB1TB매우 대형 VM, 고성능 워크로드
# Proxmox에서 Huge Pages 활성화
qm set 100 --hugepages 2  # 2MB 페이지
qm set 100 --hugepages 1024  # 1GB 페이지
 
# 호스트에서 Huge Pages 예약
echo 4096 > /proc/sys/vm/nr_hugepages  # 2MB × 4096 = 8GB 예약

⚠️ Huge Pages를 사용하면 해당 메모리는 호스트에서 예약되어 다른 용도로 사용 불가능함. Ballooning과 KSM도 동작하지 않음. 성능이 필요한 특정 VM에만 선택적으로 적용하는 것이 권장됨.

3.5 메모리 오버커밋

물리 메모리보다 더 많은 메모리를 VM에 할당하는 것.

전략방법위험도
BallooningVM이 사용하지 않는 메모리를 호스트에 반환낮음
KSM동일 페이지 공유로 실질적 사용량 감소낮음
Swap호스트 메모리 부족 시 디스크로 페이징⚠️ 높음
OOM Killer메모리 완전 부족 시 프로세스(VM) 강제 종료❌ 매우 높음

💡 VMware는 메모리 관리를 TPS → Ballooning → Compression → Swap 4단계로 수행함. Proxmox/KVM은 KSM → Ballooning → Swap → OOM Killer 순서. VMware의 Memory Compression(압축 후 메모리에 유지)에 해당하는 기능은 KVM에 없음.


4. 리소스 제어 — cgroups

4.1 cgroups v2

Proxmox는 cgroups v2를 사용하여 VM(QEMU 프로세스)과 LXC 컨테이너의 리소스를 제어함.

리소스제어 방식설명
CPUcpu.weight (shares)상대적 CPU 시간 비율
CPUcpu.max (quota/period)절대적 CPU 시간 제한
메모리memory.max최대 메모리 제한
메모리memory.high메모리 사용 감속 임계값
I/Oio.weight상대적 I/O 비율
I/Oio.max절대적 I/O 제한 (IOPS, BPS)

4.2 Proxmox의 리소스 제한 옵션

CPU 제한:

옵션설명예시
coresvCPU 수4
cpulimitCPU 사용량 상한 (코어 단위)2.0 = 2코어분까지
cpuunits상대적 CPU 가중치 (기본 1024)2048 = 기본의 2배
# VM 100: 4 vCPU지만 최대 2코어분만 사용 가능
qm set 100 --cores 4 --cpulimit 2
 
# VM 100: 다른 VM 대비 CPU 우선순위 2배
qm set 100 --cpuunits 2048

메모리 제한:

옵션설명
memory최대 할당 메모리 (MB)
balloon최소 보장 메모리 (MB)
sharesBallooning 시 상대적 우선순위 (기본 1000)

💡 VMware의 Reservation, Limit, Shares 모델과 대응:

  • Reservation ≈ balloon (최소 보장)
  • Limit ≈ memory (최대 허용)
  • Shares ≈ cpuunits / shares (상대적 우선순위)

5. KVM VM vs LXC — 워크로드 비교

5.1 아키텍처 차이

flowchart TB
    subgraph KVM_Side["KVM (하드웨어 가상화)"]
        VM_KVM["VM"]
        GuestKernel["Guest Kernel<br/>(독립 커널)"]
        QEMU_Proc["QEMU 프로세스"]
        KVM_Mod["KVM 모듈"]
        
        VM_KVM --> GuestKernel --> QEMU_Proc --> KVM_Mod
    end

    subgraph LXC_Side["LXC (OS 가상화)"]
        CT_LXC["Container"]
        NS["Namespaces<br/>(PID, NET, MNT, UTS, IPC, USER)"]
        CG["cgroups v2<br/>(리소스 제한)"]
        HostKernel["호스트 커널 공유"]
        
        CT_LXC --> NS --> CG --> HostKernel
    end

5.2 상세 비교

항목KVM VMLXC Container
가상화 수준하드웨어 (전체 머신 에뮬레이션)OS (커널 공유, 프로세스 격리)
커널독립 커널 (아무 OS 가능)호스트 커널 공유 (Linux만)
오버헤드중간 (VirtIO 시 낮음)매우 낮음 (네이티브에 가까움)
부팅 시간수십 초수 초
메모리 오버헤드100~300MB+ (게스트 커널, QEMU)수 MB (프로세스 자체만)
CPU 오버헤드낮음 (VT-x 가속)거의 없음
격리 수준높음 (하드웨어 분리)중간 (커널 공유 — 커널 취약점 시 위험)
지원 OS모든 OS (Windows, BSD 등)Linux만
디스크 I/OVirtIO 경유직접 파일시스템 접근
네트워크가상 NIC (tap + bridge)veth pair + bridge
스냅샷✅ (QEMU 수준)✅ (스토리지 수준)
라이브 마이그레이션제한적 (CRIU 기반, 실험적)
GPU Passthrough✅ (PCI Passthrough)제한적
Docker 실행✅ (nesting 활성화 필요)

5.3 LXC의 격리 메커니즘

LXC는 Linux 커널의 Namespacecgroups로 격리를 구현함.

Namespace격리 대상설명
PID프로세스 ID컨테이너 내부에서 PID 1부터 시작
NET네트워크독립 네트워크 스택, 인터페이스, IP
MNT마운트 포인트독립 파일시스템 뷰
UTS호스트명독립 호스트명, 도메인명
IPCIPC 리소스독립 세마포어, 메시지 큐
USER사용자 IDUID/GID 매핑 (Unprivileged CT)
cgroupcgroup 뷰자체 cgroup 트리

5.4 Privileged vs Unprivileged LXC

유형UID 매핑보안성능권장
Unprivileged컨테이너 root = 호스트 UID 100000+✅ 안전약간의 오버헤드✅ 기본
Privileged컨테이너 root = 호스트 root (UID 0)⚠️ 위험약간 더 빠름NFS, 특수 장치

💡 Unprivileged 컨테이너가 강력히 권장됨. 컨테이너 내부에서 root 탈출(escape)이 발생해도 호스트에서는 비권한 사용자이므로 피해가 제한됨.

5.5 워크로드별 선택 기준

워크로드추천이유
Windows 서버KVMLXC는 Linux만 지원
데이터베이스 (MySQL, PostgreSQL)KVM커널 수준 튜닝, 격리 필요
웹 서버 (Nginx, Apache)LXC경량, 빠른 프로비저닝
DNS/NTP/SyslogLXC인프라 서비스, 리소스 최소
모니터링 (Prometheus, Grafana)LXC경량 서비스
CI/CD RunnerLXC 또는 KVMDocker 필요 시 nesting 활성화
Kubernetes 워커KVM커널 모듈 필요, 격리 중요
개발/테스트 환경LXC빠른 생성/삭제, 리소스 절약
보안 민감 워크로드KVM하드웨어 수준 격리

6. VMware와의 Compute 비교

항목Proxmox (KVM)VMware (ESXi)
CPU 스케줄러Linux CFSVMkernel CPU Scheduler
NUMA 자동 최적화수동 (Pinning + NUMA 옵션)자동 (NUMA Scheduler)
CPU 오버커밋지원 (CFS 시분할)지원 (Ready, Co-Stop 메트릭)
메모리 관리Ballooning, KSM, SwapTPS, Ballooning, Compression, Swap
Memory Compression❌ 없음✅ (Swap 전 단계)
리소스 예약balloon(최소), cpuunits(가중치)Reservation, Limit, Shares
DRS (자동 밸런싱)❌ 없음✅ (vMotion 기반 자동 재배치)
Resource PoolPool (기본)Resource Pool (계층 구조)
컨테이너✅ LXC 내장❌ (Tanzu는 별도)
Hot Add CPU
Hot Add Memory

💡 VMware의 가장 큰 차별점은 DRS(자동 부하 분산)NUMA 자동 최적화임. Proxmox에서는 이를 수동 설정이나 외부 스크립트로 보완해야 함. 반면 LXC라는 경량 컨테이너 옵션은 Proxmox만의 강점임.


정리

Proxmox의 컴퓨트 리소스 관리는 Linux 커널의 기능을 그대로 활용하는 구조임.

  • CPU: Linux CFS가 vCPU 스레드를 스케줄링. CPU 타입, Pinning, NUMA 설정으로 최적화
  • 메모리: Ballooning으로 동적 조절, KSM으로 페이지 공유, Huge Pages로 TLB 최적화
  • KVM VM: 하드웨어 가상화로 모든 OS 지원, 강한 격리, 약간의 오버헤드
  • LXC: OS 가상화로 Linux만 지원, 매우 낮은 오버헤드, 경량 서비스에 적합
  • 리소스 제어: cgroups v2 기반으로 CPU, 메모리, I/O를 세밀하게 제한

다음 글

#5 Network Configuration — Linux Bridge, VLAN, Bonding, SDN 아키텍처


🔗 관련 문서


📝 참고 자료