BESTNET-CLOUD
GPU-VPS
GPUStack
10G Private Network
NFS Shared Cache
기술 블로그 / 인프라 구축 가이드
Bestnet Cloud × GPU-VPS를 10G 프라이빗 네트워크로 연결하여
GPUStack 클러스터를 구현하는 절차 #
베스트넷 클라우드를 컨트롤 플레인으로, GPU-VPS를 추론 워커로 분리하고,
공유 NFS 캐시로 모델 파일을 일원화하는 구성입니다.
클라이언트 포털 측 준비부터
Ubuntu 상의 구현, 운영 확인까지를 사용 방법 문서로 정리했습니다.
Private Link
모델 다운로드
GPU Worker
공유 모델 보관처
이 문서에서 다루는 범위 #
본 문서는 Bestnet Cloud 상에 AI-SRV를 구축하여 GPUStack Server + NFS를 집약하고,
GPU-VPS 측에 여러 GPU 워커를 배치하는 초기 구축 패턴을 다룹니다.
역할 분리와 공유 캐시 설계가 주제이므로, 공개용으로 실제 IP나 내부 명명 규칙은 예시 값으로 치환했습니다.
설계의 핵심은 GPU가 필요 없는 컨트롤 플레인과 모델 보관처를 범용 클라우드 측으로 옮기고,
GPU-VPS는 오로지 추론 실행용 노드로 한정하는 것입니다.
이렇게 해두면 워커를 늘려도 스토리지의 중복 투자를 피하기 쉽고,
모델의 실체는 Bestnet Cloud 측 공유 영역에서만 관리할 수 있습니다.
모델 등록은 GUI에서만
AI-SRV에 GPUStack Server + NFS를 통합
모든 worker는 NFS 마운트 포인트 /models를 공유
여기에서는 0.6.x 계열의 구축 패턴을 알기 쉽게 정리합니다.
Bestnet Cloud 지식을 실제 구축 순서로 재구성하기 #
Bestnet Cloud의 지식 문서에서는 클라이언트 포털의 운영 작업이 세밀하게 나뉘어 있습니다.
따라서 GPU 클러스터 구축에서는 “어느 시점에 어떤 지식 문서를 사용할지”를 먼저 정해두면 작업 재시도를 줄일 수 있습니다.
본 문서에서는 포털 측 준비를 다음 순서로 정리했습니다.
포털 보호
MFA·허용 IP 개념을 먼저 확립
SSH 키 등록
OS 배포 전에 관리 키 정비
템플릿 생성
AI-SRV와 GPU-VPS를 Ubuntu 24로 준비
Private Network
10G 세그먼트에 모든 노드 연결
Firewall / NAT
공개 범위와 통신 방향 제한
Snapshot
초기 상태로 복원 가능한 지점 보존
아키텍처의 사고방식 #
역할은 심플합니다. Bestnet Cloud 쪽의 AI-SRV가 Web UI / API / NFS 공유를 담당하고,
GPU-VPS 쪽의 노드는 GPUStack Worker와 추론 실행만 집중합니다.
10G 프라이빗 네트워크를 사용해 내부 통신을 폐쇄함으로써,
모델 배포·NFS·클러스터 접속을 모두 private side로 몰아넣을 수 있습니다.
BESTNET-CLOUD
control-01 #
GPUStack Server + NFS를 통합한 AI-SRV
- Web UI / API 제공
/srv/gpustack_models를 NFS export- 로컬에서는
/models에 bind mount - 모델 실체를 한 곳으로 집약
NFS / UI / Worker Join / 내부 통신
GPU-VPS
gpu-worker-01 / 02 #
/models를 공유 마운트하고, 추론만 담당하는 worker 그룹
- GPUStack Worker 기동
--cache-dir /models를 통일- 각 worker에 대용량 모델 보관 영역을 가지지 않음
- 수평 확장 시에는 같은 패턴으로 대수 추가
→
최초의 worker가 모델을 1회만 취득
→
다른 worker는 같은
/models에서 읽어오기만
사전에 결정해둘 항목 #
| 역할 | 배치처 | 호스트명(예) | Private IP(예) | 주요 책무 |
|---|---|---|---|---|
| Server + NFS | Bestnet Cloud | control-01 | 10.10.0.10 | GPUStack UI / API, NFS, 모델 보관처 |
| GPU Worker #1 | GPU-VPS | gpu-worker-01 | 10.10.0.21 | 추론 실행, 공유 /models 사용 |
| GPU Worker #2 | GPU-VPS | gpu-worker-02 | 10.10.0.22 | 추론 실행, 공유 /models 사용 |
공개용 예시입니다. 실제 환경에서는 자사의 naming rule과 private subnet에 맞춰 주십시오.
클라이언트 포털 측 준비를 먼저 확정한다 #
클라이언트 포털 자체의 방어를 정비한다 #
서버 생성보다 먼저 관리면의 방어 방침을 결정합니다. 특히 팀 운용에서는
MFA와 허용 IP 처리를 먼저 정리해 두면 나중에 “누가 어디서 관리면에 들어갈 수 있는가”로 고민하지 않습니다.
SSH 키를 등록한 후 서버를 만든다 #
AI-SRV와 GPU 워커를 생성한 후 개별적으로 키를 삽입하는 것보다, 클라이언트 포털의 SSH 키 관리에서
먼저 키를 정비해 두는 것이 템플릿 배포 후 바로 관리에 들어갈 수 있습니다.
- 운용 팀용 공개키를 정리한다
- 긴급 시 공유키와 개인키를 혼재시키지 않는다
- 기사 공개 시 키 fingerprint도 게재하지 않는다
Bestnet Cloud 상에 AI-SRV를 템플릿에서 생성한다 #
AI-SRV에는 Ubuntu 24 계열 템플릿을 사용하며, GPUStack Server와 NFS 모두를 탑재합니다.
이 노드는 모델 보관처도 겸하므로, OS 디스크와 별도로 충분한 저장 영역을 확보하는 설계가 적합합니다.
- 역할은 GPUStack Server + NFS
- private network에 연결한다
- UI 공개가 필요한 경우에만 public 측을 검토한다
- 모델 저장처의 용량은 worker보다 AI-SRV 측을 두껍게 한다
GPU-VPS 측에 worker를 필요 대수만큼 생성한다 #
worker는 추론용이므로, GPU 종류·VRAM·향후 모델 크기를 기준으로 GPU-VPS의 플랜을 선택합니다.
한편, 모델 본체는 NFS 측에 배치하므로, worker의 스토리지는 OS와 실행에 필요한 최소한으로 줄이기 쉽습니다.
- Ubuntu 24 계열로 통일한다
- GPU driver / CUDA를 사용할 수 있는 전제로 생성한다
- private network에 연결한다
- 필요 없으면 public IP를 부여하지 않는 구성도 검토한다
10G 프라이빗 네트워크에 전체 노드를 탑재한다 #
NFS와 GPUStack의 내부 통신은 Bestnet Cloud와 GPU-VPS를 연결하는 10G private link 상에서 흐릅니다.
이를 통해 모델 읽기나 worker join을 public 측으로 내보내지 않아도 됩니다.
- AI-SRV와 전체 worker를 동일 private segment에 수용한다
- 고정 IP를 할당하여 후속 NFS export와 systemd 설정을 안정화한다
- worker에 외부 통신이 필요하면 NAT 라우터 방식 또는 임시 public egress를 선택한다
worker를 private-only로 배치하고 싶은 경우, Bestnet Cloud의 가상 라우터 / NAT 패턴을 사용하여
OS 업데이트나 외부 획득만 밖으로 내보내는 설계가 다루기 쉽습니다.
방화벽의 초기 규칙을 결정한다 #
규칙은 “AI-SRV에 필요한 inbound를 최소한만 허용하고, worker는 SSH 이외의 inbound를 거의 부여하지 않는다”는 방침으로 충분합니다.
포털의 방화벽 화면에서 먼저 기존 규칙을 확인한 후, 필요한 포트만 추가합니다.
| 대상 | 포트 / 프로토콜 | 송신원 고려사항 | 용도 |
|---|---|---|---|
| AI-SRV | 22/tcp | 관리 원본 IP만 제한 | SSH |
| AI-SRV | 80/tcp | 관리 네트워크 or private side | GPUStack Web UI / API |
| AI-SRV | 2049/tcp | private subnet만 | NFS v4 |
| AI-SRV | 111/tcp,111/udp | 필요 시에만 private subnet | rpcbind를 사용하는 구성용 |
| GPU Worker | 22/tcp | 관리 원본 IP만 제한 | SSH |
NFS v4 전제라면 2049/tcp에 집중하기 쉬운 반면, 환경에 따라 rpcbind를 사용하는 경우가 있습니다. 공개 범위는 반드시 private subnet으로 제한합니다.
첫 스냅샷을 취득한다 #
OS 초기 생성, 키 투입, private network 연결, 방화벽 정비가 끝나면,
일단 AI-SRV와 GPU worker의 스냅샷을 취득해 두면, 이후 미들웨어 도입에서 실패해도 복구하기 쉬워집니다.
OS 측 베이스라인 만들기 #
서버와 worker 모두에서, 먼저 시각 동기화와 NFS 기반을 맞춥니다. GPU 워커는 이후에 GPU driver / CUDA를 설치하므로,
먼저 OS 업데이트와 재시작 포인트를 완료해 두면 안정적입니다.
# 전체 노드
sudo apt update
sudo apt install -y nfs-common
# NFS 서버용 (AI-SRV만)
sudo apt install -y nfs-kernel-server
AI-SRV에 GPUStack Server + NFS 구축하기 #
GPUStack Server 설치하기 #
초기 구축 예시에서는 AI-SRV에 GPUStack Server를 도입하여 관리 UI에 로그인할 수 있는 상태를 만듭니다.
초기 관리자 비밀번호는 기록한 후 안전한 vault로 이동하며, 기사에는 게재하지 않습니다.
curl -sfL https://get.gpustack.ai | sh -s -
cat /var/lib/gpustack/initial_admin_password
# Web UI (예시)
# http://10.10.0.10/NFS 공유 디렉터리 만들기 #
모델 파일의 실체는 /srv/gpustack_models에 둡니다.
이를 private subnet에만 export하고, AI-SRV 자체에서도 /models로 bind mount합니다.
이렇게 해두면, 서버에서 보이는 경로와 worker에서 보이는 경로가 통일됩니다.
sudo mkdir -p /srv/gpustack_models
echo "/srv/gpustack_models 10.10.0.0/24(rw,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports
sudo exportfs -ra
# Server 자체도 bind mount
sudo mkdir -p /models
sudo mount --bind /srv/gpustack_models /models
echo "/srv/gpustack_models /models none bind 0 0" | sudo tee -a /etc/fstabworker 참가 토큰 발급하기 #
GPUStack의 GUI에서 worker join token을 생성합니다. 공개 문서에서는 <WORKER_JOIN_TOKEN>으로 표기하며,
실제 값은 게재하지 않습니다. 또한 GUI에 로그인할 수 있는 관리 주체도 private network 쪽으로 맞추는 운영이 더 안전합니다.
GPU-VPS 측에 공유 cache를 마운트하여 worker를 참가시키기 #
먼저 /models를 NFS 마운트하기 #
각 worker는 AI-SRV가 export하고 있는 공유 영역을 동일한 경로 /models로 마운트합니다.
이 시점에서 모든 worker의 cache path가 통일되므로 모델의 중복 저장을 방지할 수 있습니다.
sudo mkdir -p /models
echo "10.10.0.10:/srv/gpustack_models /models nfs defaults 0 0" | sudo tee -a /etc/fstab
sudo mount -a마운트 후에는 mount | grep /models로 의도한 공유 대상이 보이는지 확인합니다.
GPUStack Worker 설치하기 #
AI-SRV 측에서 발급한 token을 사용하여 각 GPU-VPS를 worker로 클러스터에 참가시킵니다.
curl -sfL https://get.gpustack.ai | sh -s - --server-url http://10.10.0.10 --token <WORKER_JOIN_TOKEN>worker 서비스에서 --cache-dir /models 고정하기 #
공유 cache 구성에서는 이 지정이 가장 중요합니다. GPUStack Worker의 systemd 정의에--cache-dir /models를 추가하고, data-dir도 함께 고정해 둡니다.
[Service]
ExecStart=/root/.local/bin/gpustack start --server-url http://10.10.0.10 --token <WORKER_JOIN_TOKEN> --cache-dir /models --data-dir /var/lib/gpustack-datasudo systemctl daemon-reload
sudo systemctl enable --now gpustack
# Using cache dir: /models 가 출력되면 OK
journalctl -u gpustack -fGPUStack GUI에서 worker가 Ready 상태가 되는지 확인 #
GUI의 Workers 화면에서 모든 GPU-VPS가 Ready 상태가 되는지 확인합니다.
여기서 Not Ready 상태로 남아 있다면, GPU driver / CUDA, NFS 마운트, worker 로그 순으로 확인하면 빠릅니다.
모델 배포 및 동작 확인 #
구축 완료 판단은 단순히 worker가 Ready 상태가 되는 것만이 아닙니다.
실제로 GUI에서 모델을 2 replicas 이상으로 deploy하고, 첫 번째 1대만 다운로드하며,
2대째 이후는 동일한 공유 파일을 재사용하는 것까지 확인하여 완료로 간주합니다.
이 구성에서 효과적인 비용 최적화 #
GPU-VPS마다 모델을 전체 보유하지 않으므로, GPU 노드의 스토리지를 얇게 설계하기 쉬워집니다.
큰 모델일수록 공유 NFS 캐시 방식의 효과가 명확하게 나타납니다.
운용 시 핵심 포인트 #
모니터링 및 문제 해결 #
Q. replicas를 늘리면 재다운로드하나요?
기본적으로 하지 않습니다. 공유 /models에 파일이 존재하면 worker는 이를 재사용합니다.
Q. worker는 public IP가 필수인가요?
필수가 아닙니다. 외부 통신 방식을 NAT 방식으로 맞춘다면 private-only로 운영하는 선택도 있습니다.
Q. 어디를 강화하면 비용 효율이 좋아지나요?
각 GPU worker의 스토리지가 아니라 공유 모델 저장소를 갖는 AI-SRV 측입니다. 모델을 한 곳에서 관리할 수 있기 때문입니다.
Bestnet Cloud를 제어계, GPU-VPS를 실행계로 분리하면 GPU 클러스터는 다루기 쉬워진다 #
AI-SRV에 GPUStack Server와 NFS를 통합하고, GPU-VPS 그룹은 worker로서 private network에 연결합니다.
그 위에서 /models를 공유 캐시로 만들면 스토리지 중복을 피하면서 GPU 클러스터를 자연스럽게 확장할 수 있습니다.
포털 측에서는 SSH 키, 템플릿 배포, private network, 방화벽, 스냅샷 순서로 정비하고,
OS 측에서는 NFS와 GPUStack의 경로를 통일합니다. 이것만으로도 실운영하기 쉬운 구성이 됩니다.
BESTNET-CLOUD × GPU-VPS
NFS Shared Cache
모델은 1회만 취득