26O07b

QK·5일 전

네. 현재 상태가 “B300 node가 기존 K8s cluster의 worker로 join은 완료됐지만 GPU용 label/operator 설정은 아직”이라면, 바로 Stage6를 실행하기보다 Stage6-Preflight → 핵심 Stage6 → 선택 시험으로 나누는 것이 좋습니다.

현재 환경에서는 STAGE6_TOPOLOGY=worker이고 ClusterMesh 전용 6g는 제외하면 됩니다. 또한 Spark burst(6d)는 GPU acceptance의 핵심이 아니므로 우선 제외하는 것을 권합니다.

1. 먼저 해야 할 준비

권장 준비 순서는 다음 하나의 흐름으로 보면 됩니다.

GPU worker join 완료
        ↓
① Node label / taint
        ↓
② kubelet CPU/Topology 정책 확인
        ↓
③ NVIDIA host driver 정책 결정
        ↓
④ GPU Operator 설치
        ↓
⑤ nvidia.com/gpu=8 확인
        ↓
⑥ GPU Operator validator 확인
        ↓
⑦ GPU 1장 Pod smoke
        ↓
⑧ GPU 8장 Pod smoke
        ↓
⑨ DCGM Exporter / metrics 확인
        ↓
⑩ Cilium / Hubble 확인
        ↓
⑪ Local NVMe model path 확인
        ↓
⑫ vLLM Deployment 준비
        ↓
Stage6

2. GPU Node label부터 정리

예를 들어 node 이름이:

GPU_NODE=b300-gpu-01

이라면 acceptance에서 직접 사용할 label을 하나 두는 것을 권합니다.

kubectl label node ${GPU_NODE} \
  node-role.kubernetes.io/gpu=true \
  accelerator=nvidia-b300 \
  gpu.nvidia.com/model=b300 \
  validation.openai.com/b300=true

다만 실제 GPU 모델/제품 정보 label은 GPU Operator/NFD/GFD가 자동 생성하는 NVIDIA label을 우선 사용하는 게 좋고, 위 label은 사람이 이해하기 쉬운 운영/validation label 용도라고 생각하면 됩니다.

확인:

kubectl get node ${GPU_NODE} --show-labels

Stage6용으로는 하나의 단순한 selector를 정해 놓는 게 좋습니다.

validation.openai.com/b300=true

그러면 test Pod가 실수로 compute worker에 뜨는 것을 방지할 수 있습니다.


3. Taint도 권장

GPU node를 일반 workload가 먹지 못하게 하려면:

kubectl taint node ${GPU_NODE} \
  nvidia.com/gpu=true:NoSchedule

를 권합니다.

그러면 GPU workload에는:

tolerations:
  - key: nvidia.com/gpu
    operator: Equal
    value: "true"
    effect: NoSchedule

가 필요합니다.

다만 현재 Stage6 스크립트가 생성하는 모든 test Pod에 이 toleration이 들어 있는지 먼저 확인해야 합니다.

따라서 첫 Stage6 실행 전에 taint를 바로 적용하기보다는:

1. label 먼저
2. Stage6 Pod manifest의 toleration 확인
3. taint 적용

순서가 안전합니다.


4. kubelet CPU/Topology 정책

GPU node에서 확인할 것은:

cat /var/lib/kubelet/config.yaml | \
  egrep 'cpuManagerPolicy|topologyManagerPolicy'

목표는 앞서 논의했던:

cpuManagerPolicy: static
topologyManagerPolicy: restricted

입니다.

다만 이것은 단순히 config file만 수정하고 끝내면 안 됩니다. static CPU Manager의 효과를 얻으려면 GPU/vLLM Pod의 CPU resource도 Guaranteed QoS가 되도록 설계해야 합니다.

예:

resources:
  requests:
    cpu: "32"
    memory: 256Gi
    nvidia.com/gpu: 8
  limits:
    cpu: "32"
    memory: 256Gi
    nvidia.com/gpu: 8

즉 CPU request와 limit을 동일한 정수 core로 잡는 식입니다.


5. GPU Operator 설치

현재 가장 중요한 준비입니다.

이미 Stage1에서 검증한 host NVIDIA driver를 그대로 유지하려면 초기 Stage6에서는 GPU Operator가 driver를 재설치하지 않게 하는 구성이 비교에 유리합니다.

목표 구조:

B300 Worker
 │
 ├─ Host NVIDIA Driver   ← Stage1에서 검증
 │
 ├─ containerd
 │
 └─ kubelet
       │
       ▼
 NVIDIA GPU Operator
       │
       ├─ Container Toolkit
       ├─ Device Plugin
       ├─ GPU Feature Discovery
       ├─ DCGM
       ├─ DCGM Exporter
       └─ Validator

즉 현재 acceptance에서는:

driver management     OFF
toolkit               ON
device-plugin         ON
GFD/NFD               ON
DCGM exporter         ON
validator             ON
MIG                    불필요하면 OFF

정도로 시작하는 것이 깔끔합니다.

설치 후 핵심 확인은:

kubectl get pods -n gpu-operator

와:

kubectl describe node ${GPU_NODE}

입니다.

반드시 node에:

Capacity:
  nvidia.com/gpu: 8

Allocatable:
  nvidia.com/gpu: 8

가 나타나야 합니다.

이것이 Stage6의 Gate-0이라고 생각하면 됩니다.


6. GPU Operator가 만든 label 확인

설치 후에는:

kubectl get node ${GPU_NODE} \
  -o json | jq '.metadata.labels |
  with_entries(select(.key | startswith("nvidia.com/")))'

처럼 NVIDIA label을 확인하세요.

여기서 GPU product, driver/toolkit capability 등이 정상적으로 발견되는지 보는 것이 좋습니다.

직접 만든:

validation.openai.com/b300=true

label은 Stage6 scheduling 용도로 쓰고, NVIDIA 자동 label은 실제 HW discovery 확인용으로 구분하면 관리하기 쉽습니다.


7. GPU 1장 Smoke Pod

Stage6 script를 실행하기 전에 수동으로 한 번은 해보는 것을 권합니다.

Pod가:

resources:
  limits:
    nvidia.com/gpu: 1

을 요청하게 하고 Pod 내부:

nvidia-smi

가 정상인지 봅니다.

여기서 중요한 것은 host의 nvidia-smi가 아니라:

Kubelet
  ↓
NVIDIA Device Plugin
  ↓
Container Runtime
  ↓
Pod
  ↓
GPU

경로가 정상이라는 것을 확인하는 것입니다.


8. GPU 8장 Pod도 확인

다음으로:

resources:
  limits:
    nvidia.com/gpu: 8

인 Pod를 한 번 띄워서:

nvidia-smi -L
nvidia-smi topo -m

를 확인합니다.

여기까지 성공하면 Stage6a/6c를 시작할 준비가 된 것입니다.


9. DCGM Exporter

확인:

kubectl get pods -A | grep -E 'dcgm|gpu'

그리고 exporter metrics에서 GPU metric이 실제로 나오는지 확인합니다.

Stage6에서는 단순히 exporter Pod가 Running인 것으로 끝내지 말고:

GPU util
HBM
temperature
power
clock
ECC

가 실제 B300 GPU 8장에 대해 수집되는지 보는 게 좋습니다.


10. Cilium/Hubble 준비

현재 worker topology에서는 GPU node도 기존 Cilium datapath에 정상 편입되어 있어야 합니다.

최소:

kubectl -n kube-system get pods -o wide | grep cilium

에서 GPU node의 Cilium agent가 Running인지 확인합니다.

Hubble을 Stage6i에서 사용할 계획이면 Hubble도 먼저 정상이어야 합니다.

즉:

Cilium agent on B300 node
        ↓
Pod network 정상
        ↓
NetworkPolicy 가능
        ↓
Hubble flow 관측 가능

상태까지 준비합니다.


11. Local NVMe 준비

이것도 Stage6 성능 비교에서 매우 중요합니다.

Bare-metal Stage3a에서:

/mnt/local-nvme-cache/models

를 사용했다면 K8s에서도 가능하면 동일한 데이터를 사용하세요.

예를 들어 node:

/mnt/local-nvme-cache/models/
 └─ Meta-Llama-3.1-70B-Instruct/

를 vLLM Pod에:

volumeMounts:
  - name: model-cache
    mountPath: /models
    readOnly: true

volumes:
  - name: model-cache
    hostPath:
      path: /mnt/local-nvme-cache/models
      type: Directory

처럼 mount할 수 있습니다.

Stage3a와 Stage6에서 model storage가 달라지면 startup이나 cold-load 비교가 불공정해집니다.


12. Stage6 공통 변수

현재 환경에서 가장 먼저 정해둘 값은 대략 다음입니다.

export STAGE6_TOPOLOGY=worker

export VALIDATION_ROOT=/var/log/b300_validation
export VALIDATION_ENV_FILE=/path/to/validation_env.sh

export GPU_NODE=b300-gpu-01

export GPU_NODE_SELECTOR_KEY=validation.openai.com/b300
export GPU_NODE_SELECTOR_VALUE=true

다만 현재 스크립트의 selector 변수명이 step마다 GPU_NODE_SELECTOR_VALUE, NODE_SELECTOR_VALUE 등으로 일부 다르기 때문에, 실제 package의 stage6_profile.sh를 source해서 공통값을 쓰는 방식을 권합니다.


13. Stage6c — 제일 먼저

목적: GPU Operator/NFD/Topology Manager/GPU topology 확인.

실행 전에 필요한 값:

export STAGE6_TOPOLOGY=worker
export GPU_NODE_SELECTOR_VALUE=b300-gpu-01

또는 package에서 사용하는 node selector 값에 맞춥니다.

실행:

./stage6c_k8s_gpu_topology_check.sh

여기서는:

GPU Operator
NFD/GFD
Topology Manager
nvidia.com/gpu=8
TP8 Pod
nvidia-smi topo -m

를 확인합니다.

추천: 필수


14. Stage6a — NCCL

Stage6c가 PASS한 뒤 실행합니다.

필요 변수:

export STAGE6_TOPOLOGY=worker
export GPU_NODE_SELECTOR_VALUE=b300-gpu-01

export STAGE1_NCCL_BASELINE=/var/log/b300_validation/\
stage1_xxx/nccl_result.txt

실행:

./stage6a_k8s_nccl_revalidation.sh

목적은:

Bare-metal NCCL
       ↕
Container/Pod NCCL

비교입니다.

추천: 필수


15. Stage6b — Network

현재 worker topology에서는 ClusterMesh 시험이 아닙니다.

기본:

export STAGE6_TOPOLOGY=worker

외부 iperf server가 있다면:

export EXTERNAL_IPERF_SERVER=<iperf-server-IP>

를 추가합니다.

실행:

./stage6b_k8s_network_revalidation.sh

여기서는 우선:

Pod → Pod
Pod → external endpoint

를 보면 충분합니다.

추천: 필수


16. Stage6e — AIStor/MinIO

실제 vLLM에서 AIStor/MinIO를 사용할 계획이므로 유지하는 것을 권합니다.

필요 값:

export STAGE6_TOPOLOGY=worker

export MINIO_ENDPOINT=https://<aistor-endpoint>:9000
export MINIO_ACCESS_KEY='...'
export MINIO_SECRET_KEY='...'

필요하면 bucket/object도 설정합니다.

실행:

./stage6e_clustermesh_minio_coldload.sh

worker profile에서는 ClusterMesh Global Service가 아니라:

GPU Worker/Pod
      │
 Service Network
      │
 TLS
      ▼
AIStor / MinIO

경로를 검증합니다.

추천: AIStor 사용 예정이므로 필수에 가깝게 유지


17. vLLM Deployment를 여기서 올림

이제:

6c PASS
6a PASS
6b PASS
6e PASS

이면 GPU/container/network/storage 기반이 어느 정도 검증된 것입니다.

그다음 vLLM Deployment를 올립니다.

반드시 기록할 값은:

model checkpoint
TP=8
dtype
quantization
max-model-len
max-num-seqs
gpu-memory-utilization
prefix caching ON/OFF
KV tier
CPU/memory request/limit

입니다.

Stage3a와 비교하려면 이 값이 같아야 합니다.


18. Stage6k — 핵심 vLLM 재검증

공통 변수:

export STAGE6_TOPOLOGY=worker

export NAMESPACE=gpu-validation

export VLLM_DEPLOYMENT=llama70b
export VLLM_SERVICE=llama70b

export MODEL_NAME=llama-3.1-70b

export TOKENIZER_PATH=/mnt/local-nvme-cache/models/\
Meta-Llama-3.1-70B-Instruct

export STAGE3_BASELINE_DIR=/var/log/b300_validation/\
stage3a_xxx

처음에는 한 번에 전부 하지 말고 이렇게 나누는 것을 권합니다.

1차

export STAGE6K_TESTS=basic

./stage6k_k8s_vllm_performance_revalidation.sh

PASS 후:

export STAGE6K_TESTS=mixed

./stage6k_k8s_vllm_performance_revalidation.sh

그다음:

export STAGE6K_TESTS=saturation
export SATURATION_MAX_CONCURRENCY=2048

./stage6k_k8s_vllm_performance_revalidation.sh

이 세 가지가 Stage6 vLLM core입니다.


19. Prefix는 별도로

Prefix Cache가 활성화된 Deployment에서:

export STAGE6K_TESTS=prefix

export PREFIX_TARGET_TOKENS=32000
export PREFIX_WARM_REQUESTS=6

./stage6k_k8s_vllm_performance_revalidation.sh

를 실행합니다.

여기서:

prefix_cache_queries delta
prefix_cache_hits delta
observed hit rate
cold TTFT
warm TTFT

를 봅니다.

추천: 필수

단, Prefix Cache ON 상태인지 먼저 확인해야 합니다.


20. KV tier는 조건부

실제 KV tier 구성을 사용할 때만 실행하면 됩니다.

예:

export STAGE6K_TESTS=kv

export STAGE6K_KV_ENDPOINTS='none=10.0.0.11:8000,local_nvme=10.0.0.12:8000,remote_object=10.0.0.13:8000,memkv_tcp=10.0.0.14:8000'

./stage6k_k8s_vllm_performance_revalidation.sh

하지만 현재 production 구성이 아직 확정되지 않았다면 Stage6 initial acceptance에서는 빼도 됩니다.

특히 MemKV는 native MemKV deployment가 실제 준비됐을 때 추가하면 됩니다.


21. Stage6h — NetworkPolicy

vLLM 서비스가 정상인 것을 확인한 뒤 실행합니다.

필요 값 예:

export NAMESPACE=gpu-validation

export VLLM_SELECTOR_LABEL='app=vllm-server'

export VLLM_SERVICE='llama70b.gpu-validation.svc.cluster.local'

실행:

./stage6h_network_policy_validation.sh

검증:

허용된 client
   ↓
200 OK

허용되지 않은 client
   ↓
BLOCK

추천: 필수


22. Stage6i — Hubble

Cilium/Hubble을 실제 운영에서 사용할 것이므로 실행하는 것이 좋습니다.

export STAGE6_TOPOLOGY=worker

./stage6i_hubble_observability_check.sh

현재 worker 환경에서는:

GPU Pod
 ↕
K8s Service
 ↕
Client Pod

flow가 Hubble에서 보이는지를 확인하면 됩니다.

추천: 필수


23. Stage6f — Resilience

이건 마지막에 하세요.

export GATEWAY_URL=http://<vllm-service-or-gateway>/v1/chat/completions

후:

./stage6f_k8s_resilience_test.sh

현재 GPU node가 한 대이고 TP8이면:

Node drain
   ↓
GPU 8장 사라짐
   ↓
vLLM TP8 이동할 곳 없음
   ↓
서비스 중단

이 정상입니다.

따라서 지금 6f의 목적은 HA PASS가 아니라 failure behavior와 recovery time 측정입니다.

추천: 수행하되 가장 마지막


24. 지금 빼도 되는 것

현재 환경 기준으로는 저는 다음을 initial Stage6에서 빼겠습니다.

Step현재 권장이유
6a NCCL필수TP8 container 검증
6b Network필수Pod/network 검증
6c Topology필수GPU Operator/topology
6d Spark Burst제외GPU HW/vLLM acceptance 핵심 아님
6e AIStor필수실제 storage path
6f Resilience마지막single GPU node라 HA 불가
6g ClusterMesh Partition제외현재 worker topology
6h NetworkPolicy필수production security
6i Hubble권장/필수운영 observability
6j Contention2차기본 성능 확인 후 필요
6k vLLM필수Stage3a K8s 재검증

25. 그래서 실제 추천 실행 순서는

현재 환경에서는 아래 정도가 가장 효율적입니다.

[Preflight]

GPU Node label
     ↓
kubelet CPU/Topology policy
     ↓
GPU Operator
     ↓
nvidia.com/gpu = 8
     ↓
GPU 1 Pod smoke
     ↓
GPU 8 Pod smoke
     ↓
DCGM Exporter
     ↓
Cilium/Hubble
     ↓

[Infrastructure qualification]

6c  GPU Topology
     ↓
6a  NCCL TP8
     ↓
6b  Network
     ↓
6e  AIStor
     ↓

[Serving]

vLLM Deployment
     ↓
6k-basic
     ↓
6k-mixed
     ↓
6k-saturation
     ↓
6k-prefix
     ↓

[Operational]

6h NetworkPolicy
     ↓
6i Hubble
     ↓

[Optional]

6j contention
     ↓
6k-kv
     ↓

[Destructive / Last]

6f resilience

─────────────────

6d Spark burst       SKIP
6g ClusterMesh       N/A

즉 6c → 6a → 6b → 6e → 6k → 6h → 6i → 필요 시 6j/KV → 마지막 6f를 현재 환경의 추천 core flow로 보면 됩니다.

한 가지 중요한 점은, 현재 Stage6 package의 변수명이 과거 버전에서 조금씩 발전하면서 GPU_NODE_SELECTOR_VALUE, NODE_SELECTOR_VALUE처럼 step별 차이가 남아 있습니다. 다음 정리 때는 stage6_profile.sh 하나에 GPU_NODE_NAME, GPU_NODE_SELECTOR, NAMESPACE, VLLM_SERVICE, AIStor endpoint 등을 모으고 모든 6a~6k가 동일 변수를 source하도록 통일하는 게 좋습니다. 그러면 실제 실행 때 매번 export해야 하는 값이 크게 줄어듭니다.

profile
engineer

0개의 댓글