به گزارش از وبسایت cncf، تخصیص منابع پویا (DRA) در Kubernetes نسخه 1.35 به وضعیت GA رسیده و بسیاری از افراد علاقهمند به آزمایش آن هستند. NVIDIA نیز در کنار پیشرفتهای خود، dra-driver-nvidia-gpu را به SIG مربوط به Kubernetes منتقل کرده و برچسب بتا را از مستندات حذف نموده که نشاندهنده بلوغ روزافزون این فناوری و استانداردهای مرتبط است. من در این پست از GPUهای موجود در آزمایشگاههای CNTUG Infra قرض گرفتم تا نحوه تخصیص دستگاهها و منابع با DRA را عملیاتی بررسی کنم. 🚀
آزمایشگاههای CNTUG Infra: مروری بر محیط آزمایشگاهی
CNTUG Infra Labs به منظور پرورش نسل بعدی دانشجویان و مهندسان زیرساخت نرمافزاری در تایوان راهاندازی شده است. این آزمایشگاه در دیتاسنتر Equinix توکیو میزبانی میشود و توسط چند عضو جامعه CNTUG پشتیبانی مالی میشود. راهاندازی محیط متکی بر مجموعهای از پروژههای متنباز مانند OpenStack، Ceph و Ansible است. از آنجا که نرمافزارهای زیرساختی نیازمند منابع محاسباتی، ذخیرهسازی و شبکه زیاد و همچنین دارای منحنی یادگیری بالا هستند، هدف CNTUG Infra Labs فراهم آوردن یک پلتفرم ابری برای آزمایش و میزبانی سرویسها توسط دانشجویان و اعضای جامعه است. ظرفیت اضافی نیز برای میزبانی سرویسهای عمومی مانند وبسایتها، Mattermost و Jitsi Meet یا رویدادهای کارگاهی در اختیار قرار میگیرد.
خوشه آزمایشی ما با استفاده از Cluster API + OpenStack ساخته شده است. برای اجتناب از طولانی شدن پست، مراحل راهاندازی اینجا آورده نشده است — برای جزئیات بیشتر میتوانید به دیگر پستهای وبلاگ مراجعه کنید یا منتظر پست بعدی باشید. 🙂
مشخصات سیستم:
System OS: Ubuntu 24.04 Kubernetes: v1.35.3 Containerd: 2.2.2 Nodes: 1 Control Plane + etcd, 3 Workers (No GPU), T10 * 2, A5000 * 1 NVIDIA GPU Operator: v26.3.1 NVIDIA DRA Driver GPU: v25.12
پس از بالا آمدن خوشه باید چیزی شبیهِ خروجی زیر را ببینید:
STATUS ROLES AGE VERSION capi-dralabs-control-plane-xtcth Ready control-plane 8m7s v1.35.3 capi-dralabs-md-0-p4xkh-rpfxc Ready 6m55s v1.35.3 capi-dralabs-md-xpua-djw4 Ready 2m37s v1.35.3 capi-dralabs-md-gput10-gzl84-f2m2d Ready 6m49s v1.35.3
نصب NVIDIA GPU Operator
قبل از نصب operator، گرههایی که GPU دارند را برچسب بزنید. برای محیط من این کار به شکل زیر انجام شد:
kubectl label node capi-dralabs-md-gpua5000-jw4mx-d64jz nvidia.com/dra-kubelet-plugin=true kubectl label node capi-dralabs-md-gput10-gzl24-f nvidia.com/dra-kubelet-plugin=true
مخزن Helm NVIDIA را اضافه کنید و بهروزرسانی کنید:
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia helm repo update
یک فایل values برای نصب GPU Operator ایجاد کنید (نمونهی خلاصه شده):
values-gpu-operator.yaml
manager:
env:
- name: NODE_LABEL_FOR_GPU_POD_EVICTION
value: "nvidia.com/dra-kubelet-plugin"
# توجه: اگر از توزیع دیگری مانند Rancher یا K3s استفاده میکنید،
# مسیر socket مربوط به containerd ممکن است متفاوت باشد:
CONTAINERD_SOCKET: /run/k3s/containerd/containerd.sock
حال GPU Operator را نصب کنید:
helm upgrade --install gpu-operator nvidia/gpu-operator --version=v26.3.1 --create-namespace --namespace nvidia
Operator پس از اجرا، درایور GPU را نصب کرده و تنظیمات Container Runtime را تغییر میدهد. برای تنظیمات خاصتر به اسناد رسمی NVIDIA مراجعه کنید.
نصب NVIDIA DRA Driver
یک فایل values برای nvidia-dra-driver-gpu بسازید:
values-nvidia-dra-driver-gpu.yaml
# version: 25.12.0
nvidiaDriverRoot: /run/nvidia/driver
kubeletPlugin:
nodeSelector:
nvidia.com/dra-kubelet-plugin: "true"
resources:
gpus:
enabled: true
computeDomains:
enabled: false # NVLink موجود نیست
# featureGates:
# TimeSlicingSettings: true # فعال کنید اگر میخواهید SPU را زمانبندی کنید
درایور NVIDIA DRA را نصب کنید:
helm upgrade -i nvidia-dra-driver-gpu nvidia/nvidia-dra-driver-gpu --version="25.12.0" --namespace nvidia-dra-driver-gpu --create-namespace -f values-nvidia-dra-driver-gpu.yaml
برای تأیید وضعیت Podهای در namespace مربوطه از دستور زیر استفاده کنید:
kubectl get pod -n nvidia-dra-driver-gpu NAME READY STATUS RESTARTS AGE ... 1/1 Running 0 10m
نگاهی اولیه به DRA DeviceClass
پس از نصب، مشاهده خواهید کرد که DeviceClass و ResourceSlice توسط NVIDIA DRA Driver راهاندازی شدهاند. DeviceClass نمایشدهنده دستهبندی دستگاهها است — برای مثال gpu.nvidia.com، mig.nvidia.com و vfio.gpu.nvidia.com. (اگر computeDomains فعال باشد، اطلاعات مرتبط نیز ظاهر میشود.)
kubectl get deviceclass NAME AGE gpu.nvidia.com 44m mig.nvidia.com 44m vfio.gpu.nvidia.com 44m
Driver بهطور خودکار ResourceSliceها را برای دستگاههایی که آن گره را مدیریت میکنند ایجاد میکند. دستگاههای مربوط به یک گره که توسط یک درایور مدیریت میشوند، در یک Pool قرار میگیرند. اگر تعداد دستگاهها از حدی که در یک شیء گنجانده میشود بیشتر شود (تا 128 ورودی، یا 64 در صورت استفاده از برخی ویژگیها)، درایور Pool را به چند ResourceSlice تقسیم میکند. فیلدهای .spec.pool.generation و .spec.pool.resourceSliceCount به scheduler کمک میکنند تا بفهمند آیا فهرست دستگاهها کامل و بهروز است یا خیر.
نمونه خروجی ResourceSlice:
kubectl get resourceslices NAME NODE DRIVER POOL AGE capi-dralabs-md-gpua5000-jw4mx-d64jz-gpu.nvidia.com-w9fnv capi-dralabs-md-gpua5000-jw4mx-d64jz gpu.nvidia.com 1 5m13s capi-dralabs-md-gput10-gzl84-f2m2d-gpu.nvidia.com-dtgtc capi-dralabs-md-gput10-gzl84-f2m2d gpu.nvidia.com 1 23m
برای دیدن محتوای کامل میتوانید از خروجی YAML استفاده کنید:
kubectl get resourceslices -o yaml
هر ResourceSlice شامل مرجع مالک (.metadata.ownerReferences) و فهرست دستگاهها در spec.devices است. هر دستگاه دارای ویژگیهایی مانند architecture، productName، driverVersion و غیره است. از آنجا که در آزمایشگاه ما هر گره حداکثر دو GPU دارد — بسیار کمتر از سقف 128 — هر گره فقط یک ResourceSlice تولید میکند.
نمونهای از خروجی کامل ResourceSlice (خلاصهشده):
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: capi-dralabs-md-gpua5000-jw4mx-d64jz-gpu.nvidia.com-w9fnv
generation: 1
spec:
devices:
- name: gpu-0
driver: gpu.nvidia.com
nodeName: capi-dralabs-md-gpua5000-jw4mx-d64jz
uuid: GPU-e13ce856-...
productName: NvidiaRTX
driverVersion: "580.126.20"
capacity:
memory:
value: 23028Mi
pool:
name: capi-dralabs-md-gpua5000-jw4mx-d64jz
generation: 1
چگونه یک Pod به Kubernetes اعلام میکند که به کدام دستگاه نیاز دارد؟ اینجا ResourceClaim و ResourceClaimTemplate وارد عمل میشوند.
ResourceClaim & ResourceClaimTemplate
اگر بخواهید چند Pod یک دستگاه را به اشتراک بگذارند، میتوانید یک ResourceClaim بهطور دستی ایجاد کنید که مستقل از چرخه عمر Podها باقی میماند. اما چنانچه میخواهید هر Pod دستگاه اختصاصی خود را داشته باشد، از ResourceClaimTemplate استفاده کنید: هر زمان یک Pod جدید از یک Deployment به این template ارجاع دهد، یک ResourceClaim مرتبط برای آن Pod ساخته میشود و با حذف Pod، آن ResourceClaim نیز حذف خواهد شد. این مدل مشابهٔ نحوه کار PersistentVolumeClaim و PersistentVolumeClaimTemplate در Storage است؛ DeviceClass نقش StorageClass را بازی میکند.
مثال سناریوی دستی با DRA — سناریو I: دو کانتینر که یک GPU را به اشتراک میگذارند
ابتدا یک ResourceClaim تعریف میکنیم که نشان دهد به یک GPU نیاز داریم:
lab01-rc.yaml
apiVersion: resource.k8s.io/v1
kind: ResourceClaim
metadata:
name: must-nvidia-gpu
spec:
devices:
requests:
- name: gpu
exactly:
deviceClassName: gpu.nvidia.com
count: 1
اعمال ResourceClaim:
kubectl apply -f lab01-rc.yaml kubectl get resourceclaim NAME STATE AGE must-nvidia-gpu pending 10s
اکنون میتوان یک Pod با دو کانتینر ایجاد کرد که هر دو از همان ResourceClaim استفاده کنند تا GPU را به اشتراک بگذارند — ادامه این سناریو در بخشهای بعدی قابل تکمیل است. 😊