مقدمه: فراتر از میکروسرویسهای استاندارد
سیستمهای استنتاج مدلهای زبانی بزرگ (LLM) تحت محدودیتهای منحصربهفردی عمل میکنند که با میکروسرویسهای سنتی متفاوت است. برخلاف APIهای وب بدون حالت، نقاط پایانی LLM به شدت به حافظه محدود GPU برای مدیریت کش KV تکیه دارند و اغلب اتصالات طولانیمدت را برای پاسخهای پخش زنده (Streaming) حفظ میکنند. این وابستگی به سختافزار تخصصی باعث میشود که روشهای استاندارد مهندسی آشوب ناکافی باشند. ما نمیتوانیم به سادگی یک کانتینر را از بین ببریم؛ باید وضعیت موجود در VRAM، هزینه بازسازی مدل و افزایش تأخیر ناشی از چرخههای ریست GPU را در نظر بگیریم.
در این پست، ما بررسی میکنیم که چگونه آزمایشهای آشوب را طوری طراحی کنیم که به طور خاص خرابیهای GPU و تقسیمات شبکه را هدف قرار دهند. هدف این است که فراتر از «آن بالا میآید» حرکت کنیم و به «آن با تأخیر قابل قبول و بدون از دست رفتن داده برای کلاینتهای پخش زنده بالا میآید» برسیم.
سناریو ۱: شبیهسازی خرابی ناگهانی GPU
یک حالت خرابی رایج در محیط تولید، افت GPU از باس PCI به دلیل محدودسازی حرارتی یا کرش درایور است. در محیطهای Kubernetes که از درایورهای NVIDIA استفاده میکنند، این موضوع اغلب به صورت کوردون شدن (cordon) یک نود یا کرش شدن پاد با خطای `SIGBUS` خود را نشان میدهد.
برای آزمایش این موضوع، ما نیاز داریم که از دست رفتن دستگاه محاسباتی را بدون لزوم راهاندازی مجدد کل نود شبیهسازی کنیم، زیرا زمان واکنش ارکستراتور میتواند مدیریت خطای داخلی برنامه را پنهان کند.
ما میتوانیم از `nvidia-smi` در ترکیب با فراخوانیهای سیستمی برای شبیهسازی این موضوع استفاده کنیم، یا عملیتر، یک کرش را در فرآیند سرور استنتاج در حالی که GPU تحت بار است، تزریق کنیم.
#!/bin/bash
# chaos_gpu_crash.sh
# Injects a SIGBUS into the inference process to simulate GPU access failure
PID=$(pgrep -f "vllm.engine" | head -n 1)
if [ -z "$PID" ]; then
echo "Inference process not found"
exit 1
fi
echo "Simulating GPU memory access failure on PID $PID"
# SIGBUS is often raised when memory is unmapped, simulating a VRAM access error
kill -BUS $PID
**معیارهای کلیدی برای پایش:**
* **تأخیر شروع سرد (Cold Start):** چقدر طول میکشد تا درخواست بعدی توسط یک رپلیکا سالم سرویس شود؟
* **رفتار تکرار کلاینت (Client Retry):** آیا بار均衡گرها (Load Balancers) یا کلاینتهای شما بلافاصله تکرار میکنند؟ اگر بله، آیا با صف انتظار، نودهای سالم باقیمانده را غرق میکنید؟
* **از دست رفتن کش KV:** تأیید کنید که هر تولید ناقص در حال انجام به درستی خاتمه مییابد یا اگر توسط فریمورک شما پشتیبانی میشود، از یک چکپوینت از سر گرفته میشود.
سناریو ۲: تقسیمات شبکه و نودهای عقبمانده
در تنظیمات استنتاج توزیعشده (مثلاً با استفاده از DeepSpeed یا موازیسازی تانسور vLLM)، تقسیم شبکه حیاتی است. اگر یک نود در یک گروه موازیسازی تانسور اتصال خود را از دست بدهد، کل دسته استنتاج (inference batch) شکست میخورد. با این حال، در یک معماری تفکیکشده (جداسازی Prefill از Decode)، یک تقسیم بین بار均衡گر فرانتاند و کارگرهای استنتاج علائم متفاوتی ایجاد میکند.
بیایید یک تقسیم شبکه را شبیهسازی کنیم که در آن بکاند استنتاج در دسترس نباشد اما دروازه API (API Gateway) بالا بماند.
# Use tc (traffic control) to introduce 100% packet loss to the inference backend pod
# This simulates a network partition without dropping the node entirely
POD_IP=$(kubectl get pod -l app=inference-backend -o jsonpath='{.items[0].status.podIP}')
# Drop all traffic destined for the inference backend
kubectl exec -it [gateway-pod] -- tc qdisc add dev eth0 root netem loss 100%
# Wait for the chaos window
sleep 30
# Restore traffic
kubectl exec -it [gateway-pod] -- tc qdisc del dev eth0 root
**رفتار مورد انتظار:**
1. دروازه API باید درخواستها را درون زمانبندیشده `proxy_read_timeout` (مثلاً ۵ ثانیه) منقضی کند.
2. دروازه باید در صورت موجود بودن، سریعاً به رپلیکاهای جایگزین شکست بخورد (fail-fast).
3. **به طور حیاتی:** برای پاسخهای پخش زنده (SSE)، کلاینت باید اتصال بسته را تشخیص دهد. آزمایش کنید که آیا کد سمت کلاینت شما به درستی یک قطع در میانه جریان را مدیریت کرده و پرامپت را مجدداً در صف قرار میدهد، یا اینکه به صورت خاموش شکست میخورد و منجر به کلافگی کاربر میشود.
پیادهسازی آزمایشهای آشوب خودکار در CI/CD
آزمایش آشوب دستی پایدار نیست. این سناریوها را با استفاده از ابزارهایی مانند LitmusChaos یا Chaos Mesh در خط لوله استیجینگ خود یکپارچه کنید.
apiVersion: litmuschaos.github.io/v1alpha1
kind: ChaosExperiment
metadata:
name: llm-gpu-chaos
spec:
appinfo:
appkind: deployment
labelselector: "app=vllm-server"
chaosConfig:
chaosKind: "pod-kill"
# Simulate a hard kill to trigger node-level GPU recovery
mode: "all"
duration: "120s"
**استراتژی اعتبارسنجی:**
فقط بررسی نکنید که آیا پاد راهاندازی مجدد میشود یا خیر. *کیفیت* سرویس را اعتبارسنجی کنید.
* **بررسی تأخیر P99:** تأیید کنید که تأخیر P99 در طول پنجره خرابی از ۲ برابر خط پایه فراتر نمیرود.
* **بررسی از دست رفتن توکن:** برای پخش زنده، تأیید کنید که تعداد کل توکنهای دریافتی توسط کلاینت با تعداد مورد انتظار مطابقت دارد یا اینکه یک خطای تمیز برگردانده میشود، به جای یک پاسخ ناقص و خراب.
نتیجهگیری
استنتاج LLM فقط یک سرویس بدون حالت دیگر نیست. حالتدار بودن آن در VRAM، ردپای حافظه بالا و ماهیت پخش زنده طولانیمدت آن، به یک رویکرد تخصصی در مهندسی آشوب نیاز دارد. با شبیهسازی خرابیهای GPU و تقسیمات شبکه، میتوانید شکافهای حیاتی در منطق تکرار، استراتژیهای بار均衡 و مدیریت خطای سمت کلاینت خود را کشف کنید. کوچک شروع کنید: یک کرش GPU را در استیجینگ تزریق کنید. شعاع انفجار (Blast Radius) را پایش کنید. تکرار کنید. مقاومت از طریق شکست عمدی ساخته میشود.
<<<