VPA وضبط حجم الموارد
VPA وضبط حجم الموارد
يعمل HPA الأفقي عبر إضافة نسخ جديدة من الـ Pod. أما Vertical Pod Autoscaler (VPA) فيتبع نهجاً مختلفاً: يراقب الحِمل الفعلي للتطبيق عبر الزمن ثم يوصي — أو يُطبّق مباشرةً — بقيم أفضل لـ requests وlimits الخاصة بالـ CPU والذاكرة. على نطاق إنتاجي واسع، لا يُعدّ VPA اختيارياً. الـ Pods ذات الـ requests المُبالَغ فيها تُجوّع المُجدوِل من السعة القابلة للتخصيص؛ والـ Pods ذات الـ requests غير الكافية تصطدم بـ OOMKill أو تُكبَّل بالـ CPU throttling بما يعجز مع مؤشرات الأداء الزمني. إن ضبط الحجم الصحيح هو الطريقة التي تُستعاد بها 30-50% من تكلفة الـ Cluster دون تعديل سطر واحد من كود التطبيق.
آلية عمل VPA من الداخل
يتكوّن VPA من ثلاثة Controllers تعمل في نطاق kube-system (أو نطاق مخصص عند النشر عبر المانيفستات الرسمية):
- Recommender: يراقب باستمرار بيانات استخدام CPU والذاكرة عبر Metrics API ويبني توصية باستخدام المتوسط المتحرك المُرجَّح أسياً (EWMA). يأخذ في الحسبان ذروة الاستخدام أيضاً — فالتوصية تعلو عن الوسيط عمداً لاستيعاب الارتفاعات المفاجئة.
- Admission Controller (webhook): يعترض إنشاء الـ Pod ويُعدّل قيم الموارد عند الإنشاء. هذا هو مسار العمل في وضعَي
AutoوInitial. - Updater: في وضع
Auto، يُخلي (يُزيل) الـ Pods التي تنحرف قيم مواردها انحرافاً كبيراً عن التوصية، مما يتيح لـ Admission Controller إعادة كتابتها عند إعادة التشغيل. يحترم عملية الإخلاء قواعد PodDisruptionBudget.
Auto يُوجد حلقة تغذية راجعة: يرفع VPA قيمة CPU request، فينخفض نسبة الاستخدام المُلاحظة، فيُقلّص HPA عدد الـ Pods، فيتركّز الحِمل، فيرفع VPA التوصية من جديد. الحل الآمن هو تشغيل HPA على مقاييس مخصصة (معدل الطلبات، عمق الطابور) بينما يتولى VPA إدارة الـ requests والـ limits.
تثبيت VPA
VPA ليس مُضمَّناً في Kubernetes ويجب تثبيته من مستودع autoscaler. يستهدف التثبيت الافتراضي نطاق kube-system ويستخدم شهادة موقّعة ذاتياً لـ Admission Webhook.
أوضاع تحديث VPA
يتحكم حقل updatePolicy.updateMode في مدى تطبيق VPA لتوصياته بشكل مباشر. اختر الوضع المناسب بناءً على مدى تقبّل حِمل العمل لديك لإعادة تشغيل الـ Pod:
Off— يعمل Recommender ويكتب التوصيات في حالة VPA دون تطبيق أي شيء تلقائياً. استخدم هذا الوضع لأول 7-14 يوماً مع أي حِمل عمل جديد لمراجعة التوصيات قبل الوثوق بها.Initial— يُطبّق Admission Controller التوصيات عند إنشاء الـ Pod فقط. لا يُخلَى أي Pod موجود. آمن للأحمال ذات الحالة (Stateful) أو حين تكون إعادة التشغيل مكلفة.Recreate— يُخلي Updater الـ Pods حين تنحرف قيم مواردها انحرافاً كبيراً عن التوصية، لكن فقط إذا سمح بذلك PDB. مفيد للـ Deployments ذات النسخ المتعددة.Auto— مماثل لـRecreateحالياً؛ قد يستخدم تحديثاً في المكان (in-place resize) عند استقرار Kubernetes KEP-1287 (ألفا في الإصدار 1.27+).
بعد أسبوع، افحص التوصية:
Goldilocks: تحليل ضبط الحجم على مستوى الأسطول
تشغيل كائنات VPA منفردة لكل حِمل عمل في وضع Off هو النهج الصحيح، لكن قراءة kubectl describe vpa لـ 200 Deployment ليس عملياً. تُؤتمت أداة Goldilocks (من Fairwinds) هذا العمل: تُنشئ كائن VPA في وضع Off لكل Deployment في النطاق الذي تُعلّمه، ثم تعرض لوحة تحكم ويب تقارن الـ requests الحالية بالموصى بها جنباً إلى جنب مع تقدير وفر التكلفة الشهري.
ضبط حدود resourcePolicy بشكل صحيح
بدون حدود، سيوصي VPA بأي شيء يراه نموذجه — ربما يُوصي بتخصيص 32 GiB ذاكرة لحِمل عمل مرّ به حدث OOM استثنائي واحد، أو يُخفّض طلب CPU إلى 10m لوظيفة batch تكون خاملة في الليل. دائماً حدّد minAllowed وmaxAllowed لكل container:
minAllowed— لا تسمح لـ VPA بالنزول دون الحد الأدنى المعروف للتشغيل، أو إحماء JVM Heap، أو نسبة نجاح فحوصات الصحة. لخدمات Java، الحد الآمن عادةً 512Mi ذاكرة حتى للنسخ ذات الحِمل الخفيف.maxAllowed— قيّد التوصية بنسبة من سعة أكبر Node متاحة. توصية تتجاوز 50% من الـ allocatable resource للـ Node تُقلّل كثافة الـ Pods وتُهزم الهدف منها.controlledValues: RequestsOnlyمقابلRequestsAndLimits— للـ CPU، فضّلRequestsOnlyدون CPU limit (نمط موصى به من Google لتجنب CFS throttling). للذاكرة، استخدمRequestsAndLimitsلتتناسب حدود OOM مع الاستخدام الفعلي.
requests.cpu فقط ليتمكن المُجدوِل من التوزيع الصحيح، ودع Scheduler العادل للـ Node يتعامل مع الارتفاعات. استخدم controlledValues: RequestsOnly في VPA لمنعه من ضبط CPU limit.
أنماط الفشل الإنتاجي التي يجب معرفتها
أفضى VPA في وضع Auto إلى إخلاء Deployments بأكملها في السيناريوهات التالية — جميعها موثّقة في بيئات إنتاجية حقيقية:
- سوء ضبط PDB: Deployment بثلاث نسخ و
maxUnavailable: 3(أو بدون PDB) يسمح لـ VPA Updater بإخلاء جميع الـ Pods دفعةً واحدة. طبّق PDB بحد أدنىminAvailable: 1أوmaxUnavailable: 33%لكل Deployment يخدم حركة مرور. - تضخيم Cold Start: حِمل عمل يستهلك CPU قليلاً في وقت الخمول لكنه يرتفع حاداً عند أول طلب (Node.js، Python مع imports كسولة، JVM). يُلاحظ VPA الاستهلاك الخامل ويخفض طلب CPU. عند أول نشر، تُعاد تشغيل الـ Pods بطلب CPU منخفض، فيُسبّب إحماء JVM تكبيلاً، تفشل فحوصات الصحة، تُعيد الـ Deployment نشرها القديم، وتتكرر الدورة. الحل: ضبط
minAllowed.cpuعلى استهلاك p95 الإحماء المقاس. - تذبذب التوصيات: حِمل عمل ذو ذاكرة متغيرة بشدة (مثل وظيفة batch ممزوجة مع خادم ويب في الـ Pod ذاتها). يتأرجح VPA بين توصيات منخفضة وعالية مما يُسبّب إخلاءات متكررة. الحل: افصل batch عن web في containers أو Deployments مستقلة لكي يُنمذج VPA كلاً منهما باستقلالية.
minAvailable: 1 ولديك نسخة واحدة فقط، تُحجب عملية الإخلاء — وبذلك لا تُطبَّق التوصية أبداً. النهج الصحيح للأحمال أحادية النسخة هو وضع Initial وإعادة التشغيل اليدوية خلال نافذة صيانة مجدوَلة.
دمج توصيات VPA في سير عمل GitOps
في سير عمل GitOps (ArgoCD أو Flux)، يتعارض وضع Auto في VPA مع المُتوافق (Reconciler): يُعدّل VPA مواصفات الـ Pod داخل الـ Cluster فيما يُعيد المُتوافق Deployment Manifest في git إلى قيم الـ requests الأصلية. الحل الموثّق هو إبقاء VPA في وضع Off، وتصدير التوصيات دورياً، وإعادة تغذيتها في git عبر مرحلة في مسار CI.
هذا النهج يُبقي git مرجعاً للحقيقة الوحيدة مع الاستفادة من تحليل VPA القائم على البيانات. تعتمد فرق هندسة على مستوى Spotify وShopify وشركات مماثلة الحجم هذا النمط لإجراء مراجعات ضبط الحجم ربع السنوية بدلاً من الاعتماد على التعديل التلقائي الكامل في الإنتاج.