مانیتورینگ سطح: متوسط

Incident Response در عمل: چطور زمان رفع حادثه را ۴۵٪ کم کردیم

سطح‌بندی حادثه، نقش‌ها، Runbook استاندارد، اتوماسیون با n8n و Postmortem بدون مقصر؛ تجربه‌ی واقعی کاهش ۴۵ درصدی زمان رفع حادثه.

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

ساعت ۲ بامداد، سرویس پرداخت از دسترس خارج می‌شود. در بیشتر تیم‌ها، اتفاق بعدی این است که چند نفر هم‌زمان وارد سرورها می‌شوند، هر کدام چیزی را Restart می‌کنند، در گروه چت ده‌ها پیام رد و بدل می‌شود و بعد از یک ساعت هیچ‌کس دقیقاً نمی‌داند چه چیزی مشکل را حل کرد.

در یکی از تیم‌هایی که مسئولیت زیرساخت‌های حیاتی‌اش را داشتم، با چند تغییر ساختاری، میانگین زمان پاسخ به Incident حدود ۴۵٪ کاهش پیدا کرد. هیچ‌کدام از این تغییرها ابزار گران‌قیمتی نبودند؛ بیشترشان نظم و مستندسازی بودند.

MTTR از چه ساخته می‌شود؟

 incident starts                                                     resolved
      │── detect ──│── notify ──│──── diagnose ────│──── fix ────│
        (MTTD)        (MTTA)                                
      └──────────────────────────── MTTR ───────────────────────────┘
بخش سؤال چه چیزی کوتاهش می‌کند
تشخیص چقدر طول کشید تا بفهمیم مشکلی هست؟ Alert روی علامت‌ها (خطا، زمان پاسخ)
اطلاع چقدر طول کشید تا آدم درست باخبر شود؟ On-Call مشخص، Routing درست Alert
عیب‌یابی چقدر طول کشید تا علت پیدا شود؟ Runbook، داشبورد، لاگ مرکزی
رفع چقدر طول کشید تا سرویس برگردد؟ Rollback سریع، اتوماسیون

در تجربه‌ی من، بیشترین زمان تلف‌شده در بخش عیب‌یابی بود. پس بیشترین سرمایه‌گذاری هم همان‌جا انجام شد.

سطح‌بندی حادثه

سطح تعریف مثال واکنش
SEV1 سرویس اصلی برای همه از دسترس خارج است درگاه پرداخت کار نمی‌کند فوری، همه‌ی افراد کلیدی، اطلاع به مدیریت
SEV2 بخش مهمی مختل یا خیلی کند است ۲۰٪ تراکنش‌ها خطا می‌دهند فوری، On-Call و تیم مربوط
SEV3 مشکل جزئی، راه جایگزین وجود دارد گزارش‌گیری کند است در ساعت کاری

اعلام سطح در همان دقایق اول، مشخص می‌کند چه کسانی باید درگیر شوند و جلوی هم «بی‌توجهی» و هم «وحشت» را می‌گیرد.

نقش‌ها در زمان Incident

بزرگ‌ترین تغییری که دادیم، این بود که در هر SEV1 و SEV2 سه نقش مشخص وجود داشته باشد:

  • Incident Commander: هماهنگ می‌کند، تصمیم می‌گیرد و خودش دست به کیبورد نمی‌زند.
  • Operations: کار فنی، یعنی عیب‌یابی و اجرای راه‌حل‌ها.
  • Communication: به‌روزرسانی منظم برای مدیران، پشتیبانی و در صورت نیاز کارفرما؛ مثلاً هر ۱۵ دقیقه.

Runbook: دستورالعمل به‌جای حدس

برای هر Alert مهم یک Runbook در Confluence یا Wiki تیم بنویسید. قالبی که استفاده می‌کنیم:

# PaymentGatewayHighErrorRate

## Meaning
More than 2% of payment requests are failing for 5 minutes. Users cannot pay.

## Dashboards
- Grafana: Payment overview → https://grafana.example.ir/d/payment
- Kibana: saved search "payment errors"

## Diagnose
1. Is it all requests or one bank/PSP?  → panel "errors by provider"
2. Was there a deployment in the last hour? → GitLab environments page
3. Are pods healthy?  `kubectl get pods -n production -l app=payment`
4. Is the database slow? → panel "DB query p95"

## Mitigate
- Recent deploy → roll back: `git revert` in deploy-config (ArgoCD syncs)
- One provider failing → disable it via feature flag `psp.<name>.enabled=false`
- DB connections exhausted → scale down batch jobs: `kubectl scale deploy/report-worker --replicas=0 -n production`

## Escalate
Backend on-call → Tech lead → DBA (phone numbers in on-call sheet)

ارزش واقعی Runbook این است که یک مهندس تازه‌کار هم ساعت ۲ بامداد بتواند در ۱۰ دقیقه کاری را انجام دهد که قبلاً فقط باتجربه‌ترین عضو تیم بلد بود.

اتصال همه‌چیز به هم

Alertی که فقط می‌گوید «خطا زیاد است» نیمی از کار را انجام داده است. در Annotationهای هر Alert در Prometheus، لینک Runbook و داشبورد را بگذارید تا پیام Mattermost این شکلی شود:

🔴 [FIRING] PaymentGatewayHighErrorRate — production
Error rate 4.7% (threshold 2%) for 6m
📖 Runbook:   https://wiki.example.ir/runbooks/payment-high-error-rate
📊 Dashboard: https://grafana.example.ir/d/payment?from=now-1h
🔎 Logs:      https://kibana.example.ir/app/discover#/view/payment-errors

همین سه لینک، دقایق اول هر Incident را که معمولاً صرف «کجا را نگاه کنم؟» می‌شد، حذف کرد.

خودکارسازی کارهای تکراری

بعد از چند ماه، Runbookها نشان دادند کدام اقدام‌ها بارها تکرار می‌شوند. همان‌ها را خودکار کردیم:

  • n8n: یک Workflow که Webhook از Alertmanager می‌گیرد و برای Alert «پر شدن دیسک»، لاگ‌های قدیمی را از طریق SSH پاک و نتیجه را در کانال گزارش می‌کند.
  • Ansible: Playbookهای آماده برای کارهای پرتکرار مثل Restart امن یک سرویس روی چند سرور، با serial: 1 تا همه هم‌زمان Restart نشوند.
  • ChatOps: دستورهای از پیش تعریف‌شده در Mattermost (مثلاً نمایش وضعیت Podهای یک سرویس) تا برای کارهای ساده لازم نباشد کسی VPN بزند و وارد کلاستر شود.

Postmortem بدون مقصر

بعد از هر SEV1 و SEV2، ظرف حداکثر ۵ روز کاری یک Postmortem می‌نویسیم:

  1. خلاصه: چه شد، چه مدت، چه تأثیری روی کاربران داشت.
  2. خط زمانی: از اولین نشانه تا رفع کامل (کانال Incident اینجا به کار می‌آید).
  3. علت ریشه‌ای: با روش «۵ چرا»، نه «فلانی اشتباه کرد».
  4. چه چیزی خوب کار کرد و چه چیزی نه.
  5. اقدام‌های اصلاحی: هر کدام با مسئول و تاریخ، و ثبت‌شده در Jira.

چه چیزی واقعاً تفاوت ایجاد کرد؟

اگر بخواهم از تجربه‌ی خودم فقط سه مورد را نام ببرم:

  1. لینک Runbook و داشبورد در هر Alert: بیشترین تأثیر روی زمان عیب‌یابی.
  2. نقش Incident Commander: پایان هرج‌ومرج و کارهای موازی و متناقض.
  3. پیگیری اقدام‌های Postmortem در Jira: تا همان مشکل دوباره تکرار نشود.

جمع‌بندی

Incident Response خوب با ابزار شروع نمی‌شود، با آمادگی شروع می‌شود: سطح‌بندی روشن، نقش‌های مشخص، Runbook برای Alertهای مهم و فرهنگ یادگیری بدون مقصر. ابزارهایی مثل Prometheus، Grafana، ELK، Mattermost و n8n این آمادگی را سریع‌تر و قابل اتکاتر می‌کنند.