صف‌های معلق؛ مشکل آشنا برای تیم‌های پلتفرم

هر دوشنبه صبح فهرستی از باقی‌مانده‌های آخر هفته جلوی مهندس نوبت‌کار قرار دارد: آموزش‌ها با خطای OOM مواجه می‌شوند و پادهای استنتاج به‌خاطر تمام شدن برش‌های کوچک MIG در وضعیتی معلق می‌مانند، در حالی که کارت‌های بزرگ‌تر بی‌استفاده کنار گذاشته شده‌اند. تیم برای رفع این بی‌توازنی یک اسکریپت Bash حدود ۲۰۰ خطی نوشته بود که هر ۳۰ دقیقه پروفایل‌های MIG را بازپیکربندی و پادهای گیرکرده را مجدداً زمان‌بندی می‌کرد؛ راه‌حلی پراکنده، شکننده و پرهزینه از لحاظ نگهداری.

ریشهٔ مشکل: کوبرنتیز و مدل منابع صلب

تا قبل از نسخهٔ 1.34، کوبرنتیز GPU را به‌عنوان یک منبع همسان در نظر می‌گرفت (مثلاً nvidia.com/gpu: 1). زمان‌بندی‌کننده قادر نبود تشخیص دهد آن «1» اشاره به یک B200 با 192Gi حافظه دارد یا یک H100 با 80Gi. نتیجه این شد که بارهای با نیاز حافظهٔ بالا روی گره‌های ناکافی قرار می‌گرفتند و گره‌های مناسب بیکار می‌ماندند. راهبردهای رایج مانند استخرهای گره جدا، برچسب‌گذاری، taint و toleration باعث پیچیده‌شدن مانیفست‌ها و نیاز به به‌روزرسانی گستردهٔ Helm chartها هنگام معرفی نسل جدید GPU شدند.

وقتی MIG اوضاع را پیچیده‌تر کرد

MIG (Multi-Instance GPU) امکان تقسیم یک کارت به برش‌های ایزوله با حافظه و محاسبات اختصاصی را فراهم کرد؛ ایده‌ای موثر برای افزایش بهره‌وری. اما در مدل قدیمی کوبرنتیز هر پروفایل MIG به‌عنوان یک نوع منبع جداگانه ثبت می‌شد (مثلاً nvidia.com/mig-1g.10gb). نبود منطق جایگزینی به این معنا بود که اگر برش‌های کوچک پر می‌شدند، پادها معلق می‌ماندند حتی وقتی برش‌های بزرگ‌تر خالی بودند—اتلاف ظرفیت و تشکیل صف‌های طولانی.

تغییر بازی: تخصیص پویا منابع (DRA)

از نسخهٔ 1.34 به بعد، مدل زمان‌بندی تغییر کرد: درایورهای GPU می‌توانند اطلاعات ساخت‌یافته منتشر کنند و دیگر نیازی نیست صرفاً از nvidia.com/gpu: 1 استفاده شود. تأمین منابع با استفاده از Common Expression Language (CEL) ممکن شد؛ به این معنی که می‌توان نیّت دقیق را بیان کرد؛ برای مثال «یک H100 یا بهتر با حداقل 40Gi حافظه»، یا «ابتدا برش کوچک MIG، در صورت نبود آن برش متوسط، و در نهایت GPU کامل»، یا «چهار GPU متصل با NVLink». مستندات رسمی کوبرنتیز نیز در سایت رسمی در دسترس است.

مثال: نیاز سخت‌افزاری و حافظه

apiVersion: resource.k8s.io/v1
kind: ResourceClaimTemplate
metadata:
  name: h100-or-better-40gb
spec:
  spec:
    devices:
      requests:
      - name: gpu
        deviceClassName: gpu.nvidia.com
        count: 1
        selectors:
        - cel:
            expression: >
              device.attributes["gpu.nvidia.com"].memory >= quantity("40Gi") &&
              device.attributes["gpu.nvidia.com"].generation in ["H100", "B200", "B300"]
---
apiVersion: batch/v1
kind: Job
metadata:
  name: training-job-h100-or-better
spec:
  template:
    spec:
      restartPolicy: Never
      resourceClaims:
      - name: gpu
        source:
          resourceClaimTemplateName: h100-or-better-40gb
      containers:
      - name: trainer
        image: nvcr.io/nvidia/pytorch:24.12-py3
        command: ["python", "train.py"]
        resources:
          claims:
          - name: gpu

مثال: اولویت‌دهی انعطاف‌پذیر MIG

apiVersion: resource.k8s.io/v1
kind: ResourceClaimTemplate
metadata:
  name: mig-prefer-small-then-medium-then-full
spec:
  spec:
    devices:
      requests:
      - name: gpu
        deviceClassName: gpu.nvidia.com
        count: 1
        selectors:
        - cel:
            expression: >
              device.attributes["gpu.nvidia.com"].profile in [
                "mig-1g.10gb",
                "mig-2g.20gb",
                "mig-3g.40gb",
                "full-gpu"
              ]
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: inference-service-flexible-gpu
spec:
  replicas: 2
  selector:
    matchLabels:
      app: inference-service
  template:
    metadata:
      labels:
        app: inference-service
    spec:
      resourceClaims:
      - name: gpu
        source:
          resourceClaimTemplateName: mig-prefer-small-then-medium-then-full
      containers:
      - name: inference
        image: my-inference-image:latest
        resources:
          claims:
          - name: gpu
نمایی از کارت‌های GPU در یک رک سرور

چه چیزی تغییر می‌کند و چه فایده‌هایی دارد

  • کاهش وابستگی به اسکریپت‌های دست‌ساز: نیاز به پچ‌های دوره‌ای و کران‌کاری‌های بازپیکربندی به طور چشمگیری کم می‌شود.
  • بهبود استفاده از ظرفیت: زمان‌بندی‌کننده می‌تواند منابع جایگزین مناسب را پیشنهاد دهد و از هدررفتن کارت‌ها جلوگیری کند.
  • سادگی در مانیفست‌ها: به جای پراکندگی شرط‌ها در Helm chartها، نیّت در قالب CEL متمرکز نوشته می‌شود و نگهداری آسان‌تر می‌شود.
  • پشتیبانی از توپولوژی‌های پیچیده: درخواست‌های مرتبط با NVLink یا اتصالات خاص سخت‌افزاری قابل بیان و تحقق‌اند (برای جزئیات به NVLink مراجعه کنید).

آیندهٔ استقرار GPU روی کوبرنتیز

DRA مدیریت GPU در محیط‌های کانتینری را از سطح سخت‌افزار به بیان نیاز واقعی منتقل می‌کند. خوشه‌هایی که شامل نسل‌های مختلف GPU هستند اکنون می‌توانند سیاست‌های زمان‌بندی دقیق‌تری تعریف کنند، صف‌ها را کوتاه‌تر کنند و از ظرفیت سرمایه‌گذاری‌شده بهرهٔ بیشتری ببرند. برای اطلاعات بیشتر دربارهٔ پیاده‌سازی DRA و درایورهای تولیدکننده، اسناد رسمی کوبرنتیز و مستندات NVIDIA راهنمای مفیدی هستند.

گام بعدی: تیم‌های اپلیکیشن و زیرساخت باید مانیفست‌ها را بازبینی و به‌روزرسانی کنند؛ تأثیر مستقیم این کار کاهش هزینه‌های عملیاتی و افزایش بهره‌وری GPUها خواهد بود—و این فقط آغاز مسیر است.