26S06a

QK·약 8시간 전

인터넷이 차단된 에어갭 환경에서 GPU(B300) 노드 검증, vLLM 서빙, 스토리지 연동, 성능 벤치마크를 차질 없이 완결할 수 있도록 외부망(MacBook)에서 사전 다운로드해야 하는 전체 에셋 리스트를 정리했습니다.

사내 Nexus 프록시가 있더라도 방화벽 타임아웃, 토큰 인증 제한, 레지스트리 캐시 미스(Cache Miss)에 대비한 백업용 컨테이너 이미지 아카이브옵셔널(비상용/선택) 항목까지 모두 포함했습니다.


1. 필수(Mandatory) 다운로드 목록

이 항목들이 없으면 노드 부팅 후 드라이버 인식, NVLink 활성화, 모델 서빙 자체가 불가능합니다.

① NVIDIA 호스트 드라이버 & NVSwitch 스택 (RHEL 10.2 x86_64)

  • NVIDIA Data Center Driver .run 파일:
  • 파일: NVIDIA-Linux-x86_64-<VERSION>.run (예: R570/R580 Production Branch)
  • 용도: B300 GPU 오픈 커널 모듈(--kernel-module-type=open) 및 기본 CUDA 드라이버 설치.
  • nvidia-fabricmanager RPM:
  • 파일: nvidia-fabricmanager-<VERSION>-1.x86_64.rpm
  • 중요: 위 .run 파일과 빌드 마이너 버전 번호가 100% 일치해야 함 (B300 NVLink/NVSwitch 구동 필수).
  • NVIDIA Container Toolkit RPM 세트:
  • nvidia-container-toolkit-*.x86_64.rpm
  • nvidia-container-toolkit-base-*.x86_64.rpm
  • libnvidia-container1-*.x86_64.rpm
  • libnvidia-container-tools-*.x86_64.rpm
  • 용도: Podman/K8s에서 CDI(Container Device Interface)로 GPU 패스스루.

② LLM 모델 가중치 및 설정 파일 (Llama-3.1-70B-Instruct 기준)

Hugging Face CLI의 snapshot_download를 이용해 온전히 수집해야 합니다 (약 140GB).

  • 설정 및 아키텍처 파일: config.json, generation_config.json
  • 토크나이저 에셋 (누락 시 vLLM 기동 불가):
  • tokenizer.json, tokenizer_config.json, special_tokens_map.json
  • 샤딩된 가중치 파일:
  • model.safetensors.index.json (샤드 매핑 인덱스)
  • model-00001-of-00030.safetensors ~ model-00030-of-00030.safetensors (총 30개 파티션)

③ Standalone 인프라/스토리지 바이너리 (Linux x86_64)

  • MinIO Client (mc): Linux amd64 정적 바이너리 (AIStor 버킷 생성, 모델 업로드/다운로드용).
  • k6 또는 locust 바이너리: Linux amd64 실행 바이너리 (Compute 클러스터 \rightarrow GPU 부하 생성용).

2. 컨테이너 이미지 아카이브 (.tar.gz) (Nexus 프록시 장애 대비 백업)

Nexus Proxy를 통해 pull이 가능하더라도, 대용량 이미지 풀 도중 네트워크 단절이나 에어갭 인증 실패에 대비해 MacBook에서 docker pull --platform linux/amd64docker save | gzip으로 백업해 둘 이미지들입니다.

컨테이너 이미지 (Tag)용도 및 단계비고
vllm/vllm-openai:latestPhase 3 추론 서빙 및 Phase 5 벤치마크필수
wilic/gpu-burn:latestPhase 2 전체 GPU 100% 풀로드 번인 테스트필수
nvcr.io/nvidia/k8s/cuda-sample:vectorAdd-cuda12.5.0Phase 2 NVLink P2P 대역폭 실측 (p2pBandwidthLatencyTest)필수
grafana/k6:latestPhase 5 K8s Pod 기반 분산 부하 인가기필수
prom/prometheus:latestK8s 조인 전 단독 모니터링 (9090 포트)권장
grafana/grafana:latestK8s 조인 전 실시간 시각화 대시보드 (3000 포트)권장
nvidia/k8s-device-plugin/dcgm-exporter:latestGPU 전력, 온도, SM 사용률 메트릭 노출권장
networkstatic/iperf3:latestPhase 4 스토리지 대역폭 실측용 컨테이너옵션

3. 옵셔널(선택/비상용) 다운로드 목록

현장에서 네트워크 파라미터 튜닝이나 예기치 못한 컴파일, 디스크 성능 병목 진단 시 유용한 항목들입니다.

① 진단 및 벤치마크 툴

  • MinIO Warp (warp): Linux x86_64 바이너리 (AIStor의 순수 S3 GET/PUT 처리량 멀티파트 한계 측정 시 필요).
  • ShareGPT 실데이터셋: ShareGPT_V3_unfiltered_cleaned_split.json (vLLM 내장 벤치마크 benchmark_serving.py 구동 시 실제 유저 트래픽 모사용).
  • NVIDIA DCGM RPM: datacenter-gpu-manager-*.x86_64.rpm (호스트 OS 레벨에서 dcgmi diag -r 3 진단 시 필요).

② RHEL 10.2 보조 OS RPM (사내 OS 미러에 없을 경우 대비)

  • stress-ng 및 하위 라이브러리 RPM: Phase 1 CPU/메모리 부하 검증용 (EPEL 저장소 패키지).
  • kernel-devel, kernel-headers (현재 커널 버전용): 드라이버 오픈 커널 모듈 빌드 시 필요.
  • fio, iperf3, numactl, pciutils RPM: 베어메탈 OS 점검 도구.

③ 경량 기능 테스트용 소형 LLM (단일 GPU 연동 검증용)

  • meta-llama/Llama-3.1-8B-Instruct (약 16GB): 70B를 올리기 전 파이프라인(외부망 L3 통신, K8s Egress 등) 빠른 검증용.

4. 맥북에서 바로 실행하는 다운로드 커맨드 시트

맥북 터미널에서 실행하여 한 폴더로 정리하는 명령입니다.

# 1. 수집 디렉터리 준비
mkdir -p ~/airgap_bundle/{binaries,datasets,images}

# 2. Standalone 바이너리 다운로드 (Linux x86_64 전용)
curl -sSL https://dl.min.io/client/mc/release/linux-amd64/mc -o ~/airgap_bundle/binaries/mc
chmod +x ~/airgap_bundle/binaries/mc

# k6 바이너리
curl -sSL https://github.com/grafana/k6/releases/download/v0.53.0/k6-v0.53.0-linux-amd64.tar.gz -o /tmp/k6.tar.gz
tar -xzf /tmp/k6.tar.gz -C /tmp && mv /tmp/k6-*-linux-amd64/k6 ~/airgap_bundle/binaries/ && rm -rf /tmp/k6*
chmod +x ~/airgap_bundle/binaries/k6

# 3. ShareGPT 벤치마크 데이터셋
curl -sSL https://huggingface.co/datasets/anon8231489123/ShareGPT_Vicuna_unfiltered/resolve/main/ShareGPT_V3_unfiltered_cleaned_split.json \
    -o ~/airgap_bundle/datasets/ShareGPT_V3_unfiltered_cleaned_split.json

# 4. 백업용 핵심 컨테이너 이미지 아카이브 (명시적 linux/amd64)
docker pull --platform linux/amd64 vllm/vllm-openai:latest
docker pull --platform linux/amd64 wilic/gpu-burn:latest
docker pull --platform linux/amd64 nvcr.io/nvidia/k8s/cuda-sample:vectorAdd-cuda12.5.0

docker save vllm/vllm-openai:latest | gzip > ~/airgap_bundle/images/vllm_openai_amd64.tar.gz
docker save wilic/gpu-burn:latest | gzip > ~/airgap_bundle/images/gpu_burn_amd64.tar.gz
docker save nvcr.io/nvidia/k8s/cuda-sample:vectorAdd-cuda12.5.0 | gzip > ~/airgap_bundle/images/cuda_samples_amd64.tar.gz

===

K8s 클러스터(또는 단일 노드)에서 GPU 노드의 vLLM 서빙 성능(처리량, 응답 지연 시간 등)을 측정하기 위해 k6Locust를 사용하는 실전 가이드입니다.

vLLM은 OpenAI 호환 API(POST /v1/chat/completions)를 제공하므로, 스트리밍(stream: true) 또는 비스트리밍(stream: false) 방식으로 LLM 특화 지표(TTFT, 토큰 생성 속도, P99 레이턴시)를 부하 테스트할 수 있습니다.


1. k6로 테스트하기 (고성능, 단일 바이너리, 낮은 리소스 소모)

k6는 Go 언어 기반 단일 바이너리로 구동되어 리소스를 매우 적게 먹으면서도 높은 RPS(초당 요청 수)를 뽑아낼 수 있어 베어메탈/에어갭 환경에서 가장 추천됩니다.

(1) 테스트 스크립트 작성 (vllm_test.js)

가상 사용자(VU)를 점진적으로 늘려가며 vLLM에 채팅 완결 요청을 날리는 스크립트입니다.

import http from 'k6/http';
import { check, sleep } from 'k6';

// 1. 테스트 실행 옵션 (단계별 부하 증가)
export const options = {
  stages: [
    { duration: '30s', target: 5 },   // 30초 동안 5명의 VU(동시 사용자)로 증가 (웜업)
    { duration: '1m', target: 20 },   // 1분 동안 20명으로 점진 증가
    { duration: '2m', target: 20 },   // 20명 동시 요청 유지 (지속 부하)
    { duration: '30s', target: 0 },   // 30초 동안 0명으로 쿨다운
  ],
  thresholds: {
    // 95%의 요청 지연 시간이 5초 이하이고, 에러율이 1% 미만이어야 테스트 통과
    http_req_duration: ['p(95)<5000'],
    http_req_failed: ['rate<0.01'],
  },
};

const TARGET_URL = __ENV.VLLM_URL || 'http://127.0.0.1:8000/v1/chat/completions';
const MODEL_NAME = __ENV.MODEL_NAME || 'meta-llama/Llama-3.1-70B-Instruct';

export default function () {
  const payload = JSON.stringify({
    model: MODEL_NAME,
    messages: [
      { role: 'system', content: 'You are a helpful assistant.' },
      { role: 'user', content: 'Explain the difference between TCP and UDP in 3 paragraphs.' }
    ],
    max_tokens: 256,
    temperature: 0.7,
    stream: false, // 기본 HTTP 요청 시간 측정을 위해 false (TTFT 정밀 측정 시 true 설정 후 SSE 파싱)
  });

  const params = {
    headers: {
      'Content-Type': 'application/json',
    },
    timeout: '30s',
  };

  const res = http.post(TARGET_URL, payload, params);

  // 응답 상태 코드 및 토큰 생성 여부 검증
  check(res, {
    'status is 200': (r) => r.status === 200,
    'has generated content': (r) => {
      try {
        const json = JSON.parse(r.body);
        return json.choices && json.choices.length > 0;
      } catch (e) {
        return false;
      }
    },
  });

  sleep(1); // 사용자 대기 시간(Think time) 1초
}

(2) 실행 방법

  • 바이너리 직접 실행 (에어갭 노드):
# 기본 실행
./k6 run vllm_test.js

# 대상 URL 및 모델명을 환경변수로 전달
./k6 run -e VLLM_URL="http://192.168.10.50:8000/v1/chat/completions" \
         -e MODEL_NAME="meta-llama/Llama-3.1-70B-Instruct" \
         vllm_test.js
  • Podman / Docker 컨테이너로 실행:
podman run --rm -i --net=host \
  -v $(pwd)/vllm_test.js:/vllm_test.js:ro \
  grafana/k6:latest run /vllm_test.js

2. Locust로 테스트하기 (파이썬 기반, 웹 UI 및 상세 시각화 제공)

Locust는 Python 코드로 사용자 시나리오를 작성하며, 내장 웹 UI(기본 포트 8089)를 제공하여 실시간 차트 확인이 매우 편합니다.

(1) 테스트 스크립트 작성 (locustfile.py)

import json
import os
from locust import HttpUser, task, between

MODEL_NAME = os.getenv("MODEL_NAME", "meta-llama/Llama-3.1-70B-Instruct")

class VLLMUser(HttpUser):
    # 각 요청 사이 대기 시간 (1초~3초 무작위)
    wait_time = between(1, 3)

    @task
    def generate_chat_completion(self):
        payload = {
            "model": MODEL_NAME,
            "messages": [
                {"role": "system", "content": "You are a concise AI assistant."},
                {"role": "user", "content": "Summarize the core benefits of Kubernetes in 3 bullet points."}
            ],
            "max_tokens": 200,
            "temperature": 0.5,
            "stream": False
        }

        headers = {"Content-Type": "application/json"}

        with self.client.post("/v1/chat/completions", json=payload, headers=headers, catch_response=True) as response:
            if response.status_code == 200:
                try:
                    data = response.json()
                    # vLLM usage 통계 확인
                    total_tokens = data.get("usage", {}).get("total_tokens", 0)
                    response.success()
                except json.JSONDecodeError:
                    response.failure("Response body is not valid JSON")
            else:
                response.failure(f"Failed with status code: {response.status_code}")

(2) 실행 방법

  • 방법 A: 웹 UI 대시보드로 실시간 부하 조절하며 실행
# 웹 UI 모드로 기동 (호스트의 8089 포트 오픈)
locust -f locustfile.py --host http://<GPU_NODE_IP>:8000
  1. 웹 브라우저에서 http://<실행노드_IP>:8089 접속
  2. Number of users(총 가상 유저 수, 예: 20), Spawn rate(초당 투입 유저 수, 예: 2)를 입력하고 Start swarming 클릭
  3. 실시간 RPS, Failures, Response Times(Median, 95%, 99%) 그래프 확인
  • 방법 B: 헤드리스(CLI) 모드로 자동 배치 실행 (웹 UI 없이 결과 파일 저장)
    터미널 환경에서 일정 시간 동안 부하를 주고 요약 결과를 CSV로 떨어뜨릴 때 유용합니다.
locust -f locustfile.py \
  --headless \
  --host http://127.0.0.1:8000 \
  -u 30 -r 5 \
  --run-time 3m \
  --csv=locust_result
  • -u 30: 최대 30명의 사용자
  • -r 5: 초당 5명씩 증가
  • --run-time 3m: 3분간 실행

3. k6 vs Locust 선택 가이드

비교 항목k6 (권장)Locust
언어/런타임Go 기반 (단일 바이너리)Python (파이썬 런타임 및 pip 필요)
에어갭 배포 난이도매우 쉬움 (k6 파일 하나만 복사)다소 복잡 (Python wheel 패키지 오프라인 설치 필요)
리소스 효율성CPU/RAM 소비 극도로 낮음 (단일 머신에서 수만 VU 가능)GIL 제약으로 CPU 사용량 높음 (멀티코어 분산 필요)
사용자 인터페이스CLI 터미널 출력 요약 중심직관적인 내장 Web 대시보드 그래프 제공
추천 시나리오CI/CD 파이프라인, 에어갭 베어메탈 노드 간이 검증실시간 그래프를 보며 임계치를 수동 조절하고 싶을 때

4. 테스트 시 주의점 및 실측 팁

  1. vLLM 메트릭(Prometheus)과 교차 검증:
  • 부하 인가 중에 앞서 띄워둔 Prometheus/Grafana(http://<NODE>:3000) 또는 curl http://127.0.0.1:8000/metrics를 확인합니다.
  • vllm:num_requests_waiting(큐 대기 건수)이 급증하는 시점이 GPU 서빙 파이프라인의 임계 한계(Saturation Point)입니다.
  1. 동시 사용자(Concurrency) 설정:
  • B300 (8-GPU, TP=8) 환경에서는 Llama-3.1-70B 기준으로 동시 사용자 16~64명 구간에서 최대 Throughput(초당 토큰 생성 수)이 유지되는지 단계별로 올려보며 테스트하는 것이 일반적입니다.

===

사내 Nexus 프록시 레지스트리에 등록해야 하는 컨테이너 이미지별 원본 도메인(Registry FQDN)과, RHEL 10.2 환경에서 라이선스(서브스크립션) 없이 RPM을 다운로드할 수 있는지 여부 및 현실적인 대안을 명확히 정리해 드립니다.


1. 컨테이너 이미지별 원본 서비스 도메인 (Nexus Proxy 설정용)

Nexus에서 Docker Proxy Repository를 구성할 때 Remote Storage로 등록해야 하는 원본 레지스트리 도메인 목록입니다.

대상 이미지원본 호스트 도메인 (Registry URL)Nexus Proxy 대상 FQDN비고
vllm/vllm-openaiDocker Hubregistry-1.docker.io기본 공식 Docker Registry
wilic/gpu-burnDocker Hubregistry-1.docker.io커뮤니티 GPU 번인 툴
grafana/k6Docker Hubregistry-1.docker.io부하 생성 툴
prom/prometheusDocker Hubregistry-1.docker.io모니터링 엔진
grafana/grafanaDocker Hubregistry-1.docker.io대시보드 시각화

| nvcr.io/nvidia/...


(cuda-sample, dcgm-exporter) | NVIDIA GPU Cloud (NGC) | nvcr.io | NVIDIA 공식 엔터프라이즈 레지스트리 |
| quay.io/centos/...


(테스트용 OS 베이스 컨테이너) | Red Hat Quay.io | quay.io | CentOS / CoreOS 오픈 레지스트리 |
| registry.access.redhat.com


(UBI 기반 이미지) | Red Hat 공식 레지스트리 | registry.access.redhat.com | Red Hat UBI 무료 기본 이미지 |

Nexus 프록시 개설 팁:
대부분의 툴(vllm, k6, prometheus, grafana, gpu-burn)은 Docker Hub(registry-1.docker.io) 하나만 프록시로 열려 있어도 해결됩니다. 다만 NVIDIA 공식 도구(cuda-sample, dcgm-exporter)를 끌어오려면 nvcr.io 프록시 레포지토리가 사내 Nexus에 추가로 등록되어 있어야 합니다.


2. RHEL RPM은 라이선스(서브스크립션) 없이 그냥 받을 수 있는가?

결론부터 말씀드리면, 순수 RHEL 정규 패키지(BaseOS, AppStream 등)는 원칙적으로 유효한 Red Hat Subscription(계정 인증) 없이는 일반 미러 사이트처럼 익명으로 다운로드할 수 없습니다.

하지만 인프라 테스트 및 구축 단계에서 라이선스 없이 해결할 수 있는 3가지 현실적인 방법이 있습니다.


방법 1. Red Hat 무료 "개인 개발자 서브스크립션" 활용 (공식 무료)

Red Hat은 개발자 및 엔지니어에게 최대 16대 노드까지 무료로 정식 RHEL을 사용할 수 있는 'Red Hat Developer Subscription for Individuals'를 제공합니다.

  • 비용: 완전 무료 (신용카드 등록 불필요)
  • 방법:
  1. developers.redhat.com에서 무료 개인 계정 생성.
  2. 서버(또는 맥북의 RHEL 컨테이너)에서 로그인 인증:
subscription-manager register --username <계정ID> --password <비밀번호>
subscription-manager attach --auto
  1. 인증 즉시 Red Hat 공식 CDN에서 최신 RHEL 10.2 정규 RPM을 dnf installdnf download할 수 있습니다.

방법 2. CentOS Stream 10 바이너리 활용 (100% 무료, 인증 불필요)

RHEL 10과 바이너리 레벨에서 호환되는 CentOS Stream 10 저장소를 이용하는 방법입니다.

  • RHEL 10.2에 들어가는 stress-ng, fio, pciutils, iproute, kernel-devel 등의 기반 오픈소스 패키지는 CentOS Stream 10의 RPM과 빌드 ABI가 완전히 동일합니다.
  • 라이선스나 계정 등록 없이 공개 미러 URL([http://mirror.stream.centos.org/](http://mirror.stream.centos.org/)...)에서 누구나 curl 또는 dnf로 익명 다운로드가 가능합니다.

방법 3. NVIDIA 및 UBI 전용 패키지 (Red Hat 서브스크립션 불필요)

본 작업에서 가장 중요한 패키지들은 애초에 Red Hat 라이선스 검증 대상이 아닙니다.

  • NVIDIA 관련 패키지 (nvidia-fabricmanager, datacenter-gpu-manager, nvidia-container-toolkit):
  • Red Hat이 아닌 NVIDIA 공개 웹 서버(developer.download.nvidia.com)에 호스팅되어 있으므로, Red Hat 라이선스나 계정 로그인 없이 누구나 무료로 직접 다운로드할 수 있습니다.
  • Red Hat UBI (Universal Base Image) 패키지:
  • 컨테이너 환경에서 기본 제공되는 UBI BaseOS/AppStream 저장소는 서브스크립션 없이도 무료 사용 및 업데이트가 가능하도록 공개되어 있습니다.

실무 요약

  1. Nexus 프록시: Docker Hub(registry-1.docker.io)와 NVIDIA NGC(nvcr.io) 2개 도메인을 열어두시면 모든 이미지를 커버할 수 있습니다.
  2. RPM 수집:
  • NVIDIA 드라이버/Fabric Manager/Container Toolkit은 NVIDIA 서버에서 라이선스 없이 자유롭게 다운로드 가능합니다.
  • stress-ng 등 순수 RHEL OS 패키지가 추가로 필요하다면, CentOS Stream 10 공개 저장소에서 받거나 Red Hat 무료 개발자 계정(subscription-manager)을 등록하여 받으시면 됩니다.
profile
engineer

0개의 댓글