Tüm yazılar
Teknik
  • #systems
  • #k8s

Kubernetes'te GPU zamanlama

08.04.2026·6 dk

Kubernetes'te GPU zamanlama

Kubernetes · GPU Zamanlama

2 Mayıs 2026 · Üretim notları

Kubernetes CPU ve belleği akıcı şekilde böler; ama GPU söz konusu olduğunda varsayılan zamanlayıcı oldukça naiftir. Bir GPU ya tamamen bir pod'a aittir ya da değildir. Üretimde GPU faturasını düşürmek, işte bu kaba taneliliği aşmakla başlar. Bunun yolu da yeni kart almaktan değil, zamanlayıcıya doğru ipuçlarını vermekten geçer.

Varsayılan
ya hep ya hiç
Kaldıraç
MIG · time-slicing
Yerleştirme
taint · affinity
Sonuç
%18 → %71 kullanım

Bu yazıdaki kavramlar

  • device plugin
  • MIG
  • time-slicing
  • taints & tolerations
  • node affinity
  • NVLink topolojisi
  • bin-packing

Bir GPU pahalıdır, ama asıl pahalı olan boşta bekleyen GPU'dur. Küçük bir çıkarım servisi koca bir A100'ü kapar, aylarca %12 kullanımla durur. Kubernetes'in varsayılan davranışı bu israfı görmez bile, çünkü onun gözünde GPU bölünemez bir bütündür.

Aşağıda problemi ve pratikte işe yarayan dört kaldıracı sırayla çizdim: zamanlayıcının GPU'yu nasıl gördüğü, kartı bölmenin iki yolu (MIG ve time-slicing), işleri doğru düğüme yerleştirmek (taint/affinity) ve son olarak topoloji. Bir şeyi gerçekten anlatan animasyonların köşesinde nazik bir ↻ tekrar düğmesi var.

01/08

Sorun: ya hep ya hiç

device plugin modeli bir GPU'yu bölünmez bir kaynak olarak sunar: pod ya tam bir kart ister ya da hiç. Küçük bir çıkarım servisi 80 GB'lık bir A100'ün belki 8 GB belleğini ve hesaplama biriminin (SM) küçük bir kısmını kullanır, ama kartın tamamını rezerve eder. Geri kalan her şey 'belki lazım olur' diye boşta bekler.

tek pod, koca kart
1× NVIDIA A100≈ %88 boşta

Bellek · 80 GB

8GB
boşta

Hesaplama · 108 SM

13
boşta
çıkarım servisi · 1 podrezerve: tüm kart

Birden fazla küçük iş aynı kartı paylaşamadığı için kümeyi büyütmek tek çare gibi görünür, oysa değildir. Çözüm, aynı kartı güvenli biçimde bölmek ve işleri akıllıca yerleştirmektir.

02/08

Zamanlayıcı GPU'yu nasıl görür

GPU'lar Kubernetes'e bir device plugin üzerinden tanıtılır. Plugin düğümdeki kartları sayar ve kubelet'e bildirir; kubelet bunu düğümün kapasitesine yazar; API sunucusu allocatable olarak tutar; zamanlayıcı da pod'un istediği kadar tam birim olan bir düğüm arar ve pod'u oraya bağlar.

zamanlama hattı
device pluginkubeletAPI serverscheduler

Düğümdeki 8 fiziksel GPU bu zincirden geçer ve düğümün 'allocatable' sayısı olur: 8.

GPU düğümüboş: 5·kullanımda: 3 / 8
GPU
GPU
GPU
GPU
GPU
GPU
GPU
GPU
pod · 1 GPU isterbir tam GPU'yu kapar

Kaynak bir tam sayı: pod 1, 2, … tam GPU alır; 0.3 GPU istenemez.

Püf nokta şu: bu kaynak bir tam sayıdır. Yarım GPU diye bir şey yoktur; zamanlayıcı '0.3 GPU' ayıramaz. Kartı bölmek, ya bu tam sayının ne anlama geldiğini değiştirmek (MIG) ya da aynı birimi zaman içinde birden çok pod'a dağıtmaktır (time-slicing).

03/08

MIG ile donanımda bölmek

A100/H100'de Multi-Instance GPU (MIG), kartı donanım seviyesinde izole dilimlere ayırır. Her dilimin kendi hesaplama bölmeleri, kendi bellek dilimi ve kendi bellek yol genişliği vardır. Bir A100 yedi adede kadar bağımsız örneğe bölünebilir; en yaygın profil 1g.5gb'tir (kartın 1/7 hesaplaması, 5 GB bellek).

MIG bölümleme (mekânsal)

MIG kapalı

bütün A100 · tek kiracı

1 kart = 1 pod

MIG açık · 7× 1g.5gb

1
2
3
4
5
6
7

1 kart = 7 izole örnek, hepsi aynı anda

çıkarımeğitimnotebookbatchrerankAPIyedek

her dilim ≈ kartın 1/7'i: ~14 SM hesaplama + 5 GB bellek

Önemli olan izolasyon: dilimler birbirinin performansını etkilemez, 'komşu gürültüsü' yoktur, gecikme tahmin edilebilir kalır. Her dilim Kubernetes'e ayrı bir kaynak olarak görünür, yani zamanlayıcı tek bir karta yedi farklı pod yerleştirebilir; hepsi de aynı anda çalışır. MIG mekânı böler.

04/08

Time-slicing: zamanı paylaşmak

İzolasyon gerekmeyen, ani ve aralıklı işler için daha ucuz bir yol var: time-slicing. Tek bir GPU birden çok pod tarafından paylaşılır, ama mekânda değil zamanda: kart işleri sırayla, küçük zaman dilimleri (quanta) halinde çalıştırır. Aşağıdaki zaman ekseninde imleç ilerledikçe, her an yalnızca tek bir işin GPU'da olduğunu görebilirsin.

zaman ekseni (sıralı)
iş A
iş B
iş C
GPU
zaman →
her an yalnızca tek iş çalışır bağlam değişimi

Bedeli şudur: gerçek izolasyon yoktur. Bir iş kartı kötü kullanırsa diğerlerini yavaşlatır ve her geçişte küçük bir bağlam değişimi (context switch) maliyeti vardır. Ani yükler için harika, gecikmeye duyarlı üretim trafiği için riskli. MIG mekânı böler, time-slicing zamanı.

Kubernetes'te GPU verimliliği bir zamanlama problemidir. Zamanlayıcıya doğru ipuçlarını vermek, donanım almaktan çok daha ucuzdur.
05/08

MIG mı, time-slicing mi?

İkisi de tek kartı çok işe açar, ama farklı söz verir. Karar tek soruya iner: bu işler birbirine güvenebilir mi?

MIG
time-slicing
izolasyon
donanım · tam
yok · paylaşımlı
performans
tahmin edilebilir
komşuya bağlı
bölme
mekânsal
zamansal
en uygun
üretim / kiracılar
ani / dev-test
06/08

İşi doğru düğüme koymak

Kartı böldün; peki pod doğru makineye nasıl gider? İki mekanizma birlikte çalışır. taint, pahalı GPU düğümüne bir 'giriş yasak' etiketi asar; yalnızca o taint'i tolere eden (toleration taşıyan) pod'lar oraya inebilir. node affinity ise pod'u GPU etiketli düğümlere doğru çeker.

zamanlayıcının kararı

Zamanlayıcı, taint ile toleration'ı eşleştirerek her pod'u doğru düğüme koyar:

GPU düğümütaint gpu=true:NoSchedule
GPU podtoleration ✓ · affinity a100

taint'i tolere eder, affinity çeker → girer

CPU düğümü
CPU podtoleration yok

taint'i tolere edemez → giremez, buraya düşer

taint = itme affinity = çekme

Yani taint itme, affinity çekme kuvvetidir. Sonuç: GPU pod'u (tolerasyon + affinity ile) GPU düğümüne yerleşir; tolerasyonu olmayan CPU pod'u oraya giremez ve CPU düğümüne düşer. Böylece kaçak CPU işleri pahalı kartların üstüne düşmez.

07/08

Topoloji: NVLink mi, PCIe mi?

Çok-GPU'lu işlerde kartların birbirine nasıl bağlandığı throughput'u belirler. NVLink'le bağlı kartlar birbirleriyle çok hızlı konuşur; PCIe üzerinden konuşmak ise kat kat yavaştır. Bir eğitim işinin her adımdaki all-reduce'u bu bağlantının üstünden akar.

veri yolu: NVLink vs PCIe
doğru: tek ada içinde

NVLink adası A

GPU
GPU
GPU
GPU
NVLink · ~600 GB/s
PCIe · ~32 GB/s
boşta

NVLink adası B

GPU
GPU
GPU
GPU
boşta

all-reduce NVLink üstünde uçar

yanlış: adalara bölünmüş

NVLink adası A

GPU
GPU
GPU
GPU
NVLink · ~600 GB/s
PCIe · ~32 GB/s
⚠ darboğaz

NVLink adası B

GPU
GPU
GPU
GPU
NVLink · ~600 GB/s

PCIe darboğazı

İşte bu yüzden topology-aware scheduling önemli: çok-GPU işlerini NVLink'le bağlı kartlara (aynı adaya) denk getirirsin. Aşağıda aynı dört-GPU'lu iş iki türlü yerleştiriliyor: doğru yerleştirmede veri tek ada içinde NVLink üzerinden uçuyor; yanlış yerleştirmede adalara bölünüp PCIe'ye mahkûm oluyor.

08/08

Toparlarsak

Kartı böl, işi doğru düğüme koy, topolojiye saygı duy. Üç hamle de kod değil, yapılandırmadır. Üçü birden, yeni bir GPU siparişi vermeden kapasiteni katlar.