기존 클러스터 노드들과 마찬가지로 외부망과 내부망이 모두 존재하는 환경에서, GPU 노드 인수 직후 OS/플랫폼 팀이 수행해야 할 1단계(HW 무결성 및 시스템 점검)의 상세 실행 절차입니다.
특히 GPU 노드는 고전력 소모, 복잡한 PCIe/NUMA 토폴로지, 그리고 고속 NIC(ConnectX-6 + Intel E810)가 혼재되어 있으므로 초기 HW 결함(불량 PCIe 레인, 메모리 비트 에러, 발열 이슈)을 걸러내는 작업이 필수적입니다.
GPU와 NIC가 스펙시트대로 전체 대역폭을 확보한 상태로 링크 협상(Negotiation)을 마쳤는지 확인합니다.
# GPU 인식 수량 확인 (NVIDIA 벤더 ID: 10de)
lspci -nn | grep -i 3d
# NIC 인식 확인 (Mellanox: 15b3, Intel E810: 8086)
lspci -nn | grep -E "Mellanox|Ethernet controller.*810"
# 각 디바이스의 LnkCap(스펙상 지원)과 LnkSta(현재 동작 상태) 비교
# LnkSta의 Speed(16GT/s: Gen4, 32GT/s: Gen5)와 Width(x16) 확인
for bdf in $(lspci -d 10de: -d 15b3: | awk '{print $1}'); do
echo "=== Device $bdf ==="
lspci -s $bdf -vvv | grep -E "LnkCap:|LnkSta:"
done
# CPU 소켓별 NUMA 노드 구조
numactl -H
# 각 디바이스가 물려있는 NUMA 노드 확인
for dev in $(lspci -d 10de: -d 15b3: | awk '{print $1}'); do
echo "Device $dev -> NUMA Node: $(cat /sys/bus/pci/devices/0000:$dev/numa_node)"
done
OS 부팅 과정에서 발생한 메모리 비트 에러나 PCIe AER(Advanced Error Reporting) 이벤트를 확인합니다.
# PCIe corrected/uncorrectable 에러 및 하드웨어 결함 점검
dmesg -T | grep -iE "mce|edac|aer|pcie.*error|fail|corrupted"
(AER Corrected 에러가 수백 번 이상 반복 카운팅된다면 슬롯/라이저 결착 불량이거나 불량 케이블일 가능성이 높음)
ipmitool sel elist | tail -n 30
ipmitool sdr list | grep -iE "fan|temp|status"
GPU 번인에 앞서 호스트 시스템의 기본 연산 및 시스템 메모리의 안정성을 먼저 확인합니다.
stress-ng를 이용해 시스템 메모리의 약 80~85%를 할당하고 전체 vCPU 코어를 1시간 동안 포화 상태로 구동합니다.# 전체 CPU 코어 수 확인 후 실행
stress-ng --cpu $(nproc) --vm 4 --vm-bytes 80% --verify --timeout 1h --metrics-brief
watch -n 1 'cat /sys/devices/system/edac/mc/mc*/ce_count'
watch -n 2 'sensors | grep -i "Package id"'
vLLM 구동 시 대용량 모델 가중치(Checkpoint)를 로컬 캐시에 저장하고 로드해야 하므로, 로컬 NVMe의 성능과 상태가 중요합니다.
# nvme-cli 설치 확인 후 상태 점검
nvme list
nvme smart-log /dev/nvme0n1
(Critical Warning이 0, Available Spare가 100%, Media and Data Integrity Errors가 0인지 확인)
fio --name=nvme_write --filename=/tmp/test_fio --size=10G --rw=write --bs=1M --direct=1 --ioengine=libaio --runtime=30 --group_reporting
rm -f /tmp/test_fio
현재 외부망은 Mellanox ConnectX-6, 내부망은 Intel E810입니다. 기존 클러스터(모두 E810 계열)와의 이종 구성을 감안하여 링크 레벨을 먼저 정리해야 합니다.
mlx5_core) 로드 및 펌웨어 버전 확인:ethtool -i <cx6_iface_name>
ethtool <cx6_iface_name> | grep -E "Speed:|Duplex:|Link detected:"
ip -s link show <cx6_iface_name>
ice) 및 펌웨어/DDP(Package) 버전 확인:ethtool -i <e810_iface_name>
# driver: ice, version, firmware-version 확인
ethtool -i 출력값과 펌웨어 버전을 일치시키는 작업이 권장됩니다.ethtool에서 NO-CARRIER 상태가 정상 유지되는지 확인합니다.| 점검 항목 | 통과 기준 (Pass Criteria) | 조치 사항 (Fail 시) |
|---|---|---|
| GPU/NIC PCIe 링크 | 전 장치 LnkSta = LnkCap (최대 Gen / x16 유지) | 슬롯 재장착, Riser 카드 교체 요청 |
| AER / MCE 로그 | 커널 로그 상 Uncorrectable 에러 0건 | CPU/메모리/보드 점검 요청 |
| CPU/RAM 부하 | stress-ng 1시간 통과, EDAC 에러 0건, 스로틀링 없음 | 불량 메모리 모듈 교체 |
| NVMe 상태 | Critical Warning 0, 읽기/쓰기 스펙 속도 도달 | NVMe 교체 또는 슬롯 점검 |
| NIC 펌웨어 | CX-6 최신 FW, E810 펌웨어/드라이버 기존 노드와 일치 | 펌웨어 업데이트 수행 |
이 단계가 모두 통과되면 HW 불량 이슈는 배제할 수 있으므로, 안심하고 Phase 2 (NVIDIA Driver / CUDA 설치 및 gpu-burn)로 진입하시면 됩니다.
===
2단계의 핵심 목표는 GPU 소프트웨어 스택(Driver, CUDA, Fabric Manager, Container Toolkit)을 안정적으로 배포하고, 실제 고부하 추론/학습 환경을 모사하여 전력 피크(Power Surge), 발열(Thermal Throttling), GPU 간 P2P 통신(NVLink/PCIe), VRAM 무결성을 사전에 검증하는 것입니다.
현재 노드는 외부망(ConnectX-6)만 연결되어 있으므로, 외부망을 통해 공식 리포지토리로부터 패키지를 내려받아 구성합니다.
안정성이 검증된 Data Center(Production) 브랜치 드라이버와 CUDA 스택을 구성합니다.
# Nouveau 비활성화 확인
lsmod | grep nouveau # 아무것도 출력되지 않아야 함
# 커널 헤더 및 빌드 도구 설치
apt-get install -y build-essential linux-headers-$(uname -r) dkms
# (RHEL/Rocky 계열인 경우: dnf install -y kernel-devel-$(uname -r) kernel-headers gcc make)
nvidia-fabricmanager가 필수입니다. 드라이버 버전과 Fabric Manager 버전은 반드시 완전히 일치해야 합니다.# 공식 NVIDIA 리포지토리 등록 후 드라이버 및 Fabric Manager 설치
apt-get install -y cuda-drivers-fabricmanager-550 nvidia-driver-550-server
# Fabric Manager 서비스 활성화 및 시작
systemctl enable --now nvidia-fabricmanager
systemctl status nvidia-fabricmanager
apt-get install -y nvidia-container-toolkit
nvidia-ctk runtime configure --runtime=docker
systemctl restart docker
nvidia-smi -pm 1
systemctl enable --now nvidia-persistenced
드라이버가 로드된 후 GPU 간 통신 대역폭과 토폴로지 연결 상태를 점검합니다.
nvidia-smi
# 전체 GPU 인식 수량, VRAM 용량, 드라이버/CUDA 버전 확인
# GPU 간 토폴로지 매트릭스 확인
nvidia-smi topo -m
NV# (NVLink)로 표시되어야 합니다.PIX(단일 스위치), PXB(PCIe 브리지), 또는 SYS(호스트/CPU 경유)로 표시됩니다.nvidia-smi nvlink -s
# 모든 NVLink 포트가 Active 상태인지 확인
nvidia-smi nvlink -e
# CRC 에러, 리플레이 에러가 0인지 확인
p2pBandwidthLatencyTest)docker run --rm --gpus all nvcr.io/nvidia/k8s/cuda-sample:vectorAdd-cuda12.5.0 \
p2pBandwidthLatencyTest
하드웨어 수준의 VRAM 비트 결함, 온보드 컨트롤러 결함을 조기에 발견하기 위해 NVIDIA DCGM(Data Center GPU Manager) 진단을 수행합니다.
apt-get install -y datacenter-gpu-manager
systemctl enable --now nvidia-dcgm
dcgmi diag -r 3
PCIe, Memory, Diagnostic, SM Stress)에서 PASS가 떨어지는지 확인합니다.Page Retirement나 Uncorrectable ECC Errors가 검출되는 카드는 즉시 HW 교체 대상입니다.vLLM 구동 시 발생할 수 있는 최대 전력 피크(TDP Saturation)와 랙/서버 섀시 내 쿨링 성능을 한계치까지 검증합니다.
gpu-burn 도커 컨테이너 실행docker run --rm --gpus all \
-v /tmp:/tmp \
wilic/gpu-burn:latest \
3600 # 3600초 (1시간 구동)
nvidia-smi dmon -s pucvmet -d 2
pwr: 각 GPU가 스펙상 최대 TDP(예: 400W, 700W) 근처까지 안정적으로 도달하는지 확인.temp: GPU 온도가 쓰로틀링 임계치(통상 80~83℃ 이상)를 넘지 않고 안정적인 플래토(Plateau)를 형성하는지 점검.clocks: 써멀 또는 파워 스로틀링으로 인해 클록이 급격히 튀거나(Drop) 다운되지 않는지 확인.watch -n 5 'ipmitool sensor | grep -iE "fan|psu|watt|temp"'
| 점검 항목 | 통과 기준 (Pass Criteria) | 실패 시 원인 및 조치 |
|---|---|---|
| 드라이버 & Fabric Manager | nvidia-smi 인식 정상, Fabric Manager Active (running) | 버전 불일치 확인 후 재설치 |
| NVLink / P2P 대역폭 | 모든 GPU 간 에러 0건, 스펙 대역폭 달성 | NVSwitch 보드 결착 점검 / 드라이버 재적재 |
| DCGM Level 3 진단 | 전체 테스트 항목 PASS, ECC Uncorrectable 0건 | 불량 GPU RMA 요청 |
| gpu-burn (1시간) | 연산 에러(Faulty: 0) 0건, 서버 리셋/전원 꺼짐 없음 | PSU 용량 부족 또는 전원 레일 결함 점검 |
| 써멀 및 쿨링 | 풀 로드 상태에서 최대 동작 온도 이하 유지 (클록 강하 없음) | 섀시 팬 불량, 써멀 구리스/방열판 밀착 불량 |
위 테스트를 통과하면 GPU 하드웨어와 기본 런타임의 신뢰성은 확보된 것이므로, 다음 단계인 Phase 3 (vLLM 설치 및 Compute Cluster 호출 연동)으로 진입하시면 됩니다.
===
Phase 3의 핵심 목표는 vLLM 서빙 환경을 안정적으로 구성하고, 아직 사설망(E810)이 개통되지 않은 과도기 상황에서 기존 Compute 클러스터 노드들과의 네트워크 통신 경로를 확보하여 실제 추론 API 호출 파이프라인을 검증하는 것입니다.
Compute 클러스터(외부망 + 내부망 bond1 보유)와 GPU 노드(현재 외부망 ConnectX-6만 활성화) 간 통신을 위해 가장 현실적인 방식을 먼저 결정하고 경로를 엽니다.
8000) 인바운드 허용.# 인입된 인터페이스와 나가는 인터페이스 불일치 시 드랍 방지 (Loose Reverse Path Filter)
sysctl -w net.ipv4.conf.all.rp_filter=2
sysctl -w net.ipv4.conf.default.rp_filter=2
ping -c 3 <GPU_NODE_CX6_IP>
# 포트 오픈 여부 (임시 nc/python 서버 등으로 포트 열고 확인)
nc -zv <GPU_NODE_CX6_IP> 8000
Phase 4(Storage 클러스터 연동) 전이므로, 검증용 모델을 GPU 노드의 로컬 고속 NVMe 디스크에 먼저 배치합니다.
mkdir -p /data/models /data/hf_home
export HF_HOME=/data/hf_home
meta-llama/Llama-3.1-8B-Instruct (단일 GPU TP=1)meta-llama/Llama-3.1-70B-Instruct 또는 Qwen2.5-72B-Instruct (8-GPU TP=8)# huggingface-cli 이용 다운로드 (외부망 Direct)
huggingface-cli download meta-llama/Llama-3.1-8B-Instruct \
--local-dir /data/models/Llama-3.1-8B-Instruct \
--local-dir-use-symlinks False
vLLM을 공식 컨테이너 기반으로 기동하여 호스트 종속성을 최소화하고, 안정적인 서빙 옵션을 적용합니다.
docker run -d --name vllm-test \
--runtime nvidia \
--gpus '"device=0"' \
-v /data/models:/models \
-p 8000:8000 \
--ipc=host \
--restart unless-stopped \
vllm/vllm-openai:latest \
--model /models/Llama-3.1-8B-Instruct \
--served-model-name llama-3.1-8b \
--port 8000 \
--max-model-len 8192 \
--gpu-memory-utilization 0.90 \
--enforce-eager
--ipc=host: 파이토치 및 vLLM 내부 공유 메모리(Shared Memory) 부족 에러(OOM/Crash) 방지.--enforce-eager: 초기 테스트 시 CUDA Graph 컴파일 오버헤드를 배제하고 즉각적인 서빙 및 메모리 할당 검증.docker run -d --name vllm-tp-test \
--runtime nvidia \
--gpus all \
-v /data/models:/models \
-p 8000:8000 \
--ipc=host \
vllm/vllm-openai:latest \
--model /models/Llama-3.1-70B-Instruct \
--served-model-name llama-3.1-70b \
--tensor-parallel-size 8 \
--gpu-memory-utilization 0.90 \
--max-model-len 8192
docker logs -f vllm-tp-test)에서 8개 rank의 NCCL 초기화 및 Weight Loading 완료 메시지 확인.curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "llama-3.1-8b",
"messages": [{"role": "user", "content": "Ping test"}],
"max_tokens": 30
}'
usage.total_tokens 반환 여부 확인.curl -X POST http://<GPU_NODE_CX6_IP>:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "llama-3.1-8b",
"messages": [{"role": "user", "content": "Explain Kubernetes pods in 2 sentences."}],
"max_tokens": 100,
"temperature": 0.7
}'
"stream": true) 모드 시 Chunk 수신 정상 여부 점검.apiVersion: v1
kind: Pod
metadata:
name: vllm-client-test
namespace: default
spec:
containers:
- name: curl-client
image: curlimages/curl:latest
command: ["sleep", "3600"]
kubectl exec -it vllm-client-test -- curl http://<GPU_NODE_CX6_IP>:8000/v1/models
Phase 5(본격 성능 테스트)로 넘어가기 전, Compute 노드에서 단시간 경량 동시 호출을 날려 vLLM의 PagedAttention 및 큐잉 동작을 확인합니다.
for i in {1..10}; do
curl -s http://<GPU_NODE_CX6_IP>:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "llama-3.1-8b", "messages": [{"role": "user", "content": "Count from 1 to 50"}], "max_tokens": 100}' &
done; wait
nvidia-smi를 통해 VRAM 사용률 고정 여부(PagedAttention 블록 테이블 확보) 확인./metrics 엔드포인트(http://<GPU_NODE_CX6_IP>:8000/metrics)를 스크랩하여 Prometheus 메트릭(vllm:num_requests_running, vllm:num_requests_waiting) 출력 확인.| 점검 항목 | 통과 기준 (Pass Criteria) | 조치 사항 (Fail 시) |
|---|---|---|
| 외부망 도달성 | Compute 노드 GPU 노드 8000 포트 지연 없이 통신 성공 | 인프라/보안팀 방화벽 정책 확인 |
| K8s Egress 연동 | Compute 클러스터 내부 Pod에서 API 호출 성공 | CNI Egress NAT 대역 방화벽 등록 |
| 단일/멀티 GPU 서빙 | TP=1 및 TP=8 모델 구동 시 NCCL 오류 없이 구동 완료 | nvidia-fabricmanager 상태 및 GPU 토폴로지 재점검 |
| 스트리밍 응답 | Server-Sent Events(SSE) 스트리밍 토큰 유실 없이 수신 | 프록시/방화벽의 HTTP 버퍼링/타임아웃 옵션 점검 |
이 단계가 완료되면 Compute 클러스터 애플리케이션 관점에서 GPU 노드는 서빙 가능한 상태가 되며, 이어지는 Phase 4 (Storage Cluster GPU Node 연동 및 가중치 직접 로딩)로 진입할 수 있습니다.
===
Phase 4의 핵심 목표는 Storage 클러스터(S3/NFS/Ceph/AIStor 등)와 GPU 노드 간의 데이터 파이프라인을 연결하고, 수십~수백 GB에 달하는 대규모 LLM 모델 가중치를 병목 없이 초고속으로 전송·로딩할 수 있는지 검증하는 것입니다.
기존 Storage 클러스터는 내부망 bond1에 연결되어 있으므로, GPU 노드 측의 네트워크 경로 설정과 MTU 일치 작업이 선행되어야 합니다.
사설망(E810) 정식 구성 전후 상태에 따라 스토리지와의 통신 경로를 확보합니다.
# 스토리지 클러스터 대역이 10.100.0.0/16 인 경우
ip route add 10.100.0.0/16 dev <E810_IFACE> proto static
# E810 인터페이스 MTU를 기존 노드 및 스토리지와 동일하게 설정 (예: 9000)
ip link set dev <E810_IFACE> mtu 9000
# Don't Fragment 플래그를 걸고 실제 점보 패킷(8972 bytes = 9000 - 28바이트 헤더) 왕복 검증
ping -M do -s 8972 <STORAGE_ENDPOINT_IP>
스토리지 애플리케이션 레벨로 넘어가기 전, GPU 노드 Storage 노드 간 순수 네트워크 대역폭을 먼저 확인합니다.
iperf3 -s)로 두고, GPU 노드에서 8~16개 멀티 스트림으로 테스트:iperf3 -c <STORAGE_IP> -P 8 -t 30 -O 3
sysctl -w net.core.rmem_max=67108864
sysctl -w net.core.wmem_max=67108864
sysctl -w net.ipv4.tcp_rmem="4096 87380 33554432"
sysctl -w net.ipv4.tcp_wmem="4096 65536 33554432"
스토리지 구성 방식(오브젝트 스토리지 S3 API 또는 공유 파일시스템 NFS/CephFS)에 맞춰 실측 테스트를 수행합니다.
LLM 모델 가중치는 Safetensors 파일(수 GB ~ 수십 GB 크기의 단일 오브젝트 수십 개) 형태로 구성되므로, 멀티파트 동시 읽기(Multipart Concurrent Read) 성능이 핵심입니다.
# 예: 10GB 오브젝트 기준 동시 Get Throughput 측정 (Warp 활용 예시)
warp get --host=<S3_ENDPOINT> --access-key=<KEY> --secret-key=<SECRET> \
--bucket=model-weights --obj.size=10GiB --concurrent=8 --duration=1m
aws s3 cp with multi-threading, 또는 s3cmd, mc)로 로컬 NVMe에 다운로드:# 멀티스레드 다운로드 설정 후 시간 측정
time aws s3 cp s3://model-weights/Llama-3.1-70B-Instruct/ /data/models/Llama-3.1-70B-Instruct/ \
--recursive --endpoint-url http://<STORAGE_S3_ENDPOINT>
스토리지 볼륨을 GPU 노드에 직접 마운트하여 사용할 경우입니다.
# NFS v4.2, rsize/wsize 1M, TCP 옵션 적용
mount -t nfs -o vers=4.2,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noatime <STORAGE_IP>:/models /mnt/models
fio --name=storage_seq_read \
--directory=/mnt/models \
--rw=read \
--bs=1M \
--size=50G \
--numjobs=8 \
--iodepth=16 \
--ioengine=libaio \
--direct=1 \
--group_reporting
실제 스토리지에 적재된 대형 모델 가중치를 기반으로 vLLM 엔진이 기동되는 전체 파이프라인(Cold Start)을 검증합니다.
time docker run --rm \
--runtime nvidia \
--gpus all \
-v /mnt/models:/models \
--ipc=host \
vllm/vllm-openai:latest \
--model /models/Llama-3.1-70B-Instruct \
--tensor-parallel-size 8 \
--enforce-eager
NCCL_ASYNC_ERROR_HANDLING=1, Timeout 30분 기본값) 발생 여부 점검.Init 스크립트가 S3에서 로컬 고속 NVMe(/data/models)로 동기화한 뒤 vLLM을 올리는 패턴 검증.| 점검 항목 | 통과 기준 (Pass Criteria) | 조치 사항 (Fail 시) |
|---|---|---|
| L2/L3 도달성 & MTU | ping -M do -s 8972 무손실 통과 | 스위치 포트 및 인터페이스 MTU 9000 재구성 |
| 원시 전송 대역폭 (iperf3) | E810 링크 스펙의 85% 이상 대역폭 확보 | TCP 윈도우 튜닝 및 인터페이스 링 버퍼(ethtool -G) 점검 |
| I/O 처리량 (FIO / S3) | 로컬 NVMe 쓰기 한계치 또는 스토리지 링크 한계치 도달 | 스토리지 노드 I/O 병목 또는 멀티파트 세션 수 증설 |
| vLLM Cold Start | 70B 모델 기준 1분~2분 이내 Weight Load 완료 후 Serving 준비 완료 | 로딩 전략 변경 (직접 마운트 로컬 NVMe 캐싱) |
===
Phase 5는 vLLM 서빙 엔진의 실무 한계치(Saturation Point)와 서비스 수준 목표(SLO)를 도출하고, 실제 다중 사용자 워크로드가 Compute 클러스터에서 유입될 때의 처리량(Throughput), 지연 시간(TTFT/ITL), 동시성(Concurrency), 리소스 병목을 정량화하는 단계입니다.
에어갭 환경이므로 외부 네트워크 의존 없이 내부 데이터셋과 오프라인 벤치마크 도구를 활용해 4개 하위 단계로 진행합니다.
LLM 서빙 성능 평가는 일반 HTTP 처리량과 달리 토큰 생성 특성을 반영한 4대 핵심 지표를 측정합니다.
실제 엔터프라이즈 업무 환경을 반영하여 3가지 대표 시나리오를 구성합니다.
| 시나리오 | 입력 토큰 (Input) | 출력 토큰 (Output) | 대표 업무 유형 | 성능 특징 |
|---|---|---|---|---|
| A. 대화형 챗봇 (Interactive) | ~512 | ~256 | 질의응답, 에이전트 대화 | ITL(TPOT) 중심 검증, 동시 세션 처리 |
| B. RAG / 문서 요약 (Heavy Prefill) | ~4,096 | ~512 | 문서 검색 후 요약, 로그 분석 | Prefill 병목, TTFT 및 KV Cache 압박 |
| C. 코드 생성 / 장문 생성 (Heavy Decode) | ~1,024 | ~2,048 | 코드 생성, 리포트 작성 | Decode 병목, Throughput 및 VRAM 대역폭 포화 |
Compute 클러스터 트래픽 유입 전, GPU 노드 로컬에서 vLLM 내장 도구(benchmark_serving.py)를 이용해 엔진 본연의 베이스라인 성능을 측정합니다.
ShareGPT_V3_unfiltered_cleaned_split.json 활용.# vLLM 컨테이너 내부 또는 Python 가상환경에서 실행
python3 -m vllm.entrypoints.openai.benchmark_serving \
--backend vllm \
--model /models/Llama-3.1-70B-Instruct \
--dataset-name sharegpt \
--dataset-path /data/benchmarks/ShareGPT_V3_unfiltered_cleaned_split.json \
--num-prompts 1000 \
--request-rate 10 \
--max-concurrency 64 \
--save-result \
--result-filename /tmp/vllm_result_tp8_concur64.json
실제 운영 환경을 모사하여 Compute 클러스터의 여러 워커 노드/Pod에서 GPU 노드로 동시 요청을 부하시킵니다.
locust (분산 모드) 또는 k6 컨테이너를 Compute 클러스터의 Pod 4~8개로 분산 배포.vllm_load.js):import http from 'k6/http';
import { check } from 'k6';
export const options = {
stages: [
{ duration: '2m', target: 16 },
{ duration: '3m', target: 64 },
{ duration: '3m', target: 128 },
{ duration: '2m', target: 0 },
],
};
export default function () {
const payload = JSON.stringify({
model: 'llama-3.1-70b',
messages: [{ role: 'user', content: 'Explain distributed data lakehouse architecture in detail.' }],
max_tokens: 512,
stream: false
});
const params = { headers: { 'Content-Type': 'application/json' }, timeout: '60s' };
const res = http.post('http://<GPU_NODE_IP>:8000/v1/chat/completions', payload, params);
check(res, { 'status is 200': (r) => r.status === 200 });
}
사용자 UI 연동 시 체감 성능인 TTFT를 정확히 추출하기 위해 스트리밍 청크 단위 타임스탬프를 기록합니다.
# benchmark_ttft.py (Compute Cluster의 Pod/Bastion에서 실행)
import asyncio, time, httpx
API_URL = "http://<GPU_NODE_IP>:8000/v1/chat/completions"
CONCURRENCY = 32
async def send_streaming_request(client, prompt_id):
payload = {
"model": "llama-3.1-70b",
"messages": [{"role": "user", "content": "Tell me a comprehensive history of computing."}],
"max_tokens": 256,
"stream": True
}
t0 = time.perf_counter()
first_token_time = None
total_tokens = 0
async with client.stream("POST", API_URL, json=payload, timeout=60.0) as resp:
async for chunk in resp.aiter_lines():
if chunk.startswith("data: ") and not chunk.endswith("[DONE]"):
if first_token_time is None:
first_token_time = time.perf_counter()
total_tokens += 1
end_time = time.perf_counter()
ttft = (first_token_time - t0) * 1000 if first_token_time else 0
tpot = ((end_time - first_token_time) / total_tokens * 1000) if total_tokens > 0 else 0
return {"ttft": ttft, "tpot": tpot, "tokens": total_tokens}
async def main():
limits = httpx.Limits(max_connections=100, max_keepalive_connections=50)
async with httpx.AsyncClient(limits=limits) as client:
tasks = [send_streaming_request(client, i) for i in range(CONCURRENCY)]
results = await asyncio.gather(*tasks)
avg_ttft = sum(r["ttft"] for r in results) / len(results)
avg_tpot = sum(r["tpot"] for r in results) / len(results)
print(f"[Concurrency {CONCURRENCY}] Avg TTFT: {avg_ttft:.2f} ms | Avg TPOT (ITL): {avg_tpot:.2f} ms")
asyncio.run(main())
부하 인가 중 GPU 노드에서 아래 지표들을 1~2초 주기로 수집하여 병목 원인을 규명합니다.
http://<GPU_NODE_IP>:8000/metrics)vllm:num_requests_running: 동시 처리 중인 요청 수 (배치 크기).vllm:num_requests_waiting: 대기 큐(Queue)에 쌓인 요청 수 (0보다 크면 서빙 용량 포화).vllm:gpu_cache_usage_factor: GPU KV Cache 메모리 점유율 (1.0 도달 시 요청 선점/Preemption 또는 큐잉 발생).DCGM_FI_DEV_GPU_UTIL: GPU SM 사용률 (Compute 병목 여부).DCGM_FI_DEV_MEM_COPY_UTIL: HBM/VRAM 메모리 대역폭 활용률 (LLM Decoding 시 주된 병목 지점).DCGM_FI_DEV_POWER_USAGE: TDP 대비 실제 소비 전력 (스로틀링 검증).| 평가 항목 | 목표 성능 지표 (70B 모델, 8-GPU TP=8 기준 예시) | 이상 징후 발생 시 점검 사항 |
|---|---|---|
| TTFT (Latency) | P95 기준 < 1.5초 (입력 1k 토큰 기준) | --gpu-memory-utilization 상향, Chunked Prefill 활성화 여부 점검 |
| ITL / TPOT | 평균 < 30ms/token (초당 30 token 이상 생성 체감) | KV Cache 스왑 발생 여부, Tensor Parallel 통신 지연(NVLink) 점검 |
| 동시성 처리 | 동시 32개 세션 인가 시 에러율(5xx/Timeout) 0% | vLLM --max-num-seqs 조정 및 Compute 노드 HTTP Timeout 설정 검토 |
| 안정성 (VRAM) | Concurrency 포화 상태에서도 OOM 크래시 없이 대기 큐 정상 소화 | --max-model-len 및 PagedAttention 블록 크기 최적화 |
위 기준을 바탕으로 얻은 최종 Throughput-Latency 커브 데이터를 토대로 Compute 클러스터의 API 게이트웨이 및 HPA(또는 Rate Limiting) 임계값을 설정하시면 전체 노드 도입 및 서비스 연동 절차가 완료됩니다.