네. 이번에는 현재 실제 구축 대상을 기준으로 꽤 구체적으로 잡는 게 좋습니다.
기준 환경을 다음처럼 고정하겠습니다.
Kubernetes 1.33
Node OS RHEL 10.2
GPU NVIDIA B300 x 8
GPU Node Bare-metal
NIC Intel E810
NIC driver ice
RDMA driver irdma
Network bond0 / bond1
bond0 External
bond1 K8s internal + RoCEv2
CNI Cilium
GPU Operator 26.7.0
Container Runtime containerd
Storage 별도 K8s cluster의 MinIO AIStor
Network Operator 현재는 설치하지 않음
현재 NVIDIA 공식 문서상 GPU Operator 26.7은 RHEL 10.0/10.1/10.2 + Kubernetes 1.33~1.36을 지원하고, DGX/HGX B300도 지원 GPU 목록에 포함됩니다. 따라서 OS/K8s/GPU 조합 자체는 공식 지원 범위입니다. (NVIDIA Docs)
그리고 중요한 전제 하나:
Intel E810은 GPU Operator가 관리하는 NIC가 아닙니다.
따라서 이번 설치에서 GPU Operator = GPU software stack, ice/irdma = OS/network stack으로 명확히 분리하는 것을 권장합니다.
최종적으로 GPU node는 다음과 같은 구조가 됩니다.
GPU Node
RHEL 10.2 / K8s 1.33
│
┌────────────────┴────────────────┐
│ │
NVIDIA GPU Stack Intel Network Stack
│ │
GPU Operator 26.7 E810
│ │
┌─────┼──────────────┐ ice
│ │ │ irdma
Driver Toolkit Device Plugin │
│ │ │ │
│ CDI │ │
│ │ │
DCGM/DCGM Exporter │ RDMA subsystem
│ │ │
└──────────┬─────────┘ │
│ │
B300 x 8 │
│ │
└──────────────┬───────────┘
│
bond1
│
Cilium + RoCEv2
│
▼
AIStor
그리고 NVIDIA Network Operator는 현재 E810 환경에서는 넣지 않습니다.
GPU Operator 26.7에는 두 가지 방법이 있습니다.
GPU Operator
↓
ClusterPolicy
↓
Driver DaemonSet
GPU Operator
↓
NVIDIADriver CR
↓
Driver
26.7에서는 NVIDIADriver CRD를 사용할 수 있고, 특정 node label을 기준으로 서로 다른 driver type/version을 관리할 수도 있습니다. (NVIDIA Docs)
GPU node가 처음에는 1대이고 B300 x8이라는 homogeneous GPU node라면:
일단 ClusterPolicy + Operator-managed driver
가 가장 단순합니다.
나중에 GPU node가 늘어나고 driver version을 node group별로 분리해야 할 필요가 생기면 NVIDIADriver CRD로 전환/확장하는 것이 좋습니다.
저라면 실제 작업을 다음 순서로 진행합니다.
STEP 0 Hardware 확인
STEP 1 RHEL 확인
STEP 2 Kernel 확인
STEP 3 containerd 확인
STEP 4 Kubernetes/Kubespray 확인
STEP 5 Cilium 확인
STEP 6 E810/ice/irdma 확인
STEP 7 bond1 확인
STEP 8 RDMA subsystem 확인
STEP 9 B300 PCIe/NVLink/NVSwitch 확인
STEP 10 BIOS 확인
STEP 11 IOMMU/NUMA 확인
STEP 12 OS package/repository 확인
STEP 13 Air-gap image/package 준비
STEP 14 Node label/taint
STEP 15 GPU Operator 설치
STEP 16 Driver 확인
STEP 17 GPU device plugin 확인
STEP 18 CDI 확인
STEP 19 CUDA test
STEP 20 DCGM/Prometheus 확인
STEP 21 RDMA device plugin
STEP 22 RDMA test
GPU node에서 가장 먼저:
hostnamectl
dmidecode -t system
dmidecode -t baseboard
dmidecode -t processor
CPU:
lscpu
numactl -H
PCIe:
lspci -nn
lspci -tv
GPU만:
lspci -nn | grep -i nvidia
NIC:
lspci -nn | grep -Ei 'ethernet|network'
E810:
lspci -nn | grep -i 'Intel.*Ethernet'
8-GPU node라면 단순히:
nvidia-smi
만 확인하면 안 됩니다.
반드시:
nvidia-smi topo -m
를 확인하세요.
예를 들어:
GPU0 GPU1 GPU2 GPU3 GPU4 GPU5 GPU6 GPU7 NIC0
GPU0 X NV NV NV SYS ...
...
NIC0 ...
여기서 NIC가 어느 GPU와 PCIe/NUMA locality를 가지는지가 나중의 GPUDirect RDMA 성능에 매우 중요합니다.
추가:
nvidia-smi topo -m
nvidia-smi -q -i 0
8장 모두:
for i in {0..7}; do
echo "===== GPU $i ====="
nvidia-smi -i $i --query-gpu=name,pci.bus_id,uuid,memory.total --format=csv
done
여기서 한 가지 중요합니다.
사용자가 말한 "B300 8장"이 일반적인 PCIe GPU 8장이 아니라 HGX B300 8-GPU platform이라면 NVSwitch/NVLink topology가 추가됩니다.
확인:
nvidia-smi -q | grep -Ei 'NVSwitch|NVLink'
그리고:
nvidia-smi topo -m
에서 NVLink/NVSwitch 구조를 기록합니다.
이 경우 GPU Operator 설치 자체는 크게 달라지지 않지만, GPU-to-GPU 성능 테스트는 별도의 NVLink/NVSwitch validation이 필요합니다.
cat /etc/redhat-release
cat /etc/os-release
uname -r
uname -m
예상:
Red Hat Enterprise Linux 10.2
x86_64
NVIDIA 공식 support matrix에서 RHEL 10.2 + Kubernetes 1.33은 지원됩니다. (NVIDIA Docs)
uname -r
rpm -q kernel
rpm -q kernel-core
rpm -q kernel-devel
rpm -q kernel-headers
현재 실행 중 kernel과 development package가 일치해야 합니다.
KVER=$(uname -r)
rpm -q kernel-devel-${KVER}
rpm -q kernel-headers-${KVER}
여기서 실패하면 GPU Operator driver 설치 전에 해결합니다.
GPU driver container가 host kernel module을 build해야 할 경우 중요합니다.
gcc --version
rpm -q gcc
그리고:
rpm -q kernel-devel
rpm -q kernel-headers
RHEL air-gapped 환경에서는 NVIDIA driver container가 필요한 OS package를 가져올 수 있도록 local repository를 준비해야 합니다. NVIDIA 문서가 RHEL 계열에서 필요한 주요 패키지로 kernel-headers, kernel-devel, kernel-core, gcc를 명시합니다. (NVIDIA Docs)
이건 이번에 반드시 확인해야 합니다.
containerd --version
그리고:
crictl info | jq '.config.containerdEndpoint // .config'
Kubelet:
ps -ef | grep kubelet
GPU Operator 26.7의 공식 지원 runtime 표는 containerd 2.0~2.3을 대상으로 합니다. (NVIDIA Docs)
따라서 만약:
containerd 1.7.x
이면 저는 GPU Operator 설치를 바로 진행하지 않고 containerd부터 정리하겠습니다.
특히 현재 Kubespray에서 containerd 1.x를 사용 중이라면 이 부분이 가장 먼저 확인할 항목입니다.
설치 전:
cp -a /etc/containerd/config.toml \
/etc/containerd/config.toml.$(date +%Y%m%d)
확인:
containerd config dump | less
그리고 GPU Operator 26.7에서는 CDI가 기본 활성화됩니다. CDI가 container runtime의 native CDI support를 통해 GPU를 container에 주입하는 구조입니다. (NVIDIA Docs)
따라서 containerd의 CDI 관련 동작도 확인해야 합니다.
GPU Operator 26.7에서는 NRI plugin도 지원하지만 NVIDIA 문서상 아직 GA가 아니고 production 사용을 권장하지 않습니다. (NVIDIA Docs)
따라서:
cdi:
enabled: true
nriPluginEnabled: false
방향을 권장합니다.
즉:
CDI ON
NRI OFF
kubectl version
Node:
kubectl get nodes -o wide
GPU node가 추가된 후:
kubectl get node <gpu-node> --show-labels
그리고:
kubectl describe node <gpu-node>
에서:
OS Image
Kernel Version
Container Runtime
Kubelet Version
Capacity
Allocatable
을 기록합니다.
Kubespray inventory에서 GPU node가 기존 cluster에 정상적으로 들어갔는지 확인합니다.
특히:
container_manager
kube_version
kubelet_config_extra_args
그리고 GPU node에만 적용되는 host configuration이 있는지 확인합니다.
가능하면 GPU node를:
gpu_workers
같은 별도 inventory group으로 관리하세요.
예:
[all]
...
gpu01
[kube_node]
...
gpu01
[gpu_workers]
gpu01
향후:
gpu01
gpu02
gpu03
...
확장이 편해집니다.
현재 Cilium을 사용하므로:
cilium status
또는:
kubectl -n kube-system get pods -l k8s-app=cilium -o wide
Cilium version:
cilium version
확인합니다.
그리고 GPU node에서 Cilium agent가 정상인지:
kubectl -n kube-system get pod \
-l k8s-app=cilium \
-o wide | grep <gpu-node>
cat /proc/net/bonding/bond0
cat /proc/net/bonding/bond1
특히 bond1:
cat /proc/net/bonding/bond1
에서:
Bonding Mode
802.3ad
LACP rate
MII Status
Slave Interface
Aggregator ID
Actor Key
Partner Key
을 기록합니다.
사용자가 말한 것처럼 LACP active-active라면 RDMA와 bonding의 compatibility를 별도로 검증해야 합니다.
인터페이스 이름:
ip -br link
예:
eno1
eno2
bond0
bond1
E810 확인:
ethtool -i <e810-port>
중요:
driver: ice
firmware-version:
bus-info:
확인.
modinfo ice | head -30
lsmod | grep '^ice'
필요하면:
modprobe ice
modinfo irdma | head -30
lsmod | grep irdma
로드:
modprobe irdma
확인:
lsmod | grep -E 'ice|irdma'
패키지:
rpm -qa | grep -E 'rdma|libibverbs|perftest'
서비스:
systemctl status rdma
장치:
rdma link
rdma dev
ibv_devices
ibv_devinfo
정상이라면 E810의 RDMA device가 보여야 합니다.
GPU Operator 설치 전에 RDMA가 먼저 정상이어야 합니다.
즉:
GPU Operator
X
먼저
RHEL
└─ ice
└─ irdma
└─ RDMA device
가 정상이어야 합니다.
왜냐하면 GPU Operator가 실패한 것인지 E810 RDMA가 원래 안 되는 것인지 분리해야 하기 때문입니다.
가능하다면 E810이 연결된 다른 RDMA node와:
ib_write_bw
를 수행합니다.
예:
Server:
ib_write_bw -d <rdma_device>
Client:
ib_write_bw -d <rdma_device> <server-ip>
이 단계에서 PASS해야 합니다.
8-GPU B300 node에서는 BIOS 설정도 상당히 중요합니다.
확인 대상:
Above 4G Decoding
Resizable BAR
SR-IOV
IOMMU
NUMA
PCIe Link Speed
PCIe ASPM
CPU C-states
특히 GPU가 8장인 경우:
Above 4G Decoding = Enabled
는 사실상 필수로 보는 것이 좋습니다.
확인:
cat /proc/cmdline
그리고:
dmesg | grep -Ei 'iommu|DMAR'
BIOS에서 IOMMU가 필요한 architecture인지 확인합니다.
GPUDirect RDMA/PCIe device isolation을 고려한다면 이 부분을 나중에 바꾸지 말고 처음부터 표준화하는 것을 추천합니다.
numactl -H
그리고:
lspci -vv -s <GPU-PCI-address>
lspci -vv -s <E810-PCI-address>
NUMA node:
cat /sys/bus/pci/devices/<PCI>/numa_node
GPU 8장과 NIC의 NUMA 관계를 기록합니다.
GPU Operator가 driver를 관리할 것이므로 host에 NVIDIA driver를 미리 설치하지 않는 것을 권장합니다.
확인:
rpm -qa | grep -i nvidia
그리고:
lsmod | grep nvidia
만약 이미 설치되어 있다면 먼저 정리 여부를 결정해야 합니다.
현재 계획:
Host
├─ ice
├─ irdma
└─ NVIDIA driver 없음
GPU Operator
└─ NVIDIA driver 관리
입니다.
NVIDIA 공식 설치 문서도 기본 설치에서는 GPU Operator가 driver container, Container Toolkit, Device Plugin, DCGM Exporter 등을 배포한다고 설명합니다. (NVIDIA Docs)
GPU Operator 26.7의 기본값은:
driver.kernelModuleType: auto
입니다.
가능한 값:
auto
open
proprietary
NVIDIA 문서상 auto는 GPU와 driver branch에 따라 권장 kernel module type을 선택합니다. (NVIDIA Docs)
B300/Blackwell 계열에서는 저는 일단 auto를 사용하겠습니다.
즉:
--set driver.kernelModuleType=auto
또는 아예 기본값을 사용합니다.
GPU Operator 26.7 component matrix에는:
NVIDIA GPU Driver
610.57.04
595.91.07 (Recommended/Default)
580.173.02
535.309.01
등이 표시됩니다. (NVIDIA Docs)
또한 NVIDIA의 최신 driver 설치 문서에서는 RHEL 10에서 nvidia-open 패키지를 지원하고 있습니다. (NVIDIA Docs)
그리고 GPU Operator 26.7의 GDS driver 2.29.4는 Open GPU Kernel module driver가 필요합니다. (NVIDIA Docs)
따라서 향후:
GPUDirect RDMA
GPUDirect Storage
GDS
까지 고려한다면 open kernel module 기반을 우선 검토할 가치가 있습니다.
다만 현재 POC에서는 auto로 시작하는 것이 안전합니다.
사용자 환경이 air-gapped이므로 이 부분은 상당히 중요합니다.
GPU Operator는 기본적으로:
K8s node
↓
GPU Operator images
↓
local registry
Driver container
↓
RHEL packages
↓
local package repository
두 가지가 필요합니다.
NVIDIA 공식 air-gapped 문서도 이 두 가지를 명확히 요구합니다. (NVIDIA Docs)
GPU Operator 26.7의 주요 component:
gpu-operator
driver
container-toolkit
k8s-device-plugin
dcgm
dcgm-exporter
gpu-feature-discovery
mig-manager
validator
nfd
정확한 image/tag는 반드시:
helm show values nvidia/gpu-operator \
--version=v26.7.0
와 component matrix를 기준으로 mirror합니다.
26.7의 주요 component version은:
Driver 595.91.07 default/recommended
Container Toolkit 1.20.0
Device Plugin 0.20.0
DCGM Exporter 4.6.0-4.8.3
NFD 0.19.0
GFD 0.20.0
MIG Manager 0.15.0
DCGM 4.6.0-1
입니다. (NVIDIA Docs)
Driver image는 OS에 따라 tag가 붙습니다.
NVIDIA 문서에서 26.7부터 conventional RHEL/Rocky driver image tag를 OS major version 기반으로 구성하는 방식으로 변경되었습니다. 예를 들어 RHEL 10이면 rhel10 계열을 사용합니다. (NVIDIA Docs)
즉 RHEL 10.2라고 해서:
driver:595....-rhel10.2
식으로 생각하면 안 되고, 26.7에서는 OS major version tag 규칙을 적용해야 합니다.
이 부분은 기존 26.3 기준 작업계획과 달라진 중요한 부분입니다.
Driver container가 필요한 경우 최소한 RHEL node의:
kernel-headers
kernel-devel
kernel-core
gcc
가 local repository에서 접근 가능해야 합니다. (NVIDIA Docs)
확인:
dnf repolist
그리고:
dnf list installed kernel-devel
dnf list installed kernel-headers
dnf list installed gcc
air-gap이라면:
RHEL 10.2 repository
↓
internal Nexus/Repo
↓
GPU node
구조를 만드는 것이 좋습니다.
여기서 선택지가 있습니다.
GPU Operator
↓
driver container
↓
host kernel headers
↓
driver build
GPU Operator
↓
precompiled driver
↓
host kernel에 맞는 image
air-gapped 환경에서는 precompiled driver를 사용할 수 있으면 운영 복잡도가 크게 줄어듭니다.
NVIDIA 문서도 precompiled driver container를 사용하면 driver container가 OS package를 다운로드할 필요가 없어 local package repository가 필요하지 않게 된다고 설명합니다. (NVIDIA Docs)
다만 RHEL 10.2 + 실제 kernel + B300 + 선택 driver branch에 대해 precompiled image가 정확히 제공되는지 확인 후 결정해야 합니다.
GPU node를 일반 workload와 분리합니다.
예:
kubectl label node <gpu-node> \
accelerator=nvidia-b300
그리고:
kubectl label node <gpu-node> \
gpu=true
확인:
kubectl get node <gpu-node> --show-labels
GPU node를 GPU workload 전용으로 쓸 예정이라면:
kubectl taint nodes <gpu-node> \
nvidia.com/gpu=true:NoSchedule
그러면 GPU workload만 toleration을 넣어 들어오게 할 수 있습니다.
단, GPU Operator의 DaemonSet들은 해당 taint를 tolerate하도록 구성되는지 확인해야 합니다.
처음에는 taint 없이 설치하고 정상화한 뒤 taint를 적용하는 방법도 좋습니다.
먼저 Helm:
helm version
repo:
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update
chart 확인:
helm show chart nvidia/gpu-operator \
--version=v26.7.0
values:
helm show values nvidia/gpu-operator \
--version=v26.7.0 > gpu-operator-26.7-values.yaml
현재 환경에서는 다음과 같은 방향을 권장합니다.
helm upgrade --install gpu-operator \
nvidia/gpu-operator \
--version=v26.7.0 \
--namespace gpu-operator \
--create-namespace \
--set driver.kernelModuleType=auto \
--set cdi.enabled=true \
--set cdi.nriPluginEnabled=false \
--set dcgmExporter.enabled=true
실제 air-gapped 환경에서는 여기에 internal registry/repository 설정이 추가됩니다.
GPU Operator 26.7은 CDI가 기본적으로 활성화되어 있습니다.
CDI를 이용하면:
Kubernetes workload
↓
container runtime
↓
CDI specification
↓
GPU device
로 GPU injection을 처리합니다.
NVIDIA 문서도 26.7에서 CDI가 기본/권장 방식이며 native CDI를 사용하는 runtime을 활용한다고 명시합니다. (NVIDIA Docs)
따라서 특별한 이유가 없다면:
CDI를 끄지 마세요.
cdi:
enabled: true
nriPluginEnabled: false
NRI는 아직 GA가 아니므로 production 환경에서는 일단 사용하지 않는 것을 권장합니다. (NVIDIA Docs)
kubectl get pods -n gpu-operator -o wide
정상적으로는 대략:
gpu-operator
nvidia-driver-daemonset
nvidia-container-toolkit-daemonset
nvidia-device-plugin-daemonset
nvidia-dcgm-exporter
gpu-feature-discovery
node-feature-discovery
nvidia-operator-validator
nvidia-cuda-validator
등이 나타납니다.
NVIDIA 공식 26.7 verification 예제에서도 이와 같은 operand들이 Running이고 CUDA validator는 Completed 상태인 것을 정상으로 봅니다. (NVIDIA Docs)
kubectl get clusterpolicy
정상:
NAME STATUS
cluster-policy ready
상세:
kubectl describe clusterpolicy cluster-policy
kubectl get pods \
-n gpu-operator \
-o wide
그리고:
kubectl get ds -n gpu-operator
kubectl get deploy -n gpu-operator
GPU node에서:
lsmod | grep nvidia
그리고:
nvidia-smi
가장 중요합니다.
정상이라면:
+-----------------------------------------------------------------------------+
| NVIDIA-SMI ...
| GPU Name ...
| 0 B300
| 1 B300
| ...
| 7 B300
+-----------------------------------------------------------------------------+
즉:
8/8 GPU가 보여야 합니다.
nvidia-smi --list-gpus
그리고:
nvidia-smi \
--query-gpu=index,name,pci.bus_id,uuid,memory.total \
--format=csv
정확히 8개인지 확인합니다.
nvidia-smi -q
여기서:
Product Name
GPU UUID
PCI
Firmware
Driver Version
CUDA Version
Power
Temperature
ECC
MIG
등을 확인합니다.
B300 8장을 production에 넣는다면 이 출력은 설치 완료 증적으로 저장해두는 것을 추천합니다.
B300의 workload 설계에 따라 MIG를 사용할 수도 있지만 vLLM에서 8개 GPU를 full GPU로 사용하는 것이 목표라면 처음에는 MIG를 건드리지 않는 것을 추천합니다.
확인:
nvidia-smi -L
그리고:
nvidia-smi mig -lgi
현재 MIG mode가 어떻게 되어 있는지 기록합니다.
kubectl get node <gpu-node> \
-o jsonpath='{.status.capacity.nvidia\.com/gpu}{"\n"}'
예상:
8
allocatable:
kubectl get node <gpu-node> \
-o jsonpath='{.status.allocatable.nvidia\.com/gpu}{"\n"}'
역시:
8
이어야 합니다.
NVIDIA 공식 verification에서도 nvidia.com/gpu allocatable 값이 물리 GPU 수와 일치하는지를 확인하도록 합니다. (NVIDIA Docs)
kubectl get node <gpu-node> --show-labels
NVIDIA 관련:
kubectl get node <gpu-node> -o json \
| jq '.metadata.labels | with_entries(select(.key | startswith("nvidia.com/")))'
여기서:
nvidia.com/gpu
nvidia.com/gpu.product
nvidia.com/gpu.memory
nvidia.com/cuda.*
등의 정보를 확인합니다.
GPU Operator pod:
kubectl get pods -n gpu-operator | grep toolkit
node에서:
ls -l /var/run/cdi/
또는:
find /var/run/cdi -type f -maxdepth 1 -print
CDI spec이 생성되어 있어야 합니다.
가능하면:
nvidia-ctk cdi list
도 확인합니다.
예상되는 NVIDIA CDI device가 나와야 합니다.
가장 중요한 실제 test입니다.
간단한 CUDA image를 사용해서:
kubectl run gpu-test \
--rm -it \
--restart=Never \
--image=<internal-cuda-image> \
--limits='nvidia.com/gpu=1' \
-- nvidia-smi
air-gap이면 내부 registry의 CUDA image를 사용해야 합니다.
정상:
CUDA container
↓
nvidia-smi
↓
B300 visible
Pod 하나에:
resources:
limits:
nvidia.com/gpu: 8
를 요청해 실제 8 GPU가 한 pod에 모두 전달되는지 테스트합니다.
컨테이너 내부:
nvidia-smi -L
8개가 보여야 합니다.
이것은 향후 vLLM 8-GPU deployment의 기본 validation입니다.
단순 nvidia-smi만으로는 부족합니다.
CUDA sample 또는 PyTorch container에서:
import torch
print(torch.cuda.is_available())
print(torch.cuda.device_count())
for i in range(torch.cuda.device_count()):
print(i, torch.cuda.get_device_name(i))
예상:
True
8
B300
B300
...
PyTorch:
import torch
for i in range(8):
x = torch.randn((4096,4096), device=f"cuda:{i}")
y = x @ x
torch.cuda.synchronize(i)
print(i, y.mean().item())
목적은:
모든 GPU가 실제 CUDA context를 만들고 연산 가능한가?
입니다.
8 GPU 시스템에서는 반드시 해야 합니다.
nvidia-smi topo -p2p r
nvidia-smi topo -p2p w
그리고 CUDA P2P sample 또는 NCCL test를 수행합니다.
특히 vLLM을 8 GPU로 운영한다면 NCCL test는 GPU Operator 기본 validation보다 훨씬 중요합니다.
예:
all_reduce_perf \
-b 8 \
-e 1G \
-f 2 \
-g 8
결과:
NCCL
GPU ↔ GPU
NVLink/NVSwitch
가 정상인지 확인합니다.
kubectl get pods -n gpu-operator \
| grep dcgm
Exporter:
kubectl get pods -n gpu-operator \
| grep exporter
DCGM Exporter 기본 port는:
9400
입니다.
NVIDIA DCGM 문서도 exporter의 /metrics에서 DCGM_ 계열 metric이 나오는 것을 확인하도록 안내합니다. (NVIDIA Docs)
kubectl port-forward \
-n gpu-operator \
svc/nvidia-dcgm-exporter 9400:9400
다른 terminal:
curl http://127.0.0.1:9400/metrics
그리고:
curl -s http://127.0.0.1:9400/metrics \
| grep '^DCGM_' \
| head
사용자가 기존 Prometheus를 사용하고 있으므로 여기서는:
GPU Node
↓
DCGM Exporter :9400
↓
Prometheus
↓
Grafana
로 연결합니다.
처음부터 모든 DCGM metric을 가져오기보다:
GPU utilization
GPU memory
GPU power
GPU temperature
PCIe TX/RX
NVLink
ECC
XID
위주로 가져오는 것을 추천합니다.
GPU 장애에서 매우 중요한 metric/log입니다.
노드:
dmesg | grep -i xid
그리고:
journalctl -k | grep -i xid
정상 설치 후:
GPU XID error = 0
을 baseline으로 만들어 놓으세요.
kubectl get pods -n gpu-operator \
| grep validator
상세:
kubectl logs -n gpu-operator \
<validator-pod>
Validator가 실패하면 application test로 넘어가면 안 됩니다.
저라면 다음 조건을 모두 만족해야 GPU Operator installation PASS로 판정합니다.
[PASS]
RHEL 10.2
K8s 1.33
containerd supported version
↓
B300 x8 detected
↓
NVIDIA driver loaded
↓
nvidia-smi = 8 GPU
↓
nvidia.com/gpu = 8
↓
CDI functional
↓
CUDA container functional
↓
GPU Operator validator PASS
↓
DCGM exporter functional
↓
Prometheus scraping
↓
NCCL 8-GPU test PASS
여기부터는 GPU Operator와 별도 layer입니다.
현재:
GPU Operator
│
└── B300
Intel E810
│
ice
│
irdma
│
RDMA subsystem
입니다.
GPU Operator의:
driver.rdma.enabled
는 NVIDIA driver-side GPUDirect RDMA integration에 관한 설정입니다.
NVIDIADriver CRD에서도:
rdma:
enabled: false
가 기본값입니다. (NVIDIA Docs)
하지만 이것을:
rdma.enabled=true
한다고 해서:
Intel E810
+
ice
+
irdma
가 설치되는 것이 아닙니다.
따라서 현재는 그 설정을 섣불리 켜지 않는 것을 권장합니다.
그 다음 단계가:
Host
irdma
↓
RDMA device
↓
RDMA Device Plugin
↓
Kubernetes resource
↓
Pod
입니다.
여기서 Intel E810을 사용하는 만큼 NVIDIA Network Operator의 RDMA Shared Device Plugin을 그대로 적용하지 말고, Intel E810에서 사용할 generic/community RDMA device plugin을 검증해서 선택하는 것이 좋습니다.
이 부분은 GPU Operator 설치와 별도입니다.
최종적으로:
kubectl describe node <gpu-node>
에서 RDMA 관련 resource가 노출되고,
테스트 pod에서 RDMA device가 보이는지:
ls -l /dev/infiniband/
확인합니다.
RoCE는 InfiniBand가 아니지만 Linux RDMA subsystem은 /dev/infiniband/* 인터페이스를 사용할 수 있습니다.
반드시:
1. Host RDMA
↓
2. Pod RDMA
↓
3. Host ↔ Host
↓
4. Pod ↔ Pod
↓
5. RoCEv2
↓
6. PFC/ECN
↓
7. GPU memory RDMA
순서로 가세요.
처음부터 GPUDirect를 테스트하면 원인 분리가 안 됩니다.
ethtool -i <e810>
ethtool -k <e810>
ethtool -S <e810>
특히:
rx_errors
tx_errors
rx_dropped
tx_dropped
pause
ecn
등의 NIC counters를 benchmark 시작 전에 저장합니다.
rdma link
그리고:
rdma system show
필요하면:
rdma dev show
E810 RDMA device와 Ethernet interface mapping을 기록합니다.
현재 architecture가:
bond1
LACP
/ \
E810 port1 E810 port2
라면 일반 IP traffic이 정상인 것만으로 RDMA/LAG가 정상이라고 판단하면 안 됩니다.
따라서:
TCP over bond1
vs
RDMA over bond1
를 각각 측정합니다.
초기 installation에서는:
PFC/ECN을 먼저 변경하지 않는 것
을 권장합니다.
순서는:
GPU Operator
↓
RDMA
↓
RoCEv2 basic
↓
Baseline
↓
PFC/ECN
↓
성능 비교
입니다.
이렇게 해야 PFC configuration 문제가 GPU/RDMA 문제와 섞이지 않습니다.
제가 실제 운영 인수 checklist를 만든다면 다음처럼 합니다.
cat /etc/redhat-release
uname -r
containerd --version
crictl info
kubectl get node
kubectl describe node <gpu-node>
nvidia-smi
nvidia-smi -L
nvidia-smi topo -m
kubectl get node <gpu-node> \
-o jsonpath='{.status.allocatable.nvidia\.com/gpu}'
kubectl get clusterpolicy
kubectl get pods -n gpu-operator
nvidia-ctk cdi list
curl http://127.0.0.1:9400/metrics
ethtool -i <e810>
rdma link
ibv_devices
ibv_devinfo
cat /proc/net/bonding/bond1
cilium status
설치 전에:
mkdir -p /root/gpu-install-baseline
uname -a > /root/gpu-install-baseline/uname.txt
lscpu > /root/gpu-install-baseline/lscpu.txt
numactl -H > /root/gpu-install-baseline/numa.txt
lspci -nn > /root/gpu-install-baseline/lspci.txt
lspci -tv > /root/gpu-install-baseline/lspci-tree.txt
ip -br link > /root/gpu-install-baseline/ip.txt
cat /proc/net/bonding/bond1 > /root/gpu-install-baseline/bond1.txt
ethtool -i <e810> > /root/gpu-install-baseline/e810-driver.txt
lsmod > /root/gpu-install-baseline/modules.txt
GPU 설치 후:
nvidia-smi > /root/gpu-install-baseline/nvidia-smi.txt
nvidia-smi -q > /root/gpu-install-baseline/nvidia-smi-q.txt
nvidia-smi topo -m > /root/gpu-install-baseline/nvidia-topo.txt
K8s:
kubectl get nodes -o wide \
> /root/gpu-install-baseline/k8s-nodes.txt
kubectl get pods -A -o wide \
> /root/gpu-install-baseline/k8s-pods.txt
이렇게 해두면 나중에 장애가 발생했을 때 굉장히 유용합니다.
설치 완료 후 다음을 별도로 기록하세요.
nvidia-smi topo -m
nvidia-smi nvlink -s
nvidia-smi nvlink -e
nvidia-smi -q
그리고:
dmesg | grep -Ei 'NVRM|Xid|nvidia|nvlink'
정상 baseline에서는 XID가 없어야 합니다.
실제 엔지니어가 작업한다면 아래 순서 그대로 진행하겠습니다.
DAY 0 — Hardware / OS
① B300 x8 PCIe 확인
② E810 PCIe 확인
③ GPU/NIC NUMA 확인
④ BIOS 확인
⑤ RHEL 10.2 확인
⑥ kernel 확인
⑦ kernel-devel/header 확인
⑧ gcc 확인
⑨ containerd version 확인
⑩ Kubespray configuration 확인
↓
DAY 0 — Network
⑪ bond0 확인
⑫ bond1 확인
⑬ LACP 확인
⑭ E810 firmware 확인
⑮ ice 확인
⑯ irdma 확인
⑰ rdma link 확인
⑱ ibv_devinfo 확인
⑲ Host RDMA test
↓
DAY 1 — GPU Operator
⑳ Air-gap image mirror
㉑ RHEL package repository
㉒ GPU node label
㉓ GPU Operator 26.7 install
㉔ Driver install
㉕ CDI
㉖ Device Plugin
㉗ GFD/NFD
㉘ DCGM Exporter
↓
DAY 1 — GPU validation
㉙ nvidia-smi
㉚ 8 GPU 확인
㉛ CUDA container
㉜ PyTorch
㉝ GPU P2P
㉞ NCCL
㉟ DCGM
㊱ Prometheus
↓
DAY 2 — RDMA
㊲ RDMA device plugin
㊳ Pod RDMA
㊴ Pod ↔ Pod RDMA
㊵ RoCEv2
㊶ bond1 RDMA
㊷ PFC/ECN
↓
DAY 3 — GPUDirect
㊸ GPU-memory RDMA
㊹ DMA-BUF
㊺ GPUDirect RDMA
㊻ E810 limitation/support assessment
↓
DAY 4 — AIStor
㊼ TCP baseline
㊽ RoCE baseline
㊾ AIStor performance
㊿ vLLM
최종적으로는 아래 7개를 Go/No-Go gate로 두는 것을 추천합니다.
| Gate | 확인 | 목표 |
|---|---|---|
| G1 | RHEL 10.2 + K8s 1.33 + containerd | 공식/검증 조합 |
| G2 | B300 x8 | 8/8 GPU |
| G3 | CUDA/CDI | GPU workload 정상 |
| G4 | NCCL | 8-GPU communication 정상 |
| G5 | E810 + irdma | Host RDMA 정상 |
| G6 | RoCEv2 + bond1 | network RDMA 정상 |
| G7 | GPU-memory RDMA | GPUDirect 가능성 검증 |
그리고 G7은 별도로 "NVIDIA 공식 지원 여부"와 "실제 기술적으로 동작하는지"를 분리해서 기록해야 합니다.
NVIDIA 현재 문서의 GPUDirect RDMA 지원표는 RHEL 10.0 등을 특정 Network Operator 버전과 함께 명시하지만, Network Operator의 공식 지원 NIC ecosystem은 NVIDIA networking 제품 중심입니다. 따라서 Intel E810을 사용한 GPUDirect RDMA는 공식 지원 조합으로 간주하지 말고 별도 POC 결과로 판단하는 것이 안전합니다. (NVIDIA Docs)
처음 GPU node 1대를 추가하는 단계에서는 최대한 단순하게 시작하는 게 좋습니다.
RHEL 10.2
│
├── containerd 2.x
├── Cilium
├── bond0
│ └── external
│
└── bond1
├── K8s traffic
└── RoCEv2
│
Intel E810
├── ice
└── irdma
NVIDIA GPU Operator 26.7
├── NVIDIA Driver
├── Container Toolkit
├── CDI
├── Device Plugin
├── NFD/GFD
├── DCGM
├── DCGM Exporter
└── Validator
B300 x8
├── CUDA
├── PyTorch
├── NCCL
└── vLLM
별도 구성
└── RDMA Device Plugin
Network Operator 26.4.1 / Multus / RDMA CNI는 현재 단계에서 일단 넣지 않는 것을 권장합니다. Intel E810을 쓰는 상황에서는 오히려 host의 ice + irdma를 먼저 정상화하고, 이후 필요한 Pod-level RDMA isolation이 생길 때 추가하는 것이 훨씬 안전합니다.
그리고 GPU Operator 26.7의 CDI는 켜고, NRI는 끄고, driver는 Operator가 관리하며 kernelModuleType=auto로 시작하는 것이 현재 B300/RHEL 10.2 환경에서 가장 무난한 출발점입니다. (NVIDIA Docs)
특히 containerd가 현재 1.7이라면 여기서 바로 멈추고 containerd 2.x 문제부터 해결하는 것이 좋습니다. GPU Operator 26.7의 공식 runtime matrix가 containerd 2.0~2.3을 기준으로 하고 있기 때문입니다. (NVIDIA Docs)