AI- en GPU-workloads op Kubernetes: apparaatplug-ins en trainingstaken
In 2026 draait 66% van de AI-inferentieclusters op Kubernetes (CNCF Survey 2026). De reden Het is simpel: Kubernetes lost de moeilijkste operationele problemen van AI-workloads op: planning intelligente GPU-schaling, elastische schaling van trainingstaken, integratie met gedistribueerde opslag voor datasets: automatisch opnieuw proberen in geval van een knooppuntfout. Maar het opzetten van Kubernetes voor i GPU-werklast vereist specifieke vaardigheden die veel verder gaan dan de inzet van een normale webapplicatie.
In dit artikel zullen we zien hoe u de NVIDIA-apparaatplug-ins voor GPU's blootstellen aan het cluster, hoe u dit kunt plannen Gedistribueerde trainingsbanen met PyTorch en TensorFlow, hoe te gebruiken Karpenter om spotscaling uit te voeren GPU (waardoor de kosten met 40-70% worden verlaagd) en patronen om het GPU-gebruik in workloads te optimaliseren van gevolgtrekking naar de productie.
Wat je gaat leren
- Installatie en configuratie van de NVIDIA Device Plugin voor Kubernetes
- Pods plannen met GPU-vraag (nvidia.com/gpu-bron)
- Gedistribueerde training met PyTorchJob en TFJob (Kubeflow Training Operator)
- Karpenter NodePool voor automatische inrichting van spot-GPU-nodes
- GPU-time-slicing om GPU's te delen tussen meerdere pods
- MIG (Multi-Instance GPU) voor A100/H100 GPU-partitie
- GPU-monitoring met DCGM Exporter en Grafana
- Patroon voor inferentie met hoge doorvoer met TorchServe op K8s
GPU-architectuur op Kubernetes
Kubernetes is van nature niet op de hoogte van GPU's. GPU's worden blootgesteld aan het cluster via de Kader voor apparaatplug-ins: een DaemonSet die op elk knooppunt met GPU draait, registreert zich bij de kubelet en beheert de toewijzing van GPU's aan containers. De NVIDIA Device Plugin is de meest populaire implementatie van dit raamwerk.
NVIDIA-apparaatplug-in installeren
# Pre-requisiti: NVIDIA GPU drivers installati sui nodi
# Verifica driver sui nodi
kubectl get nodes -l accelerator=nvidia
kubectl describe node gpu-node-1 | grep -i nvidia
# Installa NVIDIA Device Plugin con Helm
helm repo add nvdp https://nvidia.github.io/k8s-device-plugin
helm repo update
helm install nvdp nvdp/nvidia-device-plugin \
--namespace kube-system \
--version 0.16.0 \
--set failOnInitError=false
# Oppure con manifest diretto
kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.16.0/deployments/static/nvidia-device-plugin.yml
# Verifica che le GPU siano visibili nel cluster
kubectl get nodes -o json | jq '.items[].status.allocatable | select(."nvidia.com/gpu" != null)'
# Output: { "nvidia.com/gpu": "8" } per un nodo con 8 GPU A100
NVIDIA GPU Operator installeren (aanbevolen aanpak)
Voor clusters in productie geldt de GPU-operator van NVIDIA beheert automatisch alle benodigde componenten: stuurprogramma's, apparaatplug-ins, containerruntime, DCGM-exporteur voor monitoring:
# Installa GPU Operator
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update
helm install gpu-operator nvidia/gpu-operator \
--namespace gpu-operator \
--create-namespace \
--version v24.9.0 \
--set driver.enabled=true \
--set mig.strategy=single \
--set dcgmExporter.enabled=true \
--set dcgmExporter.serviceMonitor.enabled=true
# Verifica installazione
kubectl get pods -n gpu-operator
# Attendi che tutti i pod siano Running
kubectl wait --for=condition=ready pod -l app=nvidia-device-plugin-daemonset -n gpu-operator --timeout=300s
# Verifica GPU allocabili
kubectl describe node gpu-node-1 | grep -A 5 "Allocatable:"
# nvidia.com/gpu: 8
Pods plannen met GPU
Zodra de Device Plugin actief is, kunt u GPU's aanvragen in manifesten zoals elk ander andere Kubernetes-bron. Het verschil: je gebruikt geen verzoeken, alleen limieten voor GPU's (Kubernetes garandeert altijd precies het aantal benodigde GPU's).
# pod-gpu-basic.yaml
apiVersion: v1
kind: Pod
metadata:
name: gpu-test
spec:
restartPolicy: OnFailure
containers:
- name: inference
image: nvcr.io/nvidia/pytorch:24.01-py3
command: ["python3", "-c"]
args:
- |
import torch
print(f"CUDA available: {torch.cuda.is_available()}")
print(f"GPU count: {torch.cuda.device_count()}")
print(f"GPU name: {torch.cuda.get_device_name(0)}")
x = torch.rand(1000, 1000).cuda()
print(f"Tensor on GPU: {x.device}")
resources:
limits:
nvidia.com/gpu: "1" # richiedi 1 GPU
memory: "16Gi"
cpu: "4"
requests:
memory: "16Gi"
cpu: "4"
volumeMounts:
- name: model-storage
mountPath: /models
volumes:
- name: model-storage
persistentVolumeClaim:
claimName: model-pvc
nodeSelector:
accelerator: "nvidia-a100" # schedule solo su nodi A100
tolerations:
- key: "nvidia.com/gpu"
operator: "Exists"
effect: "NoSchedule"
Training gedistribueerd met Kubeflow Training Operator
Voor het trainen van grote modellen zijn vaak meerdere GPU's op meerdere knooppunten vereist. De Kubeflow-trainingsoperator beheert gedistribueerde trainingsbanen met PyTorchJob, TFJob, MXJob en MPIJob. Installeer eerst de aandrijving:
# Installa Training Operator
kubectl apply -k "github.com/kubeflow/training-operator/manifests/overlays/standalone?ref=v1.8.0"
# Verifica
kubectl get pods -n kubeflow
kubectl get crd | grep kubeflow
PyTorchJob voor training met meerdere GPU's en meerdere knooppunten
# pytorch-distributed-training.yaml
apiVersion: kubeflow.org/v1
kind: PyTorchJob
metadata:
name: llm-finetuning-job
namespace: ml-training
spec:
pytorchReplicaSpecs:
Master:
replicas: 1
restartPolicy: OnFailure
template:
spec:
containers:
- name: pytorch
image: company.registry.io/training:llm-v2.1
command:
- python3
- -m
- torch.distributed.run
- --nproc_per_node=8
- --nnodes=4
- --node_rank=$(RANK)
- --master_addr=$(MASTER_ADDR)
- --master_port=23456
- train_llm.py
- --model=llama-7b
- --dataset=/data/training_set
- --batch-size=32
- --epochs=3
- --output=/models/finetuned
env:
- name: NCCL_DEBUG
value: "INFO"
- name: NCCL_SOCKET_IFNAME
value: "eth0"
resources:
limits:
nvidia.com/gpu: "8"
memory: "120Gi"
cpu: "32"
requests:
memory: "120Gi"
cpu: "32"
volumeMounts:
- name: training-data
mountPath: /data
- name: model-output
mountPath: /models
- name: shm
mountPath: /dev/shm
volumes:
- name: training-data
persistentVolumeClaim:
claimName: training-dataset-pvc
- name: model-output
persistentVolumeClaim:
claimName: model-output-pvc
- name: shm
emptyDir:
medium: Memory
sizeLimit: "64Gi" # shared memory per NCCL
nodeSelector:
accelerator: "nvidia-a100-80gb"
tolerations:
- key: "nvidia.com/gpu"
operator: "Exists"
effect: "NoSchedule"
Worker:
replicas: 3 # 3 worker + 1 master = 4 nodi, 32 GPU totali
restartPolicy: OnFailure
template:
spec: # stesso spec del Master...
containers:
- name: pytorch
image: company.registry.io/training:llm-v2.1
resources:
limits:
nvidia.com/gpu: "8"
memory: "120Gi"
cpu: "32"
Karpenter voor Spot GPU Node Provisioning
GPU's zijn de duurste bronnen in de cloud. Spot-GPU-instanties kosten 60-70% minder vergeleken met on-demand. Karpenter beheert de automatische inrichting van spot-GPU-nodes, met terugval naar on-demand in geval van een storing:
# karpenter-gpu-nodepool.yaml
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: gpu-spot
spec:
template:
metadata:
labels:
role: gpu-worker
accelerator: nvidia
spec:
nodeClassRef:
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
name: gpu-nodeclass
requirements:
# Tipologie di istanze GPU AWS
- key: node.kubernetes.io/instance-type
operator: In
values:
- p4d.24xlarge # 8x A100 80GB
- p3.8xlarge # 4x V100
- g5.12xlarge # 4x A10G
- g4dn.12xlarge # 4x T4
# Preferisci spot
- key: karpenter.sh/capacity-type
operator: In
values:
- spot
- on-demand # fallback
- key: kubernetes.io/os
operator: In
values:
- linux
taints:
- key: nvidia.com/gpu
value: "true"
effect: NoSchedule
limits:
nvidia.com/gpu: 256 # max 256 GPU totali nel cluster
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 30m # rimuovi nodi GPU spot quando il job finisce
---
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: gpu-nodeclass
spec:
amiFamily: AL2
role: KarpenterNodeRole
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: "my-cluster"
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: "my-cluster"
instanceStorePolicy: RAID0 # usa i dischi NVMe locali per storage temporaneo
userData: |
#!/bin/bash
# Installa NVIDIA drivers al primo boot
/etc/eks/bootstrap.sh my-cluster
nvidia-smi # verifica GPU disponibili
GPU Time-Slicing: deel een GPU tussen meerdere pods
Voor lichte gevolgtrekkingen of ontwikkelingswerklasten wordt vaak een hele GPU verspild. De GPU-time-slicing stelt u in staat een fysieke GPU te delen tussen meerdere pods, die elk een "virtuele GPU" zien met een deel van de rekentijd:
# gpu-time-slicing-config.yaml
# Configura il Device Plugin per time-slicing
apiVersion: v1
kind: ConfigMap
metadata:
name: time-slicing-config
namespace: gpu-operator
data:
any: |-
version: v1
flags:
migStrategy: none
sharing:
timeSlicing:
renameByDefault: false
failRequestsGreaterThanOne: false
resources:
- name: nvidia.com/gpu
replicas: 4 # ogni GPU fisica diventa 4 "GPU" logiche
---
# Applica il config all'operator
kubectl patch clusterpolicy gpu-cluster-policy \
-n gpu-operator \
--type merge \
-p '{"spec": {"devicePlugin": {"config": {"name": "time-slicing-config"}}}}'
# Verifica: ogni nodo con 1 GPU A100 ora mostra 4 GPU allocabili
kubectl describe node gpu-node-1 | grep nvidia.com/gpu
# Allocatable:
# nvidia.com/gpu: 4
# Pod che usa 1/4 di GPU
apiVersion: v1
kind: Pod
metadata:
name: inference-small
spec:
containers:
- name: model-server
image: company.registry.io/inference:v1
resources:
limits:
nvidia.com/gpu: "1" # ottiene 1/4 della GPU fisica
MIG: GPU met meerdere instanties voor A100 en H100
NVIDIA A100 en H100 GPU's ondersteunen MIG (GPU met meerdere exemplaren), dat verdeel de GPU in geïsoleerde hardware-instanties (niet alleen in time-sharing). Elke MIG-instantie het heeft gegarandeerd geheugen en rekenkracht en interfereert niet met de andere:
# Configura MIG sul nodo (eseguito sul nodo GPU, non da kubectl)
# Richiede: driver NVIDIA >= 525, GPU A100 o H100
# Abilita MIG mode sulla GPU
sudo nvidia-smi -mig 1
# Crea 7 istanze MIG da 1/7 di A100 (1g.10gb)
sudo nvidia-smi mig -cgip -p 0,9 # Profile 9 = MIG 1g.10gb
# Verifica istanze create
sudo nvidia-smi mig -lgi
# +-------------------------------------------------------+
# | GPU instances: |
# | GPU Name Profile Instance Placement |
# | ID ID Start:Size |
# |=======================================================|
# | 0 MIG 1g.10gb 9 1 0:1 |
# | 0 MIG 1g.10gb 9 2 1:1 |
# | 0 MIG 1g.10gb 9 3 2:1 |
# ... (7 istanze totali)
# Nel cluster Kubernetes, configurare MIG Strategy nel GPU Operator
kubectl patch clusterpolicy gpu-cluster-policy \
-n gpu-operator \
--type json \
-p '[{"op":"replace","path":"/spec/mig/strategy","value":"mixed"}]'
# Pod che richiede specifica istanza MIG
apiVersion: v1
kind: Pod
metadata:
name: inference-mig
spec:
containers:
- name: model
image: nvcr.io/nvidia/pytorch:24.01-py3
resources:
limits:
nvidia.com/mig-1g.10gb: "1" # richiedi 1 istanza MIG 1g.10gb
GPU-bewaking met DCGM Exporter
GPU-monitoring is essentieel om te begrijpen of trainingstaken efficiënt zijn en voor FinOps. DCGM Exporter stelt GPU-statistieken bloot aan Prometheus:
# DCGM Exporter viene installato automaticamente con GPU Operator
# Verifica che le metriche siano disponibili
kubectl port-forward svc/gpu-operator-dcgm-exporter 9400:9400 -n gpu-operator &
curl -s localhost:9400/metrics | grep DCGM_FI
# Metriche chiave da monitorare:
# DCGM_FI_DEV_GPU_UTIL - utilizzo GPU (0-100%)
# DCGM_FI_DEV_MEM_COPY_UTIL - utilizzo memoria GPU
# DCGM_FI_DEV_FB_USED - memoria GPU usata (MB)
# DCGM_FI_DEV_POWER_USAGE - consumo energetico (W)
# DCGM_FI_DEV_SM_CLOCK - clock streaming multiprocessor
# DCGM_FI_DEV_GPU_TEMP - temperatura GPU
# Alert: GPU sottoutilizzata (< 50% per 30 minuti = spreco)
- alert: GPUUnderutilized
expr: DCGM_FI_DEV_GPU_UTIL < 50
for: 30m
labels:
severity: warning
annotations:
summary: "GPU {{ $labels.gpu }} sul nodo {{ $labels.Hostname }} utilization < 50%"
description: "Valuta se il job puo essere terminato o ottimizzato"
# Dashboard Grafana: importa ID 12239 (NVIDIA DCGM Exporter Dashboard)
Implementatie van modellen voor inferentie met TorchServe
Voor productie-inferentie hebt u een modelserver nodig die de taakverdeling afhandelt inclusief replicatie van meerdere modellen, batchverwerking van verzoeken en versiebeheer. FakkelServe en de officiële PyTorch-oplossing:
# torchserve-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: model-inference
namespace: ml-inference
spec:
replicas: 3 # 3 replica per alta disponibilita
selector:
matchLabels:
app: model-inference
template:
metadata:
labels:
app: model-inference
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8082" # TorchServe metrics port
spec:
containers:
- name: torchserve
image: pytorch/torchserve:0.11.0-gpu
args:
- torchserve
- --start
- --model-store=/models
- --models=text-classifier=bert-classifier.mar
- --ts-config=/config/config.properties
ports:
- containerPort: 8080 # inference API
- containerPort: 8081 # management API
- containerPort: 8082 # metrics
resources:
limits:
nvidia.com/gpu: "1"
memory: "16Gi"
cpu: "4"
requests:
memory: "8Gi"
cpu: "2"
readinessProbe:
httpGet:
path: /ping
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
livenessProbe:
httpGet:
path: /ping
port: 8080
initialDelaySeconds: 120
periodSeconds: 30
volumeMounts:
- name: model-store
mountPath: /models
- name: ts-config
mountPath: /config
volumes:
- name: model-store
persistentVolumeClaim:
claimName: model-store-pvc
- name: ts-config
configMap:
name: torchserve-config
tolerations:
- key: "nvidia.com/gpu"
operator: "Exists"
effect: "NoSchedule"
---
apiVersion: v1
kind: ConfigMap
metadata:
name: torchserve-config
namespace: ml-inference
data:
config.properties: |
inference_address=http://0.0.0.0:8080
management_address=http://0.0.0.0:8081
metrics_address=http://0.0.0.0:8082
number_of_gpu=1
batch_size=32
max_batch_delay=100 # ms: attendi fino a 100ms per fare batching
max_response_size=6553500
install_py_dep_per_model=true
---
# HPA basato su latenza con KEDA (event-driven autoscaling)
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: inference-scaler
namespace: ml-inference
spec:
scaleTargetRef:
name: model-inference
minReplicaCount: 1
maxReplicaCount: 10
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus.monitoring.svc:9090
metricName: torchserve_queue_latency_microseconds
threshold: "100000" # 100ms di coda = scala up
query: avg(torchserve_queue_latency_microseconds{model_name="bert-classifier"})
Best practices voor AI-workloads op Kubernetes
GPU-kostenoptimalisatie
- Plek voor training, on-demand voor gevolgtrekking: Training kan onderbrekingen met controlepunten verwerken; gevolgtrekking moet altijd beschikbaar zijn
- Frequente controlepunten: Sla elke 30 minuten controlepunten op om de training te hervatten na een spotonderbreking
- Time-slicing voor ontwikkeling: Gebruik time-sliced GPU's voor ontwikkelaars, MIG of volledige GPU's voor productie
- Schalen naar nul: Karpenter verwijdert spot-GPU-nodes wanneer de training is voltooid. U betaalt niet voor inactieve GPU's
- Batching in inferentie: TorchServe met batch_size=32 verhoogt de doorvoer 10-20x vergeleken met afzonderlijke verzoeken
- Profiel vóór implementatie: Gebruik NVIDIA Nsight om uw trainingstaak te profileren en inefficiënties te identificeren
Veelvoorkomende GPU-fouten op Kubernetes
- Containers zonder geurtolerantie: GPU-knooppunten hebben een besmetting
nvidia.com/gpu=true:NoSchedule; zonder tolerantie wordt de Pod niet gepland op het GPU-knooppunt - Kan het geheugen niet isoleren: De GPU isoleert het geheugen niet tussen containers, zoals de CPU dat doet. Als u 1 GPU toewijst, maar het model meer geheugen gebruikt dan beschikbaar is, crasht de taak met CUDA OOM
- NCCL zonder gedeeld geheugen: Gedistribueerde PyTorch-training maakt gebruik van NCCL, waarvoor een grote /dev/shm nodig is (doorgaans 10-60 GB); configureer altijd een lege map met medium: Geheugen
- Controleer het GPU-gebruik niet: Een GPU met een bezettingsgraad van 20% is een enorme verspilling. Het DCGM-dashboard moet de eerste plaats zijn waar u na elke implementatie op let
Conclusies en volgende stappen
Kubernetes is niet toevallig het standaardplatform voor AI/ML-workloads geworden: de de abstractie van hulpbronnen, het geavanceerde planningssysteem en het ecosysteem van de operator (Kubeflow, Training Operator) maken het de ideale context om beide trainingen te orkestreren die gevolgtrekking naar schaal. Waarbij Karpenter de node-provisioning automatisch beheert Spot GPU, de kosten van een trainingsopdracht kunnen met 40-70% worden verlaagd in vergelijking met het gebruik van on-demand-instanties.
De volgende stap is het integreren van deze workloads met een volledige MLOps-pijplijn: loggen van modellen met MLflow, datasetbeheer met DVC, CI/CD voor automatische hertraining. In het FinOps for Kubernetes-artikel (artikel 9 in deze serie) wordt dieper ingegaan op de manier waarop u kunt meten en optimaliseer de totale kosten van GPU-workloads in het cluster.
Aankomende artikelen in de Kubernetes at Scale-serie
Gerelateerde serie
- MLOps en machine learning in productie — CI/CD-pijplijn voor ML, modelregistratie
- Diep leren en neurale netwerken — theoretische grondslagen voor modeltraining op GPU's
- Automatisch schalen in Kubernetes — KEDA voor schaling op basis van aangepaste statistieken







