Prometheus وGrafana

إدارة التنبيهات مع Alertmanager

18 دقيقة الدرس 7 من 32

إدارة التنبيهات مع Alertmanager

يقوم Prometheus بإطلاق التنبيهات — يقيّم قواعد التنبيه ويصنّفها إما كـpending (معلقة) أو firing (نشطة). غير أن Prometheus نفسه لا يرسل رسائل بريد إلكتروني، ولا يستدعي المهندسين المناوبين، ولا ينشر في Slack. تلك المهمة تقع على عاتق Alertmanager: وهو خادم مستقل يستقبل إشعارات التنبيه من خادم أو عدة خوادم Prometheus، ويطبّق منطق التوجيه، ويزيل التكرار، ويجمّع التنبيهات ويكتمها ويوجّهها إلى الأشخاص المناسبين عبر القنوات المناسبة في الوقت المناسب. إتقان Alertmanager هو ما يفرق بين نظام يرسل خمسين إشعارًا خلال عطل واحد، ونظام يرسل تذكرة واحدة واضحة إلى الفريق الصحيح في الساعة الثانية فجرًا.

المفاهيم الأساسية قبل الإعداد

يعمل Alertmanager على إشعارات التنبيه التي يرسلها Prometheus عبر HTTP. يحمل كل إشعار مجموعة من التسميات (نفس تسميات قاعدة التنبيه)، وتعليقات توضيحية، ورابط المُولِّد، وبيانات التوقيت. مهمة Alertmanager هي الإجابة على أربعة أسئلة لكل دفعة من التنبيهات الواردة:

  • إلى أين تذهب؟ — تُعيّن شجرة التوجيه مجموعات التسميات إلى جهات الاستقبال.
  • متى تُرسل؟ — التجميع وgroup_wait / group_interval / repeat_interval تتحكم في التوقيت لتفادي عواصف الإشعارات.
  • هل تُكتم؟ — الصوامت وقواعد الكبت تمنع الضوضاء الزائدة أو المتوقعة.
  • من يستقبلها؟ — تحدد جهات الاستقبال التكاملات الفعلية (PagerDuty, Slack, البريد الإلكتروني، OpsGenie، Webhook).

شجرة التوجيه

إعداد التوجيه في Alertmanager عبارة عن شجرة من عقد المسارات. تحمل كل عقدة شروط التطابق (مطابقات تسميات محددة أو تعبيرات نمطية)، واسم جهة الاستقبال، وتجاوزات التوقيت الاختيارية. تسير مجموعات التنبيهات الواردة عبر الشجرة بعمق أولاً، وتفوز أول عقدة مطابقة ما لم يكن continue: true مضبوطًا للسماح بالمواصلة.

المفتاح group_by بالغ الأهمية وكثيرًا ما يُساء فهمه. يخبر Alertmanager بأبعاد التسميات التي تُعرّف "المجموعة" لأغراض التجميع. إذا جمّعت حسب [alertname, cluster, env]، ستُطلق جميع التنبيهات التي تشترك في هذه القيم الثلاث كإشعار واحد، حتى لو اختلفت في pod أو instance. هذا يمنع عشر عمليات إعادة تشغيل للـ pods المتزامنة من توليد عشر إشعارات مستقلة.

# alertmanager.yml — مثال إعداد إنتاجي للتوجيه global: resolve_timeout: 5m slack_api_url: 'https://hooks.slack.com/services/T.../B.../xxx' route: receiver: 'default-receiver' group_by: ['alertname', 'cluster', 'env'] group_wait: 30s # انتظر قبل إرسال أول إشعار group_interval: 5m # انتظر قبل إرسال تنبيهات جديدة انضمت لمجموعة موجودة repeat_interval: 4h # أعد الإشعار إذا استمر التنبيه بعد هذه المدة routes: # تنبيهات البنية التحتية الحرجة → PagerDuty P1 فورًا - matchers: - severity="critical" - team="infra" receiver: 'pagerduty-infra' group_wait: 10s repeat_interval: 30m continue: false # تنبيهات التحذير لفريق المنصة → Slack فقط - matchers: - severity="warning" - team="platform" receiver: 'slack-platform' group_by: ['alertname', 'namespace'] repeat_interval: 8h # تنبيهات قاعدة البيانات → دوام مناوبة مستقلة - matchers: - component="database" receiver: 'pagerduty-dba' group_wait: 15s repeat_interval: 1h receivers: - name: 'default-receiver' slack_configs: - channel: '#alerts-general' title: '[{{ .Status | toUpper }}] {{ .GroupLabels.alertname }}' text: '{{ range .Alerts }}{{ .Annotations.summary }}\n{{ end }}' - name: 'pagerduty-infra' pagerduty_configs: - routing_key: '<PAGERDUTY_INTEGRATION_KEY>' severity: '{{ if eq .GroupLabels.severity "critical" }}critical{{ else }}warning{{ end }}' description: '{{ .GroupLabels.alertname }}: {{ .CommonAnnotations.summary }}' - name: 'slack-platform' slack_configs: - channel: '#platform-alerts' send_resolved: true - name: 'pagerduty-dba' pagerduty_configs: - routing_key: '<DBA_ROTATION_KEY>'
مفهوم أساسي — group_wait مقابل group_interval: group_wait هو وقت تخزين مؤقت عند نشأة مجموعة جديدة، يمنح Prometheus فرصة لإطلاق تنبيهات ذات صلة قبل أن يرسل Alertmanager الإشعار الأول. أما group_interval فيحكم عمليات الإرسال اللاحقة لنفس المجموعة عند انضمام تنبيهات جديدة إليها. ضبط group_wait بشكل أقصر من اللازم يسبب عواصف إشعارات أثناء الأعطال المتتالية؛ وضبطه أطول من اللازم يُؤخر أول استدعاء. ثلاثون ثانية افتراضية معقولة لمعظم بيئات الإنتاج.

قواعد الكبت (Inhibition Rules)

الكبت هو ميزة Alertmanager الأقل استخدامًا والتي يتمنى معظم المهندسين لو أعدّوها مبكرًا. تقول قاعدة الكبت: "إذا كان التنبيه A نشطًا بهذه التسميات، اكبت أي تنبيه B يطابق هذه التسميات الأخرى." هذا لا غنى عنه لمنع ضوضاء الأعراض حين يكون تنبيه السبب الجذري نشطًا بالفعل.

المثال النموذجي: يُطلق تنبيه NodeDown. بعد ثوان، تُطلق عشرون تنبيهات PodCrashLooping وHighLatency من نفس العقدة. بدون الكبت، يتلقى مهندس المناوبة إحدى وعشرين إشعارًا. مع قاعدة كبت تقول "اكبت كل شيء على نفس تسمية node حين يكون NodeDown نشطًا"، يتلقى واحدًا فقط. يجب أن يشترك مصدر الكبت والهدف في نفس قيم التسميات المحددة في equal لتُطبَّق عملية الكبت.

inhibit_rules: # اكبت تنبيهات مستوى الـ pod حين تكون العقدة بأكملها معطّلة - source_matchers: - alertname="NodeDown" target_matchers: - severity=~"warning|critical" equal: ['cluster', 'node'] # اكبت التنبيهات الأقل خطورة حين يوجد تنبيه حرج لنفس الخدمة - source_matchers: - severity="critical" target_matchers: - severity="warning" equal: ['alertname', 'namespace', 'service'] # اكبت تنبيهات التأخر الخاصة بالعملاء خلال نافذة نشر معروفة - source_matchers: - alertname="DeploymentInProgress" target_matchers: - alertname="HighP99Latency" equal: ['cluster', 'namespace']
أفضل الممارسات: صمّم قواعد الكبت كرسم بياني موجّه. تنبيه المصدر هو "السبب"، والتنبيهات الهدف هي "الأعراض". ارسم هذا الرسم حين تصمم تسلسل تنبيهاتك — يمنع ذلك الحالة التي تبتلع فيها قاعدة الكبت تنبيهًا مستقلاً حقيقيًا بسبب تسميات equal واسعة للغاية.

الصوامت (Silences)

الصوامت هي كتم مؤقت قائم على التسميات يُطبَّق عبر واجهة Alertmanager أو API. هي الأداة الصحيحة لنوافذ الصيانة المجدولة والفترات المعروفة بالمشكلات: تكتم مجموعة من التسميات لمدة محددة، وتُكبت جميع التنبيهات المطابقة دون أي تغيير في إعداد التوجيه أو الكبت. تحمل الصوامت اسم المنشئ وتعليقًا وتاريخ انتهاء — وهي قابلة للتدقيق.

أداة سطر الأوامر amtool هي الطريقة الاحترافية لإدارة الصوامت برمجيًا، لا سيما داخل سكريبتات أتمتة الصيانة:

# تثبيت amtool (مضمنة مع ثنائيات Alertmanager) # تعيين رابط Alertmanager الافتراضي export ALERTMANAGER_URL=http://alertmanager.monitoring.svc:9093 # إنشاء صمت لمدة ساعتين لنافذة صيانة قاعدة بيانات amtool silence add \ --comment="Scheduled DB failover window" \ --author="ops-bot" \ --duration=2h \ alertname=~"Database.*" env="production" cluster="us-east-1" # عرض الصوامت النشطة amtool silence query # إلغاء صمت فورًا بمعرّفه amtool silence expire 4b4f9c7a-81d2-4e8e-a9b3-xxxxxxxxxxxx # التحقق من حالة التنبيهات الحالية (مفيد في دفاتر التشغيل) amtool alert query --alertname=NodeDown # التحقق من صحة إعداد alertmanager قبل إعادة التحميل amtool check-config /etc/alertmanager/alertmanager.yml
مخاطر الإنتاج — تراكم الصوامت: الصوامت ذات المدد السخية ("دعني أكتم هذا لأسبوع") كثيرًا ما تُنسى. تُكتم التنبيهات الحقيقية إلى أجل غير مسمى. طبّق سياسة فريق صارمة: تنتهي الصوامت خلال ساعات لا أيام. للصيانة المتكررة، أتمت إنشاء الصوامت وإلغاءها عبر CI/CD بدلاً من تركها كإدخالات يدوية مفتوحة النهاية.

مسار التنبيه من البداية للنهاية

فهم المسار الكامل الذي يقطعه التنبيه يساعدك في تشخيص الإشعارات الفائتة والإشعارات المكررة — وهما أكثر شكاوى Alertmanager شيوعًا في البيئات الكبيرة.

Alertmanager alert path: from Prometheus rule evaluation to on-call notification Prometheus Rule Evaluation every 15s–1m POST /api/v2/alerts Alertmanager Ingestion dedup + fingerprint Routing Tree match labels → group + receiver Suppression silence? inhibit? drop if suppressed not suppressed Notification Pipeline group_wait / interval PagerDuty P1 on-call page Slack #infra-alerts OpsGenie escalation policy Inhibition Rules NodeDown → suppress pod alerts Active Silences maintenance window label-matched mute
المسار الكامل للتنبيه: Prometheus يُطلق → Alertmanager يوجّه → فحص الكبت (الصوامت + قواعد الكبت) → مسار الإشعارات يوزّع على تكاملات المناوبة.

تكاملات المناوبة في الإنتاج

على نطاق المؤسسات الكبيرة، تحمل تكاملات PagerDuty وOpsGenie أكبر عبء تشغيلي. بعض الأنماط التي تستحق الانتباه:

  • ربط مستوى الخطورة: عيّن تسميات severity في Prometheus مباشرة إلى مستويات خطورة PagerDuty (critical → P1 فوري، warning → P3 خلال ساعات العمل). يتم هذا في حقل القالب pagerduty_configs.severity.
  • مفاتيح إزالة التكرار: يرسل Alertmanager dedup_key ثابتًا (مستمدًا من بصمة التنبيه) بحيث تُحدَّث الإشعارات المتكررة لنفس التنبيه النشط حادثة PagerDuty القائمة بدلاً من فتح حادثة جديدة. هذا تلقائي — لكنه يعمل بشكل صحيح فقط إذا كانت تسميات group_by مستقرة عبر إطلاقات التنبيه.
  • روابط دفاتر التشغيل في التعليقات التوضيحية: أضف دومًا تعليقًا توضيحيًا runbook_url إلى قواعد التنبيه، وأظهره في قالب الإشعار حتى يصل مهندس المناوبة إلى دفتر التشغيل الصحيح بنقرة واحدة.
  • جهات استقبال Webhook: للحصول على منطق توجيه مخصص يتجاوز ما تدعمه شجرة Alertmanager، يمنحك جهاز استقبال webhook يرسل إلى Lambda صغيرة أو Cloud Run قدرة توجيه لا محدودة — مفيد للمنتجات متعددة المستأجرين التي يحتاج تنبيهها إلى التوجيه إلى قناة المستأجر المحددة الصحيحة.

التوفر العالي لـ Alertmanager

إن Alertmanager المنفرد هو نقطة إخفاق واحدة لسلسلة التنبيه بأكملها. يدعم Alertmanager تجمّعًا عاليًا للتوفر مبنيًا على بروتوكول gossip: شغّل ثلاث نسخ، وأشر بجميع خوادم Prometheus إليها جميعًا عبر alertmanager_config، ويستخدم Alertmanager بروتوكول Memberlist لتنسيق إزالة تكرار الإشعارات بحيث ترسل نسخة واحدة فقط كل تنبيه. العلامة الجوهرية هي --cluster.peer:

# تشغيل ثلاث نسخ Alertmanager — كل نسخة تعرف الأخريات عبر --cluster.peer alertmanager \ --config.file=/etc/alertmanager/alertmanager.yml \ --cluster.listen-address=0.0.0.0:9094 \ --cluster.peer=alertmanager-1:9094 \ --cluster.peer=alertmanager-2:9094 \ --web.listen-address=0.0.0.0:9093 # في إعداد Prometheus، اذكر جميع نسخ Alertmanager # prometheus.yml alerting: alertmanagers: - static_configs: - targets: - alertmanager-0:9093 - alertmanager-1:9093 - alertmanager-2:9093 timeout: 10s # Kubernetes: انشر كـ StatefulSet للحصول على أسماء DNS ثابتة # alertmanager-0.alertmanager.monitoring.svc.cluster.local # استخدم --cluster.peer بناءً على مؤشر pod الخاص بـ StatefulSet
مفهوم أساسي — إزالة تكرار gossip: في وضع التوفر العالي، تستقبل النسخ الثلاث جميعها نفس التنبيه من Prometheus. تتفاوض عبر gossip لاختيار مُرسِل واحد لكل مجموعة إشعارات. إذا سقطت تلك النسخة، تولّت أخرى المهمة. النتيجة: لا عواصف إشعارات ولا تنبيهات فائتة خلال إعادة التشغيل المتدرجة. شغّل دومًا عددًا فرديًا من النسخ (3 أو 5) لتجنب انقسام العقول في توافق gossip.

التحقق وتشخيص الأخطاء

أداتان يجب أن تكونا في متناول يدك دومًا كمشغّل Alertmanager: amtool check-config (تتحقق من صحة YAML ومنطق التوجيه قبل إعادة التحميل) ونقطة النهاية /api/v2/alerts (تعرض التنبيهات النشطة حاليًا، مفيدة في دفاتر التشغيل). تتيح واجهة Alertmanager على المنفذ :9093 مصحح شجرة التوجيه المرئي تحت "Status → Routing Tree" — الصق أي مجموعة تسميات وسيعرض لك بالضبط أي جهة استقبال ستستقبلها. هذا لا يقدر بثمن عند تشخيص سبب توجيه تنبيه إلى القناة الخاطئة.