برای راهاندازی هشدار در Prometheus سه قطعه لازم است: فایل قاعده (Alerting Rule) که Prometheus آن را در بازههای منظم ارزیابی میکند، اتصال Prometheus به Alertmanager، و فایل alertmanager.yml که هشدارها را گروهبندی میکند و بر اساس برچسب severity به ایمیل یا تلگرام میفرستد. پیش از اینکه به هشدارها تکیه کنید، پیکربندی را با promtool و amtool بررسی کنید و یک هشدار آزمایشی بفرستید.
این راهنما فرض میکند Prometheus و node_exporter روی سرور نصب شدهاند. اگر هنوز به این مرحله نرسیدهاید، ابتدا آموزش نصب و کانفیگ سرور Prometheus را ببینید. در آن مطلب و در راهنمای کانفیگ Prometheus و Grafana فقط یک نمونه کوتاه از Alertmanager آمده است؛ تمرکز این مطلب روی خود هشداردهی است: نوشتن قاعده، مسیریابی، گیرندهها، تست و خطاهای رایج. مثالها بر اساس مستندات رسمی prometheus.io نوشته شدهاند.
هشدار در Prometheus چگونه کار میکند؟
Prometheus خودش پیامی برای کسی نمیفرستد. در هر بازه ارزیابی، عبارت PromQL هر قاعده را اجرا میکند و اگر نتیجهای برگردد، برای هر سری زمانی یک هشدار میسازد و آن را به Alertmanager تحویل میدهد. Alertmanager تصمیم میگیرد هشدارها با چه گروهبندی، به کدام گیرنده و هر چند وقت یک بار ارسال شوند و کدامیک موقتاً ساکت بمانند.
| جزء | وظیفه | فایل یا پورت |
|---|---|---|
| node_exporter | انتشار متریکهای سیستم عامل مانند CPU، حافظه و دیسک | پورت 9100 |
| Prometheus | جمعآوری متریک و ارزیابی Alerting Rules | prometheus.yml و فایلهای rule_files |
| Alertmanager | گروهبندی، مسیریابی، Silence و ارسال اعلان | alertmanager.yml، پورت 9093 |
| گیرنده (Receiver) | مقصد نهایی پیام | ایمیل، تلگرام یا Webhook |
هر هشدار سه وضعیت دارد. در وضعیت inactive شرط برقرار نیست. در وضعیت pending شرط برقرار شده اما مدتی که با for تعیین کردهاید هنوز تمام نشده است. در وضعیت firing شرط به اندازه for ادامه داشته و هشدار برای Alertmanager ارسال میشود. وضعیت همه قاعدهها را در صفحه Alerts رابط وب Prometheus میبینید.
نوشتن Alerting Rules در Prometheus
قاعدهها را در فایلی جداگانه مانند /etc/prometheus/rules/node-alerts.yml بنویسید تا فایل اصلی شلوغ نشود. نمونه زیر چهار هشدار پایه برای سرورهای لینوکس دارد: از دسترس خارج شدن سرور، کمبود فضای دیسک، کمبود حافظه و مصرف بالای CPU.
groups:
- name: node-basic
rules:
- alert: InstanceDown
expr: up == 0
for: 2m
labels:
severity: critical
annotations:
summary: "Instance {{ $labels.instance }} is down"
description: "Prometheus could not scrape {{ $labels.job }} for 2 minutes."
- alert: DiskSpaceLow
expr: (node_filesystem_avail_bytes{fstype=~"ext4|xfs"} / node_filesystem_size_bytes{fstype=~"ext4|xfs"}) * 100 < 10
for: 10m
labels:
severity: warning
annotations:
summary: "Low disk space on {{ $labels.instance }} ({{ $labels.mountpoint }})"
description: 'Only {{ printf "%.1f" $value }}% free.'
- alert: MemoryPressure
expr: (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 < 10
for: 10m
labels:
severity: warning
annotations:
summary: "Available memory below 10% on {{ $labels.instance }}"
- alert: HighCpuUsage
expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90
for: 15m
labels:
severity: warning
annotations:
summary: "CPU above 90% for 15 minutes on {{ $labels.instance }}"نقش for و keep_firing_for
گزینه for جلوی هشدارهای لحظهای را میگیرد؛ یک جهش سیثانیهای CPU نباید کسی را نیمهشب بیدار کند. اگر for را ننویسید، هشدار با اولین ارزیابی موفق firing میشود. برای InstanceDown مقدار کوتاه و برای دیسک و CPU مقدار طولانیتر انتخاب کنید، چون پر شدن دیسک تدریجی است و چند دقیقه تأخیر در اعلان آن مشکلی ایجاد نمیکند.
keep_firing_for کار برعکس را انجام میدهد: هشدار را پس از برطرف شدن شرط، مدتی در وضعیت firing نگه میدارد. این گزینه برای متریکهایی که دور مرز آستانه نوسان میکنند مفید است، چون جلوی ارسال پشت سر هم پیام «رفع شد» و «دوباره فعال شد» را میگیرد.
برچسب severity و annotations
برچسبهای بخش labels به هشدار اضافه میشوند و Alertmanager مسیر ارسال را با همین برچسبها انتخاب میکند. annotations فقط متن توضیحی هستند و در مسیریابی اثری ندارند. داخل annotations با {{ $labels.instance }} به برچسبهای سری زمانی و با {{ $value }} به مقدار عددی عبارت دسترسی دارید.
در عمل دو سطح severity کافی است: critical برای مشکلی که همین حالا اقدام میخواهد و warning برای چیزی که میتواند تا ساعت کاری صبر کند. برای هر هشدار یک annotation به نام runbook با نشانی دستورالعمل رفع مشکل هم اضافه کنید تا کسی که پیام را میخواند بداند قدم اول چیست.
بررسی قاعدهها و اتصال Prometheus به Alertmanager
پیش از بارگذاری، نحو فایل را با promtool بررسی کنید. سپس مسیر فایل را در بخش rule_files و نشانی Alertmanager را در بخش alerting فایل prometheus.yml قرار دهید:
promtool check rules /etc/prometheus/rules/node-alerts.yml
promtool check config /etc/prometheus/prometheus.yml
# prometheus.yml
rule_files:
- /etc/prometheus/rules/*.yml
alerting:
alertmanagers:
- static_configs:
- targets:
- localhost:9093
# Reload without a full restart
sudo kill -HUP $(pidof prometheus)
curl -X POST http://localhost:9090/-/reload # only if started with --web.enable-lifecycleنقطه پایانی /-/reload بهصورت پیشفرض غیرفعال است و فقط وقتی کار میکند که Prometheus با فلگ –web.enable-lifecycle اجرا شده باشد؛ در غیر این صورت از سیگنال SIGHUP استفاده کنید. اگر چند Alertmanager بهصورت خوشه دارید، مستندات Alertmanager توصیه میکند نشانی همه آنها را در targets بنویسید و ترافیک بینشان را Load Balance نکنید.
پیکربندی Alertmanager: گروهبندی، routing و گیرندهها
فایل alertmanager.yml سه بخش اصلی دارد: route که درخت مسیریابی است، receivers که مقصدها را تعریف میکند و inhibit_rules که هشدارهای وابسته را ساکت میکند. نمونه زیر هشدارهای critical را هم به تلگرام و هم به ایمیل میفرستد و بقیه هشدارها فقط به ایمیل میروند:
route:
receiver: ops-email
group_by: ['alertname', 'instance']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
- matchers:
- severity="critical"
receiver: ops-telegram
continue: true
- matchers:
- severity="critical"
receiver: ops-email
receivers:
- name: ops-email
email_configs:
- to: 'ops@example.com'
from: 'alertmanager@example.com'
smarthost: 'mail.example.com:587'
auth_username: 'alertmanager@example.com'
auth_password_file: '/etc/alertmanager/smtp_password'
send_resolved: true
- name: ops-telegram
telegram_configs:
- bot_token_file: '/etc/alertmanager/telegram_token'
chat_id: -1001234567890
parse_mode: 'HTML'
inhibit_rules:
- source_matchers:
- severity="critical"
target_matchers:
- severity="warning"
equal: ['instance']ترتیب routes مهم است. Alertmanager زیرمسیرها را از بالا به پایین بررسی میکند و با اولین تطابق متوقف میشود، مگر اینکه continue برابر true باشد. در نمونه بالا continue باعث میشود هشدار critical پس از تلگرام به مسیر دوم هم برسد و ایمیل آن هم ارسال شود. هشداری که با هیچ زیرمسیری تطابق نداشته باشد، به receiver ریشه یعنی ops-email میرود.
group_by، group_wait و repeat_interval
| گزینه | پیشفرض | کاربرد |
|---|---|---|
| group_by | در نمونه: alertname و instance | هشدارهایی که این برچسبها را مشترک دارند در یک پیام ارسال میشوند |
| group_wait | 30s | مکث پیش از اولین پیام یک گروه تازه، تا هشدارهای مرتبط هم به همان پیام برسند |
| group_interval | 5m | فاصله ارسال پیام بعدی برای گروهی که هشدار جدید به آن اضافه شده است |
| repeat_interval | 4h | فاصله تکرار پیام برای هشداری که هنوز فعال است |
| continue | false | ادامه بررسی زیرمسیرهای بعدی پس از اولین تطابق |
فرض کنید ارتباط یک رک با بیست سرور قطع شود. اگر group_by فقط alertname باشد، به جای بیست پیام یک پیام با فهرست همه سرورها دریافت میکنید. اگر برعکس هر برچسب جزئی را در group_by بگذارید، گروهبندی عملاً بیاثر میشود.
ارسال هشدار Prometheus به ایمیل
در smarthost حتماً پورت را بنویسید. گزینه require_tls بهصورت پیشفرض true است، پس سرور SMTP روی آن پورت باید STARTTLS را پشتیبانی کند. send_resolved برای ایمیل بهصورت پیشفرض false است و اگر پیام «رفع شد» میخواهید، باید آن را true کنید. رمز SMTP را به جای متن فایل پیکربندی در فایلی جداگانه با دسترسی محدود نگه دارید:
sudo install -m 600 -o alertmanager -g alertmanager /dev/null /etc/alertmanager/smtp_password
sudo nano /etc/alertmanager/smtp_password # paste the SMTP password, no trailing spacesنام کاربر و گروه alertmanager به روش نصب شما بستگی دارد؛ همان کاربری را بنویسید که سرویس Alertmanager با آن اجرا میشود.
ارسال هشدار Prometheus به تلگرام
گیرنده داخلی telegram_configs از نسخه 0.24.0 به Alertmanager اضافه شده و به برنامه واسط نیازی ندارد. مراحل آمادهسازی:
- در تلگرام با BotFather یک ربات بسازید و توکن آن را در فایل /etc/alertmanager/telegram_token با دسترسی 600 ذخیره کنید.
- ربات را به گروه تیم فنی اضافه کنید و یک پیام در گروه بفرستید.
- با فراخوانی متد getUpdates در API تلگرام، مقدار chat.id را پیدا کنید. شناسه گروهها عدد منفی است.
- chat_id را بهصورت عدد و بدون کوتیشن در alertmanager.yml بنویسید؛ نوع این فیلد در مستندات int است.
برای گیرنده تلگرام، send_resolved بهصورت پیشفرض true و parse_mode پیشفرض HTML است و متن پیام از قالب پیشفرض telegram.default.message ساخته میشود. Alertmanager برای ارسال باید به api.telegram.org دسترسی خروجی داشته باشد. اگر شبکه سرور مانیتورینگ این مقصد را باز نمیکند، تلگرام را تنها گیرنده هشدارهای critical نکنید و ایمیل یا یک Webhook به سامانه داخلی سازمان را کنار آن تعریف کنید.
ساکت کردن هشدارهای وابسته با inhibit_rules
قاعده inhibit در نمونه بالا میگوید اگر برای یک instance هشدار critical فعال است، هشدارهای warning همان instance ارسال نشوند. وقتی سرور کلاً از دسترس خارج شده، پیامهای مربوط به CPU و دیسک همان سرور فقط شلوغی ایجاد میکنند. برچسبهایی که در equal مینویسید باید در هر دو هشدار وجود داشته باشند.
تست هشدار پیش از روز حادثه
هشداری که هیچوقت تست نشده ممکن است روز حادثه بهخاطر یک غلط تایپی در نام receiver ارسال نشود. این سه بررسی چند دقیقه وقت میگیرد و amtool همراه بسته Alertmanager نصب میشود:
# 1. Validate the configuration (no running Alertmanager needed)
amtool check-config /etc/alertmanager/alertmanager.yml
# 2. Which receiver gets an alert with these labels?
amtool config routes test --config.file=/etc/alertmanager/alertmanager.yml severity=critical
# 3. Send a test alert to the running Alertmanager
amtool alert add TestAlert severity=critical instance=test-01 \
--annotation=summary='Test alert, please ignore' \
--alertmanager.url=http://localhost:9093خروجی دستور دوم نام receiver را نشان میدهد. اگر انتظار دارید هشدار critical به تلگرام برود و فقط ops-email را میبینید، ترتیب routes یا matchers را بررسی کنید. پس از دستور سوم، پیام باید بعد از group_wait برسد. اگر نرسید، لاگ سرویس را با journalctl -u alertmanager -f دنبال کنید؛ خطای اتصال به SMTP یا API تلگرام همانجا ثبت میشود.
Silence برای زمان نگهداری
پیش از ریاستارت برنامهریزیشده یا بهروزرسانی کرنل، به جای حذف یا کامنت کردن قاعده، یک Silence موقت بسازید. Silence پس از پایان مدت خودش منقضی میشود و خطر فراموش کردن برگرداندن قاعده را ندارد:
amtool silence add instance="web01:9100" --duration=1h --comment="kernel update" \
--alertmanager.url=http://localhost:9093
amtool silence query --alertmanager.url=http://localhost:9093خطاهای رایج هشدار در Prometheus و Alertmanager
| مشکل | علت محتمل | راهحل |
|---|---|---|
| هشدار در صفحه Alerts در وضعیت pending میماند | متریک پیش از پایان for به حالت عادی برمیگردد | expr را در بخش Graph اجرا کنید، رفتار متریک را ببینید و for یا آستانه را اصلاح کنید |
| هشدار firing است اما پیامی نمیرسد | بخش alerting در prometheus.yml تنظیم نشده یا route به receiver دیگری میرسد | targets را بررسی و amtool config routes test را اجرا کنید |
| خطای TLS هنگام ارسال ایمیل | require_tls فعال است و سرور SMTP روی آن پورت STARTTLS ندارد | پورت و تنظیمات TLS سرور ایمیل را اصلاح کنید |
| خطای chat not found در لاگ تلگرام | ربات عضو گروه نیست یا chat_id اشتباه است | ربات را به گروه اضافه و شناسه را دوباره با getUpdates بخوانید |
| دهها پیام تکراری | group_by بیش از حد جزئی یا repeat_interval کوتاه | برچسبهای group_by را کمتر و repeat_interval را بیشتر کنید |
| پیام «رفع شد» برای ایمیل نمیآید | send_resolved در email_configs بهصورت پیشفرض false است | send_resolved: true را اضافه کنید |
| تغییر قاعده اعمال نمیشود | Prometheus پس از ویرایش فایل بارگذاری مجدد نشده است | promtool را اجرا و SIGHUP ارسال کنید |
چه چیزهایی ارزش هشدار دارند؟
هر هشدار باید یک اقدام مشخص پشتش داشته باشد. اگر گیرنده پیام نمیداند باید چه کند یا عادت کرده آن را نادیده بگیرد، قاعده را حذف کنید یا متریک را فقط در داشبورد نشان دهید. چند اصل ساده برای شروع:
- هشدار روی چیزی که کاربر حس میکند (در دسترس نبودن سرویس، خطای HTTP، تأخیر پاسخ) اولویت دارد بر متریکهای داخلی مثل مصرف CPU.
- برای دیسک، به جای درصد ثابت میتوانید زمان پر شدن را پیشبینی کنید؛ عبارت
predict_linear(node_filesystem_avail_bytes{fstype=~"ext4|xfs"}[6h], 24*3600) < 0یعنی با روند شش ساعت اخیر، دیسک تا ۲۴ ساعت دیگر پر میشود. - برای critical حداقل دو کانال مستقل تعریف کنید تا قطع شدن یک کانال باعث از دست رفتن هشدار نشود.
- هر چند ماه فهرست پیامهای ارسالشده را مرور کنید و قاعدههای پرسروصدا را اصلاح یا حذف کنید.
برای نمایش همین متریکها در داشبورد، آموزش کانفیگ سرور Grafana را ببینید. اگر هنوز بین ابزارها مردد هستید، مقایسه Zabbix، Prometheus و Nagios تفاوتها را نشان میدهد؛ در Zabbix هشداردهی داخل خود سرور Zabbix تعریف میشود و به Alertmanager نیازی نیست. طراحی، مستندسازی و بازبینی دورهای هشدارها بخشی از خدمات مانیتورینگ زیرساخت و Observability کانفیگ سرور است.
سوالات متداول
آیا بدون Alertmanager میتوان از Prometheus هشدار گرفت؟
Prometheus قاعدهها را ارزیابی میکند و وضعیتشان را در صفحه Alerts نشان میدهد، اما ارسال ایمیل یا پیام تلگرام، گروهبندی و Silence کار Alertmanager است. Grafana هم سامانه هشدار مستقلی دارد که میتواند روی داده Prometheus کار کند.
Alertmanager باید روی همان سرور Prometheus نصب شود؟
الزامی نیست و برای محیط کوچک نصب روی همان سرور کافی است. اما اگر همان سرور از دسترس خارج شود، هیچ هشداری ارسال نمیشود. برای این حالت یک بررسی ساده از بیرون، روی سرور یا شبکهای دیگر، در نظر بگیرید.
چرا یک هشدار پشت سر هم فعال و رفع میشود؟
متریک دور مرز آستانه نوسان میکند. for را طولانیتر کنید، از میانگین در بازه زمانی (مثلاً rate روی ۵ دقیقه) استفاده کنید یا با keep_firing_for هشدار را پس از رفع شرط مدتی فعال نگه دارید.
فایلهای rule را کجا نگه داریم؟
فایلهای rule و alertmanager.yml را در یک مخزن Git نگه دارید و پیش از اعمال، promtool و amtool check-config را اجرا کنید. به این ترتیب تاریخچه تغییرات هشدارها مشخص است و خطای نحوی به سرور نمیرسد.





