[Proxmox 시리즈 6편] 표준 LXC 구성과 경계 정하기

English version

Windows VM 템플릿을 정리했다면 이제 가벼운 서비스를 담당할 LXC 컨테이너 표준을 잡을 차례입니다. LXC는 호스트와 같은 리눅스 커널을 공유하므로 빠르고 가볍지만, 권한 모델과 스토리지 경계를 제대로 이해하지 않으면 호스트 전체를 위험에 빠뜨릴 수 있습니다. 특히 Nesting, Privileged 플래그, bind-mount를 아무 생각 없이 켜는 습관은 컨테이너 격리를 무력화시키거나 백업을 어렵게 만듭니다.

이 글에서는 Proxmox에서 LXC를 만들 때 기본으로 확인해야 할 항목을 정리합니다. 템플릿 선택, 비권한(unprivileged) 컨테이너로 시작하는 이유, 메모리·디스크 기본값과 cgroup 제한, bind mount와 device pass-through 기준, Nesting이 필요한 상황과 부작용, 그리고 LXC로 하지 말아야 할 워크로드까지 살펴보겠습니다. 각 섹션마다 실무에서 반복적으로 쓰는 pct 명령과 설정 예시를 덧붙였습니다.

이 글의 흐름

  1. 왜 LXC 표준이 필요한가
  2. 템플릿 선택과 초기 패키지 구성
  3. 비권한 컨테이너 기본 설정
  4. 자원 배분과 스토리지 계획
  5. Nesting, bind mount, device passthrough 사용 기준
  6. LXC로 적합하지 않은 워크로드와 경계

이번 글에서 새로 나오는 용어

  1. Unprivileged Container: 컨테이너 내부 UID/GID를 매핑해 root 권한을 직접 호스트에 노출하지 않는 방식입니다.
  2. Bind Mount: 호스트 디렉터리를 컨테이너 파일시스템에 연결하는 방식으로, 파일 권한을 주의 깊게 다뤄야 합니다.
  3. Nesting: 컨테이너 안에서 다시 컨테이너나 systemd를 돌리는 기능으로, 보안을 희생하는 대신 편의를 얻습니다.
  4. cgroup 제한: CPU, 메모리, I/O를 제한하는 컨트롤 그룹 설정으로 LXC 자원 경계를 정의합니다.
  5. idmap: Proxmox가 컨테이너 UID/GID를 호스트 UID/GID로 매핑하는 테이블입니다.

읽기 카드

  • 예상 소요 시간: 15분
  • 사전 준비: Proxmox VE 8.x, LXC 템플릿 저장소 동기화, 기본 ZFS 또는 LVM 스토리지, 물리 스위치 VLAN 지원 여부 파악
  • 읽고 나면: LXC 표준 템플릿을 만들고 Nesting·bind mount를 언제 사용할지 결정하며 백업/보안 체크리스트를 적용할 수 있습니다.

왜 LXC 표준이 필요한가

LXC는 VM보다 생성이 빠르고 자원 소모가 적습니다. 하지만 권한 경계를 직접 조정해야 하므로, 한번 잘못 설정하면 Proxmox 호스트 전체가 영향을 받을 수 있습니다. 표준을 정하지 않으면 컨테이너마다 권한, 스토리지, 네트워크 구성이 제각각이 되어 백업과 복구, 감사가 어려워집니다.

목표

  1. 모든 컨테이너는 기본적으로 비권한 상태로 운영한다.
  2. 템플릿과 패키지 버전은 최소한 분기별로 갱신해 보안 패치를 놓치지 않는다.
  3. 자원 제한(cgroup)을 명시해 과도한 오버커밋을 피한다.

템플릿 선택과 초기 패키지 구성

Proxmox는 pveam updateTemplates 탭에서 공식 이미지를 내려받을 수 있습니다. 표준화하려면 다음을 권장합니다.

  • 배포판: Debian 또는 Ubuntu LTS. Rolling 배포판은 장기 운영 시 문제를 키웁니다.
  • 버전 관리: 템플릿 이름에 연도/월을 적어 언제 받은 이미지인지 메모합니다.
  • 초기 패키지: curl, git, htop, qemu-guest-agent(컨테이너용), chrony 정도를 기본 설치하면 운영 편의성이 높아집니다. SSH 기본 포트, 관리자 계정 정책 등도 템플릿에서 통일합니다.

컨테이너를 생성한 뒤 pct template 또는 pct create+pct clone을 이용해 동일 구성을 템플릿으로 저장해 두면 반복 생성이 쉬워집니다. 템플릿 이름에 배포판·버전·패치 레벨을 포함시키고, Git/Ansible로 초기 패키지 변경 기록을 남기면 Drift를 줄일 수 있습니다.

# 예시: 2025년 2월 Debian 표준 템플릿 구축
pveam download local debian-12-standard_12.2-1_amd64.tar.zst
pct create 120 local:vztmpl/debian-12-standard_12.2-1_amd64.tar.zst \
  -unprivileged 1 -cores 2 -memory 512 -swap 0 \
  -net0 name=eth0,bridge=vmbr1,firewall=1
pct exec 120 -- apt-get update && apt-get install -y curl git htop chrony qemu-guest-agent
pct template 120

비권한 컨테이너 기본 설정

pct createunprivileged=1을 기본으로 두고, 정말 필요한 경우(특정 커널 기능이 필요하거나, 디바이스를 곧바로 넘겨야 하는 경우)에만 privileged를 허용합니다. 비권한 컨테이너는 다음 이점을 줍니다.

  1. 컨테이너 root가 호스트 root와 분리되어 권한 상승 위험이 줄어든다.
  2. 백업 시 ACL/권한 충돌이 덜 발생한다.
  3. Proxmox가 자동으로 UID/GID 매핑을 관리하므로 사용자 추가가 단순해진다.

다만 bind mount가 필요한 경우 mp0, mp1 설정에서 uidmap을 적절히 지정하지 않으면 쓰기 권한 문제가 발생합니다. Proxmox 8에서는 mp0=/tank/logs,mp=/var/log/app,uid=1000,gid=1000,backup=1처럼 UID/GID를 명시할 수 있습니다.

주의: bind mount 경로는 vzdump 백업에서 기본적으로 제외됩니다. backup=1 옵션을 쓰더라도 원본 데이터는 host 경로에 남아 있으므로, 해당 dataset에 대한 스냅샷·백업 전략을 별도로 세워야 합니다.

자원 배분과 스토리지 계획

컨테이너는 "가볍다"는 인식 때문에 자원 제한 없이 방치되기 쉽습니다. 표준을 세울 때는 다음 규칙을 추천합니다.

  • 메모리: 최소 256MB, 기본 서비스는 512MB~1GB. swap은 물리 메모리가 충분하지 않다면 0으로 두고, 대신 호스트 레벨에서 zram swap을 고려합니다.
  • CPU 제한: cores=1 또는 2로 시작하고 cpulimit/cpuunits를 지정해 과도한 CPU 점유를 막습니다. 특정 워크로드는 cpuset으로 NUMA 노드에 핀해 캐시 간섭을 줄입니다.
  • 디스크: 8GB 이상을 기본으로 두고, 로그가 많은 서비스는 별도의 bind mount나 추가 디스크를 연결합니다. Directory 기반 rootfs는 빠르지만 ZFS/LVM 같은 블록 storage가 스냅샷과 백업에 유리합니다.
  • 스토리지 유형: ZFS를 쓴다면 compression=lz4, atime=off를 기본으로 하고, LVM-thin이라면 스냅샷 여유 공간과 thin pool 사용률을 모니터링합니다.

Nesting, bind mount, device passthrough 기준

Nesting

  • 사용 시점: 컨테이너 안에서 Docker, LXD, systemd-nspawn 같은 2차 컨테이너 런타임을 돌려야 할 때.
  • 위험: 컨테이너 격리가 약해지고, Docker가 요구하는 cgroup 기능을 호스트와 그대로 공유합니다. 커널/보안 업데이트 영향 범위가 커지고, 커널 취약점 악용 시 호스트까지 침해될 수 있습니다.
  • 대안: 가능하면 해당 워크로드를 KVM VM으로 올리거나, 단일 프로세스 실행 수준이라면 Nesting 없이 직접 운영합니다.

Bind Mount

  • 사용 시점: 로그, 데이터 디렉터리를 호스트의 별도 ZFS dataset이나 NAS 마운트와 연결할 때.
  • 주의 사항: mp0=/tank/data,mp=/data,uid=1000,gid=1000,backup=1처럼 권한과 백업 여부를 명시합니다. 호스트 dataset을 삭제하거나 권한을 바꾸면 LXC 안에서도 즉시 반영되므로, 변경 절차와 접근 통제를 문서화해야 합니다.

Device Passthrough

  • 사용 시점: USB 지그비 동글, 시리얼 디바이스 등 특정 하드웨어를 컨테이너가 직접 써야 할 때.
  • 주의 사항: /dev/ttyUSB0를 그대로 넘기기보다 usbX 옵션을 사용해 hotplug를 안정화하고, 가능한 한 해당 서비스만 담당하는 컨테이너를 별도로 두어 장애 범위를 줄입니다. Privileged 모드로 전환해야 한다면 방화벽 규칙과 AppArmor 정책을 재검토합니다.

LXC로 적합하지 않은 워크로드와 경계

다음과 같은 경우에는 VM을 사용하는 편이 낫습니다.

  1. 커널 모듈 의존: ZFS, WireGuard, FUSE 같은 모듈을 직접 올려야 한다면 LXC보다 VM이 안전합니다. 컨테이너에서 커널을 건드리면 호스트 전체가 영향을 받을 수 있습니다.
  2. 중요 데이터베이스: PostgreSQL, MySQL 메인 인스턴스는 파일 권한과 I/O 일관성 때문에 VM(또는 물리 서버)으로 운영하는 것이 복구가 쉽습니다. UID/GID 매핑 오류가 발생하면 데이터 복구가 어렵고, 스냅샷도 불안정합니다.
  3. 강한 멀티테넌시/제로 트러스트: 여러 팀·고객이 나눠 쓰는 환경에서는 컨테이너 권한 모델보다 VM 격리(필요시 물리 분리)가 확실합니다.
  4. 중첩 가상화: KVM/Hyper-V를 다시 돌려야 한다면 VM 안에서 실행해야 합니다. LXC는 Nested-V를 지원하지 않습니다.

즉, LXC는 네트워크 유틸리티, 프록시, 경량 애플리케이션 서버, 모니터링, 인증 프록시처럼 상태가 단순하고 커널 의존이 낮은 워크로드에 적합합니다. 이때도 PVE Firewall/OPNsense 뒤에 배치하고, 자원 제한과 백업 정책을 동일하게 적용해야 합니다.

마무리

LXC는 "가볍다"는 장점 때문에 무심코 쓰기 쉽지만, 표준 템플릿과 권한·자원 규칙을 정해 두어야만 Proxmox 전체 운영 모델이 깔끔해집니다. 이번 글에서 정리한 기본값을 템플릿으로 저장하고, 컨테이너마다 동일한 체크리스트를 적용해 보세요. 다음 글에서는 LXC와 VM을 모두 수용할 네트워크 설계—기본 브리지부터 사설망, OPNsense, VPN 기반 원격 접속까지—를 살펴보겠습니다.

💬 댓글

이 글에 대한 의견을 남겨주세요