Résumé
- Les GPU sont la ressource centrale des charges de travail IA : le taux d'utilisation moyen des GPU dans les clusters K8s n'est que de 30 à 40 % ; l'optimisation de la planification peut le porter à plus de 80 %
- Partitionnement MIG NVIDIA : une seule A100 peut être divisée en 7 instances, prenant en charge l'exécution parallèle de différentes tâches IA et multipliant par 3 l'utilisation des ressources
- Trois modes de partage GPU : Time Slicing (TS), MPS et MIG, adaptés respectivement à l'inférence, à l'entraînement et aux scénarios mixtes
- Stratégies de planification multi-locataires : gestion des quotas GPU, préemption basée sur la priorité et mise à l'échel élastique pour garantir le respect des SLA
- Cet article propose une solution complète de planification GPU K8s, incluant la configuration du Device Plugin et des pratiques d'extension du planificateur
Table des matières
Planification GPU : le défi central des clusters IA
État actuel du gaspillage des ressources GPU
| Problème |
Cause |
Pourcentage de gaspillage |
| Faible utilisation en inférence |
Une seule requête d'inférence utilise seulement 10 à 20 % du GPU |
40 à 60 % |
| Fragmentation de l'entraînement |
L'entraînement de petits modèles occupe une carte entière |
20 à 30 % |
| Attente inactive |
Tâches en file d'attente en attendant la libération du GPU |
15 à 25 % |
| Mauvaise configuration |
Les requêtes de ressources ne correspondent pas à l'utilisation réelle |
10 à 15 % |
Évolution de la planification GPU
| Phase |
Période |
Approche |
Caractéristiques |
| Mode exclusif |
Avant 2020 |
1Pod=1GPU |
Simple mais gaspilleur |
| Time Slicing |
2021 |
Partage par tranches de temps GPU |
Adapté à l'inférence |
| Partitionnement MIG |
2022 |
Partitionnement matériel de l'A100 |
Isolation forte |
| Partage MPS |
2023 |
Partage GPU multi-processus |
Adapté à l'entraînement |
| Planification élastique |
2024-2026 |
MIG dynamique + priorité |
Intelligente |
Spécifications GPU courantes en 2026
| GPU |
Mémoire |
Instances MIG |
Scénarios adaptés |
Prix ($/h) |
| A100 80GB |
80GB |
7x10GB ou 2x40GB |
Entraînement et inférence généraux |
3,5 |
| H100 80GB |
80GB |
7x10GB ou 2x40GB |
Entraînement de grands modèles |
4,5 |
| H200 141GB |
141GB |
7x20GB ou 2x70GB |
Modèles ultra-grands |
6,0 |
| L40S 48GB |
48GB |
MIG non pris en charge |
Inférence / fine-tuning |
1,5 |
| RTX 4090 |
24GB |
MIG non pris en charge |
Développement et test |
0,8 |
Partitionnement MIG NVIDIA en pratique
Aperçu de l'architecture MIG
┌──────────────────────────────────────────────────────────────┐
│ A100 80GB MIG Partitioning Schemes │
│ │
│ Scheme 1: 7x MIG 1g.10gb (maximum parallelism) │
│ ┌──────┐┌──────┐┌──────┐┌──────┐┌──────┐┌──────┐┌──────┐ │
│ │ GI 0 ││ GI 1 ││ GI 2 ││ GI 3 ││ GI 4 ││ GI 5 ││ GI 6 │ │
│ │10GB ││10GB ││10GB ││10GB ││10GB ││10GB ││10GB │ │
│ │14SM ││14SM ││14SM ││14SM ││14SM ││14SM ││14SM │ │
│ └──────┘└──────┘└──────┘└──────┘└──────┘└──────┘└──────┘ │
│ Suited for: 7 lightweight inference services in parallel │
│ │
│ Scheme 2: 2x MIG 3g.40gb (large model inference) │
│ ┌─────────────────────────────┐┌─────────────────────────────┐│
│ │ GI 0 ││ GI 1 ││
│ │ 40GB ││ 40GB ││
│ │ 42SM ││ 42SM ││
│ └─────────────────────────────┘└─────────────────────────────┘│
│ Suited for: 2x 70B model inference (quantized) │
│ │
│ Scheme 3: 1x MIG 4g.40gb + 2x MIG 1g.10gb (mixed) │
│ ┌─────────────────────────────┐┌──────┐┌──────┐ │
│ │ GI 0 ││ GI 1 ││ GI 2 │ │
│ │ 40GB ││10GB ││10GB │ │
│ │ 56SM ││14SM ││14SM │ │
│ └─────────────────────────────┘└──────┘└──────┘ │
│ Suited for: 1 large model inference + 2 lightweight inference │
└──────────────────────────────────────────────────────────────┘
MIG Configuration in Practice
# nvidia-mig-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nvidia-mig-config
namespace: gpu-operator
data:
config.yaml: |
version: v1
mig-configs:
all-1g.10gb:
- devices: all
mig-enabled: true
mig-devices:
"1g.10gb": 7
all-2g.20gb:
- devices: all
mig-enabled: true
mig-devices:
"2g.20gb": 3
all-3g.40gb:
- devices: all
mig-enabled: true
mig-devices:
"3g.40gb": 2
mixed:
- devices: [0]
mig-enabled: true
mig-devices:
"3g.40gb": 2
- devices: [1]
mig-enabled: true
mig-devices:
"1g.10gb": 7
- devices: [2, 3]
mig-enabled: false
---
apiVersion: nvidia.com/v1alpha1
kind: MigManager
metadata:
name: mig-manager
spec:
config: nvidia-mig-config
gpuClientsConfig:
version: v1
gpuClients:
- namespace: "ai-inference"
podSelector:
matchLabels:
workload: "llm-inference"
migDevice: "3g.40gb"
- namespace: "ai-inference"
podSelector:
matchLabels:
workload: "light-inference"
migDevice: "1g.10gb"
MIG Pod Scheduling
# Large model inference - using MIG 3g.40gb
apiVersion: v1
kind: Pod
metadata:
name: llm-inference-70b
namespace: ai-inference
labels:
workload: llm-inference
spec:
containers:
- name: inference
image: vllm/vllm-openai:latest
resources:
limits:
nvidia.com/mig-3g.40gb: 1
env:
- name: MODEL_NAME
value: "Qwen/Qwen2.5-72B-Instruct-AWQ"
- name: GPU_MEMORY_UTILIZATION
value: "0.95"
- name: MAX_MODEL_LEN
value: "8192"
---
# Lightweight inference - using MIG 1g.10gb
apiVersion: v1
kind: Pod
metadata:
name: embedding-service
namespace: ai-inference
labels:
workload: light-inference
spec:
containers:
- name: embedding
image: huggingface/tei:latest
resources:
limits:
nvidia.com/mig-1g.10gb: 1
env:
- name: MODEL_NAME
value: "BAAI/bge-large-zh-v1.5"
- name: MAX_BATCH_SIZE
value: "256"
Trois modes de partage GPU
Comparaison des modes
| Dimension |
Time Slicing (TS) |
MPS |
MIG |
| Niveau d'isolation |
Logiciel |
Matériel (partiel) |
Matériel (complet) |
| Isolation mémoire |
Non (partagée) |
Non (partagée) |
Oui (indépendante) |
| Isolation des performances |
Faible |
Moyenne |
Bonne |
| Parallélisme |
Élevé |
Moyen |
Moyen |
| Isolation des pannes |
Faible |
Faible |
Bonne |
| Scénarios adaptés |
Inférence |
Entraînement |
Mixte |
| Exigence GPU |
Général |
Volta+ |
A100+ |
Configuration du Time Slicing
# gpu-time-slicing.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: gpu-time-slicing-config
namespace: gpu-operator
data:
config.yaml: |
version: v1
flags:
migStrategy: none
sharing:
timeSlicing:
renameByDefault: false
resources:
- name: nvidia.com/gpu
replicas: 4
devices: all
---
# Pod using time slicing
apiVersion: apps/v1
kind: Deployment
metadata:
name: inference-pool
namespace: ai-inference
spec:
replicas: 8
selector:
matchLabels:
app: inference
template:
metadata:
labels:
app: inference
spec:
containers:
- name: inference
image: vllm/vllm-openai:latest
resources:
limits:
nvidia.com/gpu: 1
env:
- name: MODEL_NAME
value: "Qwen/Qwen2.5-7B-Instruct"
Configuration MPS
# gpu-mps-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: gpu-mps-config
namespace: gpu-operator
data:
config.yaml: |
version: v1
sharing:
mps:
resources:
- name: nvidia.com/gpu
replicas: 2
devices: all
---
apiVersion: v1
kind: Pod
metadata:
name: training-job-mps
namespace: ai-training
spec:
containers:
- name: training
image: pytorch/pytorch:2.4-cuda12.4
resources:
limits:
nvidia.com/gpu: 1
command:
- python
- -m
- torch.distributed.launch
- --nproc_per_node=2
- train.py
Arbre de décision de sélection du mode
Avez-vous A100/H100 ?
├── Non → Time Slicing (inférence) / MPS (entraînement)
└── Oui → Isolation complète requise ?
├── Oui → Partitionnement MIG
└── Non → Entraînement requis ?
├── Oui → MPS
└── Non → Time Slicing
Configuration du Device Plugin GPU K8s
Déploiement du Device Plugin NVIDIA
# nvidia-device-plugin.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nvidia-device-plugin-daemonset
namespace: kube-system
spec:
selector:
matchLabels:
name: nvidia-device-plugin-ds
template:
metadata:
labels:
name: nvidia-device-plugin-ds
spec:
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule
priorityClassName: system-node-critical
containers:
- name: nvidia-device-plugin
image: nvcr.io/nvidia/k8s-device-plugin:v0.16.0
args:
- --config=default
- --mig-strategy=mixed
- --pass-device-specs=true
- --device-list-strategy=configmap
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
volumeMounts:
- name: device-plugin
mountPath: /var/lib/kubelet/device-plugins
volumes:
- name: device-plugin
hostPath:
path: /var/lib/kubelet/device-plugins
Surveillance des ressources GPU
# gpu-monitor.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: gpu-monitor-config
namespace: monitoring
data:
gpu-metrics.json: |
{
"metrics": [
"gpu_utilization",
"gpu_memory_utilization",
"gpu_memory_used_bytes",
"gpu_memory_total_bytes",
"gpu_power_usage_watts",
"gpu_temperature_celsius",
"gpu_sm_clock_mhz",
"gpu_mem_clock_mhz"
],
"scrape_interval": "15s",
"labels": {
"cluster": "production",
"region": "cn-east"
}
}
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: dcgm-exporter
namespace: monitoring
spec:
selector:
matchLabels:
app: dcgm-exporter
template:
metadata:
labels:
app: dcgm-exporter
spec:
containers:
- name: dcgm-exporter
image: nvcr.io/nvidia/k8s/dcgm-exporter:3.3.7
ports:
- containerPort: 9400
name: metrics
env:
- name: DCGM_EXPORTER_COLLECTORS
value: "/etc/dcgm-exporter/dcp-metrics-inventory.csv"
resources:
limits:
nvidia.com/gpu: 1
Stratégies de planification GPU multi-locataires
Gestion des quotas GPU
# gpu-resource-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: gpu-quota-team-a
namespace: team-a
spec:
hard:
requests.nvidia.com/gpu: "8"
limits.nvidia.com/gpu: "8"
requests.nvidia.com/mig-3g.40gb: "4"
limits.nvidia.com/mig-3g.40gb: "4"
requests.nvidia.com/mig-1g.10gb: "14"
limits.nvidia.com/mig-1g.10gb: "14"
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: gpu-quota-team-b
namespace: team-b
spec:
hard:
requests.nvidia.com/gpu: "4"
limits.nvidia.com/gpu: "4"
requests.nvidia.com/mig-3g.40gb: "2"
limits.nvidia.com/mig-3g.40gb: "2"
Planification avec préemption basée sur la priorité
# gpu-priority-class.yaml
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: gpu-critical
value: 1000000
globalDefault: false
description: "Critical GPU workloads - can preempt others"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: gpu-high
value: 900000
globalDefault: false
description: "High priority GPU workloads"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: gpu-low
value: 100000
globalDefault: false
description: "Low priority GPU workloads - preemptible"
---
# Online inference - high priority
apiVersion: apps/v1
kind: Deployment
metadata:
name: online-inference
spec:
template:
spec:
priorityClassName: gpu-critical
containers:
- name: inference
resources:
limits:
nvidia.com/mig-3g.40gb: 1
---
# Offline training - low priority
apiVersion: batch/v1
kind: Job
metadata:
name: offline-training
spec:
template:
spec:
priorityClassName: gpu-low
containers:
- name: training
resources:
limits:
nvidia.com/gpu: 4
Mise à l'échel élastique GPU
# gpu-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: inference-hpa
namespace: ai-inference
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: inference-pool
minReplicas: 2
maxReplicas: 20
metrics:
- type: Pods
pods:
metric:
name: gpu_utilization
target:
type: AverageValue
averageValue: "70"
- type: Pods
pods:
metric:
name: request_latency_ms
target:
type: AverageValue
averageValue: "200"
behavior:
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 50
periodSeconds: 120
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 25
periodSeconds: 300
Gestion des clusters GPU en production
Étiquetage et planification des nœuds GPU
# gpu-node-labels.yaml
# Label GPU types
kubectl label nodes gpu-node-1 nvidia.com/gpu.product=A100-SXM4-80GB
kubectl label nodes gpu-node-2 nvidia.com/gpu.product=H100-SXM5-80GB
kubectl label nodes gpu-node-3 nvidia.com/gpu.product=L40S-48GB
# Label MIG configurations
kubectl label nodes gpu-node-1 nvidia.com/mig.config=mixed
kubectl label nodes gpu-node-2 nvidia.com/mig.config=all-3g.40gb
# Schedule to specific GPU
apiVersion: v1
kind: Pod
metadata:
name: h100-training
spec:
nodeSelector:
nvidia.com/gpu.product: H100-SXM5-80GB
containers:
- name: training
resources:
limits:
nvidia.com/gpu: 8
Auto-guérison des pannes GPU
# gpu-health-check.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: gpu-health-monitor
namespace: kube-system
spec:
selector:
matchLabels:
app: gpu-health-monitor
template:
metadata:
labels:
app: gpu-health-monitor
spec:
serviceAccountName: gpu-health-sa
containers:
- name: monitor
image: custom/gpu-health-monitor:latest
env:
- name: CHECK_INTERVAL
value: "60"
- name: MEMORY_ERROR_THRESHOLD
value: "10"
- name: TEMPERATURE_THRESHOLD
value: "90"
- name: AUTO_CORDON
value: "true"
volumeMounts:
- name: nvidia
mountPath: /usr/local/nvidia
volumes:
- name: nvidia
hostPath:
path: /usr/local/nvidia
Résultats d'optimisation de l'utilisation GPU
| Mesure d'optimisation |
Augmentation de l'utilisation |
Économies de coûts |
| Partitionnement MIG |
+35 % |
30 % |
| Time Slicing |
+25 % |
20 % |
| Planification par priorité |
+15 % |
15 % |
| Mise à l'échel élastique |
+10 % |
10 % |
| Optimisation combinée |
+50 % |
50 % |
Résumé et ressources
Points clés à retenir
- Partitionnement MIG : la fonctionnalité phare de l'A100/H100 — transforme 1 carte en 7, le premier choix pour l'inférence
- Partage GPU : Time Slicing pour l'inférence, MPS pour l'entraînement, MIG pour les charges mixtes
- Planification multi-locataires : le trio quotas + priorités + mise à l'échel élastique garantit le respect des SLA
- Optimisation combinée : MIG + planification + mise à l'échel ensemble permettent 50 % d'économies
Recommandations de solution de planification GPU
| Taille du cluster |
Solution recommandée |
Utilisation attendue |
| <8 cartes |
Time Slicing |
60 % |
| 8 à 32 cartes |
MIG + Time Slicing |
75 % |
| 32 à 128 cartes |
MIG + planification par priorité |
80 % |
| >128 cartes |
Suite de solution complète |
85 %+ |
Besoin de générer rapidement des commandes cURL pour tester les API d'inférence GPU ? Essayez notre outil cURL vers Code et le JSON Formatter.
Lectures complémentaires