بازگشت به بلاگ
Infra

اجرای LLM روی Kubernetes با تأخیر زیر ۵۰ میلی‌ثانیه

14 دقیقه مطالعه

معماری پایه

یک Deployment در Kubernetes پشتِ یک Service از نوع ClusterIP که یک Ingress جلویش قرار گرفته. تا حدود ۵۰ درخواست بر ثانیه برای یک مدل کوچک خوب کار می‌کند. اما وقتی ترافیک ناگهان بالا می‌رود، یا زمان‌بندی pod‌های GPU سه دقیقه طول می‌کشد، یا سرور مدل دو ثانیه cold-start دارد، از هم می‌پاشد.

مقیاس خودکار با KEDA

HPA (مقیاس‌گذار افقی pod) بر اساس CPU و حافظه مقیاس می‌دهد. اما استنتاج LLM به GPU و عمق صف وابسته است و هیچ‌کدام با مصرف CPU خوب نگاشت نمی‌شوند.

KEDA (مقیاس خودکار رویدادمحور Kubernetes) بر اساس هر معیار دلخواهی مقیاس می‌دهد؛ عمق صف، تأخیر Pub/Sub، طول لیست Redis. ما تعداد درخواست‌های استنتاج را در یک stream در Redis منتشر می‌کنیم؛ KEDA وقتی عمق stream از یک آستانه عبور کند pod‌های سرور مدل را مقیاس می‌دهد. تأخیر مقیاس‌گرفتن از چند دقیقه (cold-start مقیاس‌گذار خوشه) به چند ثانیه (افزایش replica از ۱ به N) می‌رسد.

اشتراک GPU با time-slicing

برای مدل‌هایی که در ۴ تا ۸ گیگابایت VRAM جا می‌شوند، اختصاص کاملِ GPU اسراف است. فناوری time-slicing و MIG انویدیا (GPU چنداینستنسه) اجازه می‌دهد چند pod یک A100 را به اشتراک بگذارند و هرکدام یک سهم تضمین‌شده بگیرند.

nvidia.com/gpu: 1 را تنظیم کنید و پروفایل time-slice را روی 1g.10gb بگذارید. یک A100 هشتادگیگابایتی می‌تواند ۸ اینستنس مدل را هم‌زمان، هرکدام با ۱۰ گیگابایت، سرویس بدهد؛ یعنی ۸ برابرِ توان عبوری به ازای هر GPU.

hedging درخواست برای تأخیر دنباله

تأخیر p50 برابر ۱۲ میلی‌ثانیه است و p99 برابر ۲۸۰ میلی‌ثانیه. دنباله را عمدتاً miss‌های KV-cache و مکث‌های گاه‌به‌گاه GC می‌سازند. درخواست‌های hedged: بعد از ۴۰ میلی‌ثانیه یک درخواست تکراری به replica دوم بفرستید. هر پاسخی زودتر رسید همان را بردارید و دیگری را لغو کنید. این کار p99 را از ۲۸۰ به حدود ۴۵ میلی‌ثانیه می‌رساند، با تنها حدود ۱۵ درصد افزایش در کل محاسبات.