الملفات
ghaymah-exam-ayashosha-sre/q2-postmortem/postmortem-report.md
2026-07-29 05:21:40 +03:00

9.2 KiB
خام اللوم التاريخ

Q2 — تحليل حادثة انقطاع (Postmortem)

التاريخ: 28 يوليو 2026
المدة: 45 دقيقة
الخدمة: تطبيق Node.js على غيمة (nodeapp-production)
التأثير: انقطاع كامل عن المستخدمين — HTTP 502/503
السبب المباشر: OOMKilled متكرر (نفاد الذاكرة)


1. الملخص التنفيذي

في 28 يوليو 2026، تعطّل تطبيق الإنتاج على Ghaymah Cloud لمدة 45 دقيقة بسبب قتل الحاويات المتكرر من نوع OOMKilled.
ارتفع استهلاك الذاكرة تدريجياً بعد نشر إصدار جديد، حتى تجاوز الحد المخصص للحاوية (512 MiB — فئة t1).
بدأت الحاويات في الدورة: تشغيل → امتلاء الذاكرة → OOMKill → إعادة تشغيل، مما جعل Health Probes تفشل وخرجت جميع النسخ من Load Balancer.

السبب الجذري: حد ذاكرة غير كافٍ + تسريب ذاكرة (memory leak) في middleware جديد + غياب تنبيهات مبكرة و auto-scaling.

الإجراء الفوري: رفع حجم الحاوية إلى ρ-l (1 GiB) وزيادة count من 2 إلى 4، ثم rollback للإصدار السابق.


2. Timeline

الوقت (UTC+3) الحدث
14:00 حركة طبيعية — 2 حاويات، استهلاك ذاكرة ~55%
14:12 نشر إصدار v1.4.2 (rolling deploy)
14:18 الذاكرة ترتفع إلى ~78% على الحاويات الجديدة
14:22 أول OOMKill — الحاوية pod-7f3a تُقتل من Kernel
14:24 إعادة تشغيل تلقائية — Health probe يفشل لـ 30 ثانية
14:26 OOMKill ثاني — بدء restart loop
14:30 LB يزيل كل الحاويات من rotation — بداية الانقطاع الكامل
14:35 تنبيه uptime يرسل (تأخر 13 دقيقة عن أول OOMKill)
14:40 مهندس on-call يراجع logs — يجد OOMKilled و Exit Code 137
14:42 rollback إلى v1.4.1 + رفع size إلى ρ-l
14:45 Health probes تنجح — استعادة الخدمة

MTTR: 45 دقيقة
MTTD (Mean Time To Detect): ~13 دقيقة (بطيء)


3. Root Cause Analysis

3.1 السبب المباشر (Immediate Cause)

Linux Kernel قتل عملية الحاوية لأنها تجاوزت memory limit المحدد في .ghaymah.json:

"resourceTier": "t1"   // 512 MiB RAM

رسالة النظام:

State: OOMKilled
Exit Code: 137
Reason: Memory limit exceeded

3.2 السبب الجذري (Root Cause)

# السبب التفصيل
1 حد ذاكرة منخفض t1 (512 MiB) غير مناسب لحمل الإنتاج بعد النشر الجديد
2 Memory leak middleware logging في v1.4.2 يخزّن request bodies في array بدون حد أقصى
3 لا auto-scaling count: 2 ثابت — لم يُضف حاويات عند ارتفاع الحمل
4 تنبيهات متأخرة لا يوجد alert على memory > 80% أو restart count

3.3 العوامل المساهمة

  • لم يُجرَ load test على v1.4.2 قبل الإنتاج
  • Rolling deploy أبقى 20% من الحاويات القديمة لكن الجديدة consumptive أكثر
  • لا مراقبة لـ container_restart_count

4. التوصيات (Action Items)

# الإجراء الأولوية المسؤول الحالة
1 إصلاح memory leak في middleware P0 Backend تم
2 رفع الحد الأدنى للذاكرة إلى ρ (768 MiB) P0 SRE تم
3 تفعيل auto-scaling (انظر القسم 2 أدناه) P1 SRE 🔄 قيد التنفيذ
4 تنبيه RasidAI عند memory > 80% لـ 2 دقيقة P1 SRE 🔄 قيد التنفيذ
5 تنبيه عند restart_count > 3 في 10 دقائق P1 SRE 📋 مخطط
6 load test إلزامي قبل deploy لـ main P2 DevOps 📋 مخطط
7 إضافة /health يفحص memory usage P2 Backend 📋 مخطط

5. سياسة Auto-Scaling لمنصة غيمة

غيمة توفر مفتاحين رئيسيين في .ghaymah.json:

  • count: — عدد النسخ (Horizontal Scaling)
  • size: — فئة CPU/RAM: ρ, ρ-m, ρ-l, ρ-xl (Vertical Scaling)

5.1 Horizontal Pod Scaling (HPA)

زِد count عندما:
  - متوسط CPU > 70% لمدة 3 دقائق، أو
  - متوسط Memory > 75% لمدة 3 دقائق، أو
  - p95 latency > 800ms لمدة 5 دقائق

قلّل count عندما:
  - CPU < 30% AND Memory < 40% لمدة 10 دقائق

الحدود:
  - min_count: 2
  - max_count: 10
  - scale_up_cooldown: 60s
  - scale_down_cooldown: 300s

مثال في .ghaymah.json:

{
  "count": 2,
  "autoscaling": {
    "enabled": true,
    "min": 2,
    "max": 10,
    "metrics": [
      { "type": "memory", "target": 75, "duration": "3m" },
      { "type": "cpu", "target": 70, "duration": "3m" }
    ]
  }
}

5.2 Vertical Scaling (VPA-lite)

ارفع size عندما:
  - Memory > 85% على ALL instances لمدة 5 دقائق
  - OOMKill حدث مرة واحدة على الأقل

مسار الترقية:
  t1 (512 MiB) → ρ (768 MiB) → ρ-l (1 GiB) → ρ-xl (2 GiB)

لا تُخفِض size تلقائياً — يدوي فقط بعد مراجعة 7 أيام

5.3 سياسة منع OOMKilled

1. memory_limit = observed_peak × 1.3 (هامش 30%)
2. إذا restart_count > 2 في 5 min → scale up فوراً (count +1 أو size +1)
3. rolling deploy: لا تزيد أكثر من 50% من الحاويات دفعة واحدة
4. Graceful shutdown: SIGTERM grace period = 30s قبل SIGKILL

5.4 Flowchart

Memory > 75% لـ 3 min?
  ├─ نعم → count + 1 (حتى max)
  └─ لا → استمر

OOMKill detected?
  ├─ نعم → size + 1 فوراً + alert P0
  └─ لا → استمر

Memory > 85% على كل instances?
  ├─ نعم → size + 1
  └─ لا → OK

6. الكشف المبكر — أدوات مراقبة غيمة

6.1 RasidAI Monitoring

  • مراقبة real-time للتطبيقات على غيمة
  • تنبيهات مقترحة:
    • Memory utilization > 80% لمدة 2 دقيقة → Warning
    • Memory utilization > 90% لمدة 1 دقيقة → Critical
    • Container restart > 3 في 10 دقائق → Critical
    • Health probe failures > 2 متتالية → Critical

6.2 Logs (JSON — 30 يوم retention)

gy logs app nodeapp-production --env production --follow

ما نبحث عنه:

OOMKilled
Exit code 137
FATAL ERROR: Reached heap limit
JavaScript heap out of memory
  • كل log يحتوي trace-id — نربط الطلبات قبل الانهيار
  • Dashboard في RasidAI: رسم memory usage vs limit over time

6.3 Health & Retry Probes

غيمة تدعم HTTP/TCP probes:

"healthCheck": {
  "path": "/health",
  "interval": 10,
  "timeout": 5,
  "unhealthyThreshold": 2
}

تحسين /health:

app.get('/health', (req, res) => {
  const used = process.memoryUsage().heapUsed / 1024 / 1024
  if (used > 400) return res.status(503).json({ status: 'degraded', memory_mb: used })
  res.json({ status: 'ok', memory_mb: used })
})

→ الحاوية تخرج من LB قبل OOMKill

6.4 CLI — فحص سريع

gy resource app status --env production
gy resource app logs --env production --tail 100

6.5 لوحة مراقبة (Dashboard)

Metric Threshold Warning Threshold Critical
Memory % 80% 90%
CPU % 70% 85%
Restart count / 10min 1 3
p95 latency 500ms 1000ms
Error rate (5xx) 1% 5%

6.6 كيف كان يمكن اكتشافها قبل الانقطاع؟

14:18  Memory 78%  → ⚠️ Warning alert (كان سيُرسل)
14:20  Memory 85%  → 🔴 Critical alert
14:22  OOMKill      → 🔴 Auto scale-up + P0 page
14:30  Outage       → ❌ لم يحدث (في الواقع)

الفجوة: لم تكن التنبيهات مفعّلة → MTTD 13 دقيقة بدلاً من 2 دقيقة.


7. الدروس المستفادة

  1. OOMKilled = Exit 137 — أول شيء نفحصه في logs بعد أي restart غير متوقع
  2. حد الذاكرة يجب أن يُحسب من P99 + 30% وليس من التقدير
  3. Auto-scaling أفقي و عمودي معاً — HPA وحده لا يكفي إذا leak في كل instance
  4. Health endpoint يجب أن يفحص memory وليس return 200 فقط
  5. RasidAI + alerts = MTTD أقل من 5 دقائق → يمنع 45 دقيقة outage

8. المراجع