FinOps وتحسين تكاليف السحابة

الحوسبة الفورية وقابلة الاسترداد

18 دقيقة الدرس 6 من 26

الحوسبة الفورية وقابلة الاسترداد

تُعدّ الحالات الفورية (AWS Spot Instances) والأجهزة الافتراضية قابلة الاسترداد (GCP Preemptible VMs) وأجهزة Spot الافتراضية (Azure Spot VMs) العتلة الأعلى تأثيراً في خفض التكلفة لأي فريق هندسي يشغّل أحمال عمل قابلة للتحمّل. وهي تتيح في المتوسط خصماً من 60% إلى 90% قياساً بالأسعار العادية، إذ يتراوح خصم AWS Spot عادةً بين 70% و80% لعائلات الأجهزة ذات الأغراض العامة. عند إنفاق 500 ألف دولار شهرياً على EC2 بالأسعار العادية، يوفّر تحويل 40% من الطاقة إلى Spot ما بين 140 و160 ألف دولار شهرياً — دون تعديل سطر واحد من كود التطبيق. الثمن الوحيد هو أن مزود السحابة يستطيع استرداد الطاقة بإشعار مدته دقيقتان. كل ما في هذا الدرس يتمحور حول التصميم الهندسي الذي يجعل هذا الاضطراب حدثاً روتينياً غير ذي شأن.

آلية عمل أسواق Spot

تحتفظ AWS وGCP وAzure بمجمعات من طاقة الحوسبة غير المستخدمة التي ستبقى خاملة بغير ذلك. وتُتيح هذه الطاقة بأسعار مخفّضة بشرط أن تستردّها عند ارتفاع الطلب العادي. تختلف آلية كل مزود:

  • AWS Spot: لم يعد السعر قائماً على المزايدة — منذ عام 2017 يُحدّد AWS الأسعار خوارزمياً لكل منطقة توفر وعائلة أجهزة. تدفع سعر Spot الحالي عن كل ثانية تشغيل، وتتلقى إشعار انقطاع قبل دقيقتين عبر خدمة بيانات التعريف (http://169.254.169.254/latest/meta-data/spot/termination-time) وعبر EventBridge اختيارياً. تتفاوت معدلات الانقطاع تفاوتاً كبيراً: قد يعمل m5.xlarge في us-east-1a أسابيع بلا انقطاع، بينما قد تُسترد عائلة GPU في المنطقة ذاتها خلال ساعات. ينشر Spot Instance Advisor تاريخ تكرار الانقطاع لكل عائلة ومنطقة توفر — استشره قبل اختيار تركيبة الأسطول.
  • GCP Preemptible / Spot VMs: محدودة بـ24 ساعة تشغيل بصرف النظر عن الطلب، مع إشارة إيقاف ACPI قبل 30 ثانية من الاسترداد. أما Spot VMs (العرض الأحدث) فلا حدّ زمني لها لكنها تحمل مخاطر الاسترداد ذاتها. العلامة --provisioning-model=SPOT تُفعّلها في Terraform وgcloud.
  • Azure Spot VMs: استخدم سياسة الإخلاء Deallocate (إيقاف الجهاز مع الحفاظ على القرص وإمكانية إعادة التشغيل — الخيار المفضّل) أو Delete (حذف الجهاز والأقراص). يصل إشعار الإخلاء قبل دقيقتين عبر Azure Scheduled Events في نقطة نهاية بيانات التعريف المحلية.
النموذج الذهني الأساسي: طاقة Spot ليست غير موثوقة — هي قابلة للانقطاع. ثمة فرق. أسطول Spot سليم في عائلة أجهزة مختارة بعناية ومنطقة توفر مناسبة يعمل أياماً أو أسابيع بلا انقطاع. ما يجب تجنّبه تماماً هو التصميم بحيث يُسبّب انقطاع واحد فشلاً مرئياً للمستخدم أو ضياع بيانات. صمّم للانقطاع؛ وارتح حين لا يحدث.

تصنيف أحمال العمل: ما يصلح لـ Spot

قبل لمس أي قالب إطلاق، صنّف أحمال عملك بصدق. السؤال الثنائي: هل يُسبّب إزالة مفاجئة لهذا الجهاز خلال دقيقتين فشلاً مرئياً للمستخدم أو ضياع بيانات؟

  • مرشّحات مثالية لـ Spot: عوامل CI/CD، خطوط أنابيب البيانات الدُّفعية (Spark وFlink وEMR)، مهام تدريب النماذج مع دعم نقاط التفتيش، تحويل الفيديو، معالجة السجلات، بنية اختبار الأحمال، عمال الطبقة عديمة الحالة خلف ALB مع فحوصات صحة، وأي مستهلك قائمة انتظار يستطيع إعادة المحاولة بأمان.
  • مرشّحات مشروطة: عقد عمال Kubernetes تشغّل pods عديمة الحالة (مع PodDisruptionBudgets وخطافات preStop)، مجموعات التحجيم التلقائي التي تفوق طاقتها المطلوبة الحدّ الأدنى الثابت بكثير، وبيئات التطوير والاختبار حيث الانقطاع مقبول تماماً.
  • مرشّحات سيئة لـ Spot: قواعد بيانات أساسية، عقد قرام ZooKeeper أو etcd، أي شيء يحمل حالة محلية مؤقتة غير محفوظة، وحدات انتخاب القائد المنفردة، عقد مستوى التحكم Kubernetes في الإنتاج.

تنويع الأجهزة: المبدأ الأهم في Spot

التقنية الأكثر فعالية في تحقيق المرونة هي تنويع الأجهزة: طلب الطاقة عبر عائلات أجهزة متعددة وأحجام ومناطق توفر متنوعة في آنٍ واحد. مجموعة ASG مقيّدة بنوع جهاز واحد في منطقة توفر واحدة ستُعطَّل في آنٍ واحد عبر الأسطول بأكمله عند استرداد ذلك المجمع. مجموعة تمتد على ست عائلات أجهزة عبر ثلاث مناطق توفر لن تشهد تقريباً أي انقطاع شامل — كل مجمع مستقل والانقطاعات محلية.

استخدم استراتيجية التخصيص capacity-optimised (لا lowest-price) في AWS Auto Scaling. تختار هذه الاستراتيجية من أعمق مجمع متاح، مما يُقلل تكرار الانقطاع ويتجنب مشكلة التجمّع حين تتدافع كل الأساطيل في المنطقة نحو أرخص مجمع مستنزِفةً إياه بسرعة.

# Terraform: ASG with instance diversification and capacity-optimised Spot strategy # ec2/spot_asg.tf resource "aws_autoscaling_group" "workers" { name = "batch-workers-spot" vpc_zone_identifier = var.private_subnet_ids # spread across 3 AZs desired_capacity = 20 min_size = 2 max_size = 60 mixed_instances_policy { instances_distribution { on_demand_base_capacity = 2 # keep 2 on-demand as stable floor on_demand_percentage_above_base_capacity = 0 # everything else is Spot spot_allocation_strategy = "capacity-optimized" } launch_template { launch_template_specification { launch_template_id = aws_launch_template.worker.id version = "$Latest" } # Six families with equivalent vCPU counts — independent capacity pools override { instance_type = "c5.4xlarge" } override { instance_type = "c5a.4xlarge" } override { instance_type = "c5n.4xlarge" } override { instance_type = "m5.4xlarge" } override { instance_type = "m5a.4xlarge" } override { instance_type = "r5.2xlarge" } } } lifecycle { create_before_destroy = true } tag { key = "spot-fleet" value = "batch-workers" propagate_at_launch = true } }
Spot Fleet Architecture: Multi-AZ, Multi-Family with On-Demand Floor Application Load Balancer health checks every 10s AZ — us-east-1a c5.4xlarge (Spot) pool: deep / freq: low m5a.4xlarge (Spot) pool: deep / freq: low c5.4xlarge (On-Demand) base floor = 2 instances INTERRUPTED draining → replaced AZ — us-east-1b c5n.4xlarge (Spot) pool: deep / freq: low r5.2xlarge (Spot) independent pool m5.4xlarge (Spot) pool: deep / freq: low AZ — us-east-1c c5a.4xlarge (Spot) pool: deep / freq: low m5a.4xlarge (Spot) independent pool r5.2xlarge (Spot) independent pool Spot Instance On-Demand (floor) Interrupted (draining)
أسطول Spot موزّع عبر ثلاث مناطق توفر وست عائلات أجهزة. انقطاع في مجمع واحد (باللون الأحمر) معزول — يتوقف ALB عن توجيه حركة المرور إليه خلال ثوانٍ، ويستبدله ASG من مجمع آخر.

معالجة الانقطاع: نافذة الدقيقتين

حين يُرسل AWS إشعار انقطاع Spot، لديك 120 ثانية بالضبط قبل أن يُوقَف الجهاز أو يُحذَف. ما تفعله في هذه النافذة يحدد إن كان الانقطاع غير مرئي لمستخدميك أو يُسبّب حادثة. النمط المعياري له ثلاث طبقات:

  1. اكتشاف الإشعار. استطلع نقطة نهاية IMDS كل 5 ثوانٍ من عملية وكيل خفيفة، أو اشترك في حدث EventBridge EC2 Spot Instance Interruption Warning (يُنشَر قبل نحو دقيقتين من الانقطاع). تُصدر AWS أيضاً توصيات إعادة التوازن — إشارة أقدم وأكثر ليونة بأن جهازك في خطر متزايد للانقطاع. تصرّف عند توصية إعادة التوازن بشكل استباقي للحصول على بديل نظيف قبل بدء الإشعار الصعب.
  2. إخلاء العمل الجاري. لـ Kubernetes: اضبط العقدة على NoSchedule ونفّذ kubectl drain. لعمّال الويب: أزل التسجيل من مجموعة هدف موازن الحمل (مهلة تصريف اتصالات ALB، عادة 30 ثانية، تتولى طلبات HTTP الجارية). لعمّال الدُّفعات: احفظ نقطة تفتيش على S3 أو قاعدة بيانات وضع وحدة العمل كقابلة للاستئناف قبل إيقاف الجهاز.
  3. إشارة ASG. إن كنت تستخدم خطاف دورة حياة، أرسل نبضة قلب CONTINUE للسماح لـ ASG بإطلاق بديل فوراً بدلاً من انتظار مهلة فحص الصحة الكاملة.
#!/usr/bin/env bash # /usr/local/bin/spot-interruption-handler.sh # Run as a systemd service or supervised process on each Spot instance. # Polls IMDS for the interruption notice and triggers graceful shutdown. IMDS="http://169.254.169.254" TOKEN=$(curl -s -X PUT "$IMDS/latest/api/token" \ -H "X-aws-ec2-metadata-token-ttl-seconds: 30") while true; do STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ -H "X-aws-ec2-metadata-token: $TOKEN" \ "$IMDS/latest/meta-data/spot/termination-time") if [ "$STATUS" = "200" ]; then echo "[$(date -u)] Spot interruption notice received — beginning graceful shutdown" # 1. Stop accepting new work systemctl stop worker-daemon # 2. Checkpoint any in-flight state to S3 aws s3 cp /var/worker/checkpoint.json \ "s3://${CHECKPOINT_BUCKET}/checkpoints/$(hostname).json" # 3. Signal Auto Scaling lifecycle hook (if configured) REGION=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \ "$IMDS/latest/meta-data/placement/region") INSTANCE_ID=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \ "$IMDS/latest/meta-data/instance-id") ASG_NAME=$(aws autoscaling describe-auto-scaling-instances \ --instance-ids "$INSTANCE_ID" --region "$REGION" \ --query 'AutoScalingInstances[0].AutoScalingGroupName' --output text) aws autoscaling complete-lifecycle-action \ --lifecycle-action-result CONTINUE \ --instance-id "$INSTANCE_ID" \ --auto-scaling-group-name "$ASG_NAME" \ --lifecycle-hook-name spot-interruption-hook \ --region "$REGION" 2>&1 || true break fi sleep 5 done
توصية إعادة توازن AWS: اشترك في أحداث EventBridge EC2 Instance Rebalance Recommendation إضافةً إلى إشعار الانقطاع. هذه الإشارة الأقدم تمنحك انطلاقة أسبق — يمكنك استبدال جهاز مهدّد باستباقية قبل انطلاق الساعة الصعبة ذات الدقيقتين، وهو أمر ثمين بشكل خاص لمهام تدريب ML طويلة الأمد أو خطوط أنابيب دُفعية حالتها تستغرق أكثر من دقيقتين للكتابة.

Kubernetes على Spot: مجموعات العقد وميزانيات انقطاع الـ Pod

تشغيل عقد عمال Kubernetes على Spot يُعدّ أحد أعلى التهيئات تأثيراً في منظومة الأدوات بأكملها. يجب دائماً تشغيل مستوى التحكم وetcd على أجهزة عادية؛ عقد العمال للأحمال عديمة الحالة مرشّحة مثالية لـ Spot. التهيئات الحرجة هي:

  • مجموعات عقد منفصلة لكل نوع دورة حياة. احتفظ بمجموعة عقد عادية على الأقل (لـ pods النظام والأحمال الحساسة لـ PDB) ومجموعة عقد Spot واحدة أو أكثر (لـ pods التطبيقات). استخدم محددات العقد أو الإكراهات لتوجيه أحمال العمل: eks.amazonaws.com/capacityType=SPOT.
  • PodDisruptionBudgets. كل Deployment بأكثر من نسخة واحدة يجب أن يمتلك PDB. PDB بقيمة maxUnavailable: 1 يضمن أن Kubernetes لن يُصرّف عقدة Spot إن كان ذلك سيُبقي أقل من العدد المطلوب من pods الجاهزة. بدون هذا، قد يؤدي التصريف المتزامن لعقدتين إلى تقليص pods النشطة للنصف مؤقتاً.
  • AWS Node Termination Handler. هذا DaemonSet يراقب إشعارات انقطاع Spot وتوصيات إعادة التوازن على مستوى العقدة، يُلوّث العقدة، يُصرّفها عبر Kubernetes API، ويُشير لمجموعة التحجيم التلقائي قبل أن يُوقف السحابة الجهاز. ثبّته قبل وضع أي حمل إنتاجي على عقد Spot.
# Kubernetes: PodDisruptionBudget + Spot node toleration for a web Deployment # k8s/web-deployment.yaml apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: web-pdb namespace: production spec: minAvailable: "70%" selector: matchLabels: app: web --- apiVersion: apps/v1 kind: Deployment metadata: name: web namespace: production spec: replicas: 10 selector: matchLabels: app: web template: metadata: labels: app: web spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 preference: matchExpressions: - key: eks.amazonaws.com/capacityType operator: In values: ["SPOT"] tolerations: - key: "spot" operator: "Equal" value: "true" effect: "NoSchedule" terminationGracePeriodSeconds: 90 containers: - name: web image: myapp:latest lifecycle: preStop: exec: command: ["/bin/sh", "-c", "sleep 15"] readinessProbe: httpGet: path: /healthz port: 8080 periodSeconds: 5 failureThreshold: 3

خطوط أنابيب الدُّفعات المتحمّلة للأعطال على Spot

لأحمال الدُّفعات العقد أبسط: تنقسم العمل إلى وحدات محفوظة بنقاط تفتيش، وأي وحدة لم تُكتمل بسبب انقطاع تُعاد على جهاز بديل. مبادئ التصميم التي تجعل هذا يعمل على نطاق واسع:

  • مهام أمنية التكرار. كل وحدة عمل يجب أن تكون آمنة للتنفيذ أكثر من مرة. اكتب إلى بادئة S3 مؤقتة وأعد التسمية بشكل ذري عند الاكتمال؛ استخدم كتابات مشروطة في DynamoDB لمنع الإدخالات المكررة.
  • حفظ نقاط التفتيش بتكرار. لتدريب ML الطويل، احفظ أوزان النموذج إلى S3 كل N خطوة (عادة كل 5–15 دقيقة من وقت الحوسبة). عند إعادة التشغيل، حمّل نقطة التفتيش الأخيرة وتابع. PyTorch Lightning وTensorFlow وHugging Face Trainer تدعم هذا بشكل أصلي.
  • المطالبة الذرية بالمهام. استخدم SQS مع مهلة الرؤية كقائمة عمل موزّعة. يطالب العامل برسالة (تصبح غير مرئية للآخرين)، يعالجها، ويحذفها عند النجاح. إن انقطع الجهاز قبل الحذف، تنتهي مهلة الرؤية ويلتقط جهاز آخر نفس الرسالة. اضبط مهلة الرؤية على 1.5x من المدة المتوقعة للمهمة.
  • AWS Spot + EMR. يتعامل EMR Managed Scaling وتهيئة عقدة المهام المدركة لـ Spot مع الانقطاعات تلقائياً: تعمل عقد المهام (حوسبة عديمة الحالة) على Spot؛ عقد النواة (تكرار HDFS) تعمل على أجهزة عادية.
أكبر نمط مضادّ في Spot: استخدام Spot لعمليات طويلة الأمد ذات حالة تكتب على القرص المحلي وليس لها نقاط تفتيش — تدريب ML يكتب حالة النموذج على /tmp فقط، أو مهام دُفعية تتراكم نتائجها في الذاكرة لساعات قبل الحفظ. انقطاع واحد يُضيع ساعات من الحوسبة. الحل: احفظ نقاط تفتيش في مخزن الكائنات بفترات منتظمة قبل نقل أي حمل عمل إلى Spot.

استراتيجية مزج Spot مع الأجهزة العادية

أساطيل Spot الإنتاجية دائماً تمزج نسبة من الطاقة العادية كأرضية ثابتة. النسبة الصحيحة تعتمد على تحمّل الحمل:

  • الدُّفعات / تدريب ML: 0–10% عادي. Spot النقي مقبول إن كانت المهام محفوظة بنقاط تفتيش. احتفظ بأرضية عادية صغيرة فقط لضمان عدم وصول الأسطول إلى الصفر حين تكون الطاقة محدودة في جميع المجمعات.
  • طبقة الويب عديمة الحالة: 20–30% عادي. الأرضية العادية تضمن عدداً أدنى من الأجهزة السليمة التي تصمد أمام أسوأ حالة من الانقطاع المتزامن متعدد المجمعات. يوجّه ALB عبر كليهما ولا يلاحظ المستخدمون أي فرق.
  • عوامل CI/CD: 80–100% Spot. عمليات البناء قابلة للإعادة بطبيعتها. بناء فاشل يُعاد تصنيفه في القائمة؛ لا أثر على المستخدم. النسبة الصغيرة من الأجهزة العادية تمنع فقط إفراغ الأسطول تماماً خلال أزمة طاقة إقليمية.

على نطاق كبير، تشغّل شركات مثل Airbnb وNetflix وLyft ما بين 60% و80% من إجمالي حوسبة EC2 على Spot أو طاقة مخفّضة مكافئة. الاستثمار الهندسي للوصول إلى هذا المستوى — معالجات الانقطاع، نقاط التفتيش، تنويع الأجهزة، PDBs — يُؤتي ثماره خلال أسابيع عند أي حجم يتجاوز 50 ألف دولار شهرياً من إنفاق EC2.