Plánování úloh pro AI clustery: SLURM, Kubernetes, Ray a kdy nepotřebujete ani jedno
Scheduler rozhoduje o tom, která úloha poběží na kterých GPU, kdy a na čí účet. Bez něj se sdílený cluster zvrhne v to, že si lidé na Slacku píšou, jestli zrovna někdo nepoužívá node 3. Se špatným schedulerem strávíte víc inženýrských hodin nad YAMLem než nad samotnými modely.
Tento článek porovnává schedulery, po kterých lidé reálně sahají — SLURM, Kubernetes (s Kueue nebo Volcano), Ray a KubeRay a komerční řešení Run:ai a Determined — a nezastírá ani případ, kdy je správnou odpovědí „nic, stačí SSH“. Čtenář už má za sebou K01, K02 a K03 a nyní se rozhoduje, co nad cluster o 1–32 uzlech postavit.
Co scheduler vlastně dělá
Tři úkoly, zhruba v pořadí podle obtížnosti: umístit práci na volné zdroje, zařadit do fronty práci, která se zatím nevejde, a koordinovat víceuzlové úlohy — distribuovaný trénink potřebuje, aby všech N ranků odstartovalo naráz (gang scheduling), protože v PyTorchi dist.barrier() blokuje donekonečna, pokud se jeden rank nikdy neukáže (viz K06).
Cokoli nad rámec clusteru pro jediný tým navíc potřebuje multi-tenantní kvóty s půjčováním, slábnoucí fair-share mezi týmy, preempci a pořádné účtování GPU (aby úloha viděla správně nastavené CUDA_VISIBLE_DEVICES ). Všechny schedulery níže zvládají první tři body. Liší se v tom druhém seznamu a v tom, jakou práci u Vás předpokládají.
Zásadní dělicí čára: dávkové úlohy vs. dlouho běžící služby
Tohle je vůbec nejdůležitější rozlišení. Dávkové úlohy trénují osm hodin a skončí, proženou sweep 200 krátkých úloh nebo přes noc zpracují dataset — začátek, konec, výsledek, nic neodpovídá na HTTP. Dlouho běžící služby jsou vLLM endpoint obsluhující inferenci 24/7, databáze scene memory nebo monitorovací stack — mají běžet pořád a po pádu se restartovat.
SLURM vznikl pro dávky. Kubernetes vzniklo pro dlouho běžící služby. Všechno ostatní je jedno z těch dvou natahované na tu druhou polovinu.
| Workload | SLURM | Kubernetes |
|---|---|---|
| Osmihodinový trénink | Nativně | Potřebuje Kueue nebo Volcano |
| Sweep 200 úloh přes hyperparametry | Nativně | Neohrabané |
| vLLM inferenční endpoint 24/7 | Neohrabané | Nativně |
| Mix: trénink + inference + nástroje | Bolestivé | Nativně (s Kueue) |
| Víceuzlový distribuovaný trénink | Nativně (gang) | Potřebuje gang plugin |
| Automatický restart spadlých služeb | Ne | Nativně |
Pokud Váš cluster dělá jen jednu z těch věcí, je volba snadná. Pokud dělá obojí — což je čím dál běžnější — je otázkou, u kterého scheduleru jste ochotni zaplatit provozní daň.
SLURM — výchozí volba z HPC, která u čistého tréninku pořád vítězí
Na SLURMu běží víc než 65 % superpočítačů z TOP500 a většina publikovaných frontier tréninků. Pro workloady typu „pošli trénovací úlohu, počkej na výsledky, vezmi si checkpoint“ je správnou odpovědí už dvacet let.
Model uvažování je jednoduchý: partition je pojmenovaný pool uzlů (gpu-5090, cpu-only, bigmem); job je shell skript s direktivami #SBATCH, odesílaný příkazem sbatch; GRES (Generic RESources) eviduje GPU — --gres=gpu:rtxpro6000:2 si řekne o dvě konkrétní karty; gang scheduling je vestavěný.
Minimální slurm.conf pro čtyřuzlový cluster s 8× RTX Pro 6000 Blackwell na uzel:
ClusterName=kentino-lab
SlurmctldHost=head01
SchedulerType=sched/backfill
SelectType=select/cons_tres
SelectTypeParameters=CR_Core_Memory
GresTypes=gpu
# GPU accounting — without these two lines, fair-share runs on CPU-seconds and is meaningless
AccountingStorageType=accounting_storage/slurmdbd
AccountingStorageTRES=gres/gpu
PriorityType=priority/multifactor
PriorityDecayHalfLife=7-0
PriorityWeightFairshare=10000
PriorityWeightAge=1000
# cgroups isolate the GPUs a job is allowed to see
ProctrackType=proctrack/cgroup
NodeName=node[01-04] CPUs=128 RealMemory=1024000 Sockets=2 \
CoresPerSocket=64 ThreadsPerCore=1 Gres=gpu:rtxpro6000:8 State=UNKNOWN
PartitionName=train Nodes=node[01-03] Default=YES MaxTime=48:00:00 State=UP
PartitionName=interactive Nodes=node04 MaxTime=04:00:00 \
PriorityTier=10 State=UP
Odpovídající gres.conf na každém uzlu:
AutoDetect=nvml
NodeName=node[01-04] Name=gpu Type=rtxpro6000 File=/dev/nvidia[0-7]
AutoDetect=nvml se dotazuje přímo NVIDIA Management Library, sám zachytí MIG řezy a ušetří Vám ruční psaní cest k zařízením.
Uživatel odešle:
#!/bin/bash
#SBATCH --job-name=qwen-finetune
#SBATCH --partition=train
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=8
#SBATCH --gres=gpu:rtxpro6000:8
#SBATCH --time=12:00:00
#SBATCH --output=logs/%j.out
srun python -m torch.distributed.run \
--nnodes=2 --nproc-per-node=8 \
--rdzv-backend=c10d \
--rdzv-endpoint=$(scontrol show hostnames | head -1):29500 \
train.py --config configs/qwen72b.yaml
PyTorch Elastic a SLURM do sebe zapadají čistě: SLURM vlastní alokaci, srun spustí jeden proces na úlohu, torch.distributed.run spolu s rendezvous backendem řeší přidělení ranků. Při výpadku uzlu --max-restarts u torchrun spolu s --requeue u #SBATCH obnoví běh z posledního checkpointu. Takhle to dělá každý.
Co dostanete zadarmo: gang scheduling, slábnoucí fair-share, backfill, účtování (každá GPU-sekunda zalogovaná do sacct) a jednoduchou sémantiku — žádné CRD, žádný controller, žádný graf YAML objektů. Co nedostanete: dlouho běžící služby s automatickým restartem, HTTP ingress, rolling updaty, sidecar kontejnery, deklarativní stav. SLURM je dávkový scheduler. Zacházet s ním jako s Kubernetes bolí.
SLURM je správná volba, když: provozujete trénink, dávkovou inferenci nebo simulace; uživatelé píšou shell skripty; a ustojí to jeden SRE na částečný úvazek.
Kde SLURM naráží na strop
Na třech místech. Služby webového typu — nezná pojem „běž navždy, po pádu se restartuj, vystav port 8000“. vLLM se do dlouho běžící SLURM úlohy nacpat dá, ale health-checky, rolling updaty a load balancing už jsou Váš problém. Heterogenní workloady — SLURM předpokládá jeden pool zdrojů; cluster, na kterém běží trénink + inference + Jupyter + monitoring + příprava dat, chce jemnější ovládání. Přísná multi-tenantní izolace — cgroups izolují CPU a paměť; izolace GPU stojí na CUDA_VISIBLE_DEVICES a na tom, že ji kód uživatele respektuje. Žádné namespacy, žádná síťová politika na úrovni úlohy, žádná tenance kontejnerové třídy. Pro laboratoř v pořádku; pro hostovanou službu pro více zákazníků ne.
Jakmile na něco z toho narazíte, správným krokem bývá přidat druhou vrstvu — Kubernetes pro služby — místo toho, abyste mučili SLURM. SUNK od CoreWeave a managed nabídky z roku 2026 provozují SLURM na Kubernetes, takže tentýž cluster zvládá obojí. V měřítku Kentino bývají dva oddělené malé clustery jednodušší.
Kubernetes pro AI: cloud-native cesta
Kubernetes vzniklo proto, aby udrželo v chodu bezstavové webové služby. Pro AI clustery se „všechno ostatní“ přišroubovává zvenčí. Stack roku 2026: NVIDIA GPU Operator (ovladače, CUDA, NCCL, DCGM, device plugin, konfigurace MIG), Kueue (fronta, kvóty, admission), Volcano (scheduler s podporou dávek), Kubeflow Trainer (CRD PyTorchJob, TFJob, MPIJob), KubeRay (Ray na K8s) a Karpenter nebo Cluster Autoscaler pro provisioning uzlů.
Proč je naivní Kubernetes pro AI špatně: výchozí kube-scheduler je FIFO bez gang sémantiky. Klidně spustí 7 z 8 podů distribuovaného tréninku a osmý nechá v Pending, zatímco běžících sedm drží GPU naprázdno. Není to teorie — je to vůbec nejčastější chyba týmů, které se pokusí spustit trénink na clusteru postaveném pro inferenci. Řešením jsou Kueue (admission na úrovni úlohy) a Volcano (gang umístění na úrovni podů). Aktuální best practice je obojí: Kueue nahoře, Volcano pod ním.
Volcano
Volcano je dávkový scheduler z CNCF, který se instaluje vedle kube-scheduleru nebo místo něj. Přidává skutečný gang scheduling se sémantikou minAvailable (pustí nula, nebo N, nikdy ne část), priority front a preempci, strategie fair-share / binpack / topology-aware a prvotřídní podporu pro PyTorchJob, TFJob, MPIJob, RayJob a SparkApplication.
Minimální fronta a k ní gang-schedulovaná trénovací úloha v PyTorchi:
apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:
name: training
spec:
weight: 4
capability:
nvidia.com/gpu: 32
---
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
name: qwen-finetune
spec:
schedulerName: volcano
minAvailable: 16 # gang: all 16 ranks or zero
queue: training
policies:
- event: PodEvicted
action: RestartJob
tasks:
- replicas: 16
name: worker
template:
spec:
containers:
- name: pytorch
image: kentino/pytorch:2.5-cuda13
resources:
limits:
nvidia.com/gpu: 1
command: ["torchrun", "--nnodes=16", "--nproc-per-node=1", "train.py"]
Kdy Volcano nepotřebujete: čistě inferenční cluster s nezávislými vLLM Deploymenty. Každý pod vlastní svoje GPU, žádná koordinace napříč pody, výchozí kube-scheduler stačí. Volcano se vyplatí ve chvíli, kdy do clusteru přimícháte distribuovaný trénink.
Kueue a půjčování kvót
Kueue řeší vrstvu, kterou Volcano neřeší: kdo smí spotřebovat kolik clusteru a co se stane, když jeden tým zahálí.
apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
name: rtxpro6000
spec:
nodeLabels:
nvidia.com/gpu.product: "RTX-PRO-6000-Blackwell"
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
name: team-research
spec:
cohort: "shared-gpu"
resourceGroups:
- coveredResources: ["nvidia.com/gpu"]
flavors:
- name: rtxpro6000
resources:
- name: "nvidia.com/gpu"
nominalQuota: 16
borrowingLimit: 8
Oba týmy v kohortě mají garantovaných 16 GPU a mohou si půjčit až 8 z nevyužitého poolu toho druhého. Vysokoprioritní práce půjčenou kapacitu preemptuje. Roadmapa Kueue pro rok 2026 cílí na MultiKueue (dispatch napříč clustery) a kooperativní preempci — úloze, která umí checkpointovat, lze říct „ulož stav a uvolni místo do 60 sekund“ místo toho, aby byla rovnou zabita.
MIG a sdílení GPU
NVIDIA device plugin ve výchozím stavu alokuje celé GPU. Pro trénink a velkou inferenci je to správně; pro malou inferenci, notebooky nebo vývoj je to plýtvání. Tři režimy sdílení: MIG (hardwarová izolace paměti i chyb, produkční multi-tenantní inference), MPS (kooperativní, bez izolace), time-slicing (bez izolace, jen pro vývoj).
MIG existuje na H100/H200, A100 a B200 — na žádném GPU z nabídky Kentino ne. RTX 5090, RTX 4090, RTX Pro 6000 Blackwell, L40 ani L4 MIG nepodporují. Pokud Váš návrh vyžaduje hardwarově izolované oddíly GPU, omezuje Vás to na SXM/datacentrové díly, které Kentino nestaví. Time-slicing inzeruje N virtuálních GPU na jedno fyzické a scheduler vůbec netuší, že jsou přetížená — používejte jej jen pro vývoj.
V čem je Kubernetes dobré: dlouho běžící inferenční služby (vLLM Deploymenty škálované přes HPA podle hloubky fronty, rolling updaty, health checky — SLURM nemá nic srovnatelného), heterogenní workloady na jednom clusteru, ekosystém (Prometheus, Grafana, Argo). Co za to zaplatíte: funkční stack K8s + GPU Operator + Kueue + Volcano + Kubeflow má minimálně 20 komponent. Realistický odhad: Kubernetes znamená 5–10× vyšší provozní zátěž než SLURM u čistě dávkového tréninku.
Kubernetes je správná volba, když: na clusteru běží inferenční služby vedle tréninku, máte platformový tým, záleží Vám na tom, aby bylo všechno deklarativní, nebo potřebujete přenositelnost mezi clustery.
Ray a KubeRay — distribuované výpočty nativně v Pythonu
Ray je jiné zvíře. Ve smyslu SLURMu nebo K8s to vlastně ani není clusterový scheduler — je to distribuovaný Pythonový runtime, který s sebou nese scheduler, object store a autoscaler. Píšete Python s dekorátory @ray.remote a Ray si sám domyslí, kde kterou úlohu spustit.
Kam se Ray hodí: ladění hyperparametrů (Ray Tune — stovky běhů paralelně, špatné se ořežou brzy; případ užití, pro který Ray vznikl a ve kterém je dodnes nejlepší), zpětnovazební učení (RLlib — prostředí a učící se agenti jako aktoři, což na Ray sedne čistě a na dávkové úlohy SLURMu mizerně), distribuovaný trénink (Ray Train, obaluje PyTorch DDP / FSDP / DeepSpeed), serving modelů (Ray Serve, nativně v Pythonu, vlastní multi-model pipeline) a předzpracování dat (Ray Data). Co Ray není: multi-tenantní dávkový scheduler pro sdílený cluster. Ray předpokládá, že cluster vlastní jedna aplikace.
KubeRay je operátor, který Ray provozuje na Kubernetes. Tři CRD: RayCluster (dlouho žijící), RayJob (jednorázový), RayService (Ray Serve, rolling updaty). Minimální RayCluster:
apiVersion: ray.io/v1
kind: RayCluster
metadata:
name: rl-cluster
spec:
rayVersion: '2.55.0'
headGroupSpec:
rayStartParams: { dashboard-host: '0.0.0.0' }
template:
spec:
containers:
- name: ray-head
image: rayproject/ray:2.55.0-py311-cu125
resources:
limits: { cpu: 8, memory: 32Gi }
workerGroupSpecs:
- groupName: gpu-workers
replicas: 4
minReplicas: 0
maxReplicas: 8
rayStartParams: {}
template:
spec:
containers:
- name: ray-worker
image: rayproject/ray:2.55.0-py311-cu125
resources:
limits:
cpu: 16
memory: 128Gi
nvidia.com/gpu: 4
KubeRay škáluje skupinu workerů mezi minReplicas a maxReplicas podle toho, jak Ray vidí čekající úlohy. V kombinaci s Kueue (RayJob + gang scheduling přes Kueue je zdokumentovaný a funguje) dostanete multi-tenantní Ray na multi-tenantním K8s clusteru — produkční nasazení, které většina „Ray shopů“ skutečně provozuje.
Kdy dává smysl samostatný Ray (bez K8s): malá výzkumná laboratoř, kde cluster vlastní jeden člověk, dynamika je důležitější než multi-tenance a workload je těžký na RL nebo hledání hyperparametrů. Hybrid, ke kterému většina týmů dojde: SLURM nebo K8s jako základní vrstva, která vlastní uzly a multi-tenanci; Ray spouštěný uvnitř SLURM úlohy nebo K8s namespace po dobu workloadu jednoho uživatele. Neinstalujte Ray jako svůj nejvyšší scheduler.
Run:ai a Determined — komerční patro
Dvě placená řešení se objevují dost často na to, aby stálo za to je zmínit. Obě míří na stejnou bolest: K8s + Volcano + Kueue + GPU Operator je spousta YAMLu a některé organizace raději koupí, než aby stavěly.
NVIDIA Run:ai (akvizice 2024, přejmenováno 2025) je GPU scheduler nativní pro K8s. Dělení GPU na zlomky rozděluje jedno GPU mezi workloady na úrovni paměti — požadavky typu 0.5 GPU, dynamické zvětšování a bin-packing. Run:ai se vyplatí v podnicích s 10+ ML týmy, které soupeří o sdílená GPU. Pod touto hranicí pokryje Kueue + GPU Operator většinu téhož zdarma.
Determined.AI (HPE, 2021) je spravovaná trénovací platforma — sledování experimentů, hledání hyperparametrů, správa checkpointů a distribuovaný trénink v jednom produktu. Nejlépe sedne výzkumným týmům, které chtějí vyladěný dashboard, aniž by samy integrovaly pět nástrojů.
Problém interaktivních notebooků
Vzorec, který dostihne skoro každý sdílený GPU cluster: výzkumníci chtějí kvůli vývoji přístup k GPU přes JupyterHub a to musí koexistovat s dlouho běžícími trénovacími úlohami, které drží celé uzly. Naivní odpověď — jedno vyhrazené GPU na notebook — zahodí 80 % clusteru. Striktní odpověď — nutit výzkumníky všechno posílat přes sbatch — je vyžene na laptopy s hračkovými modely.
Tři funkční vzorce: SLURM salloc + Jupyter na alokaci (salloc --gres=gpu:1 --time=4:00:00, na alokovaném uzlu spustíte Jupyter server a tunelujete se dovnitř; tvrdý časový limit, GPU řádně zaúčtované — nejčistší odpověď pro SLURM cluster), Kubernetes + JupyterHub + Kueue (pody s notebooky přes nízkoprioritní frontu, trénovací úlohy preemptují nečinné notebooky), nebo Run:ai s dělením GPU na zlomky (každý notebook dostane 0.25 / 0.5 GPU). Ať zvolíte cokoli, nastavte interaktivním sezením časový limit — notebook bez timeoutu je GPU natrvalo vyřazené z clusteru.
Upřímná realita malého týmu
Většina obsahu o schedulerech na internetu předpokládá cluster o 256 GPU a platformový tým. Realistický zákazník Kentina je blíž 1–4 uzlům, 4–32 GPU celkem a 2–6 uživatelům, kteří se navzájem znají a domluví se na Slacku. Pro takové nasazení scheduler nepotřebujete.
# user 1
ssh node01
tmux new -s my-training
CUDA_VISIBLE_DEVICES=0,1,2,3 python train.py
# Ctrl-B D to detach
# user 2 — coordinates on Slack first
ssh node01
nvidia-smi # which GPUs are free?
tmux new -s other-training
CUDA_VISIBLE_DEVICES=4,5,6,7 python train.py
A to je celý systém plánování úloh. SLURM se začne vyplácet zhruba od 16 GPU nebo 8 uživatelů, podle toho, co nastane dřív. Pod touto hranicí provozní režie převáží přínos. Scheduler instalujte, až když selhává lidská koordinace, ne dřív.
Kdy se který nástroj hodí — shrnutí
| Scénář | Doporučení |
|---|---|
| 1–2 uzly, 4–16 GPU, 2–6 uživatelů, kteří spolu mluví | SSH + tmux + nvidia-smi. Žádný scheduler. |
| Výzkumná laboratoř, 4–32 uzlů, dávkové trénovací úlohy | SLURM. Nudný, prověřený, sedne. |
| Inferenční platforma obsluhující zákaznický provoz | Kubernetes + GPU Operator. Žádný dávkový scheduler. |
| Smíšený cluster: trénink + inference + nástroje | Kubernetes + Kueue + Volcano + Kubeflow. |
| Hodně distribuovaného Pythonu: RL, hledání hyperparametrů | Ray (nebo KubeRay) nad SLURMem nebo K8s. |
| 10+ ML týmů soupeří o GPU, rozpočet na nástroje | Run:ai na Kubernetes. |
| Spravované trénovací experimenty + sledování | Determined.AI. |
| 200+ GPU, více týmů, více workloadů | Federovaně: SLURM na dávky, K8s na služby. |
Co dělat dál — rozhodovací strom
Projděte to po pořádku. První „ano“ debatu ukončuje.
- Méně než 16 GPU a méně než 8 uživatelů, kteří spolu mluví? Ano → žádný scheduler. Sepište konvence do markdown souboru. Vraťte se k tomu, až koordinace přestane fungovat.
- Běží na clusteru kromě tréninku i dlouho běžící inferenční služby? Ano → základem je Kubernetes. Přidejte GPU Operator, pak Kueue a pak Volcano, pokud je ve hře distribuovaný trénink. Ne → základem je SLURM.
- Máte platformový tým nebo rozpočet na něj (0.5–1.0 FTE po dobu šesti měsíců, 0.25 FTE v ustáleném stavu)? Ne → zůstaňte u SLURMu bez ohledu na mix workloadů. Daň za K8s je reálná.
- >10 týmů soupeří o čas na GPU s přísnými nároky na kvóty? Ano → zvažte Run:ai. Ne → Kueue a kohorty Vás dostanou z 80 % tam, kam potřebujete.
-
Workload těžký na RL, hledání hyperparametrů nebo distribuovaný Python? Ano → Ray (KubeRay na K8s, nebo
salloc+ Ray na SLURMu). Ne → Ray vynechte. - Hardware s podporou MIG (datacentrové karty)? V nabídce Kentino ne → počítejte s alokací celých GPU nebo s time-slicingem jen pro vývoj. Nestavte návrh na MIG.
Většina konverzací v Kentinu končí u kroku 1, 2 nebo 3. Zbytek je dekorace.
Související články: distribuovaný trénink v K02, inferenční clustery v K03, úložiště clusteru v K04, řešení výpadků v K06, strop propustnosti PCIe v K07.
Tohle je součást Kentino Wiki, referenční série o AI výpočtech, robotice a systémech, které je spojují. Komentáře a opravy uvítáme na info@kentino.com.