Prometheus، Grafana و Alertmanager ترکیب استاندارد مانیتورینگ زیرساختهای مدرن هستند و بدون نیاز به لایسنس، روی یک سرور کوچک هم اجرا میشوند. در این راهنما یک استک کامل را با Docker Compose راه میاندازیم: Prometheus برای جمعآوری و ذخیرهی متریک، node_exporter برای متریک میزبان، cAdvisor برای متریک کانتینرها، Alertmanager برای هشدار و Grafana برای نمودار. همهی فایلها قابلکپیاند.
معماری در یک نگاه
| جزء | نقش | پورت پیشفرض |
|---|---|---|
| Prometheus | جمعآوری (pull) و ذخیرهی متریک؛ ارزیابی قواعد هشدار | 9090 |
| node_exporter | متریک میزبان: CPU، حافظه، دیسک، شبکه | 9100 |
| cAdvisor | متریک هر کانتینر Docker | 8080 |
| Alertmanager | گروهبندی و ارسال هشدار (ایمیل، webhook، …) | 9093 |
| Grafana | داشبورد و کاوش داده | 3000 |
جریان کار: exporterها متریک را روی یک آدرس HTTP (معمولاً /metrics) نشان میدهند، Prometheus هر ۱۵ ثانیه آنها را میخواند، قواعد هشدار را ارزیابی میکند و هشدارهای فعال را به Alertmanager میفرستد، و Grafana از Prometheus کوئری میگیرد.
ساختار پوشهها
monitoring/
├── docker-compose.yml
├── prometheus/
│ ├── prometheus.yml
│ └── rules.yml
├── alertmanager/
│ └── alertmanager.yml
└── grafana/
└── provisioning/datasources/prometheus.yml
فایل docker-compose.yml
نسخهها را ثابت کردهایم (اصل ثابتبودن تگ در راهنمای اشتباههای رایج Compose توضیح داده شده)؛ پیش از استفاده با آخرین نسخهی پایدار هر پروژه جایگزین کنید.
services:
prometheus:
image: prom/prometheus:v2.55.0
restart: unless-stopped
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.retention.time=15d
- --web.enable-lifecycle
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- ./prometheus/rules.yml:/etc/prometheus/rules.yml:ro
- prom_data:/prometheus
ports:
- "127.0.0.1:9090:9090"
networks: [monitoring]
node-exporter:
image: prom/node-exporter:v1.8.2
restart: unless-stopped
command: ["--path.rootfs=/host"]
pid: host
volumes:
- /:/host:ro,rslave
networks: [monitoring]
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.49.1
restart: unless-stopped
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
networks: [monitoring]
alertmanager:
image: prom/alertmanager:v0.27.0
restart: unless-stopped
volumes:
- ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
networks: [monitoring]
grafana:
image: grafana/grafana:11.3.0
restart: unless-stopped
environment:
GF_SECURITY_ADMIN_PASSWORD__FILE: /run/secrets/grafana_admin
secrets: [grafana_admin]
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning:ro
ports:
- "127.0.0.1:3000:3000"
networks: [monitoring]
secrets:
grafana_admin:
file: ./secrets/grafana_admin.txt
volumes:
prom_data:
grafana_data:
networks:
monitoring:
YMLDocker Compose Validatorفایل Compose را پیش از اجرا بررسی کنید.- پورتهای Prometheus و Grafana فقط روی
127.0.0.1منتشر شدهاند؛ Alertmanager، node_exporter و cAdvisor اصلاً منتشر نشدهاند و فقط داخل شبکهیmonitoringدر دسترساند. برای دسترسی از بیرون، یک reverse proxy با HTTPS و احراز هویت جلوی Grafana بگذارید (راهنمای Nginx). - رمز ادمین Grafana از فایل خوانده میشود (پسوند
__FILEدر متغیرهای Grafana)؛ فایلsecrets/grafana_admin.txtرا در Git نگذارید. - cAdvisor دسترسی خواندنی گسترده به میزبان لازم دارد؛ به همین دلیل آن را فقط در شبکهی داخلی نگه میداریم.
پیکربندی Prometheus
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- /etc/prometheus/rules.yml
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:9093"]
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ["localhost:9090"]
- job_name: node
static_configs:
- targets: ["node-exporter:9100"]
- job_name: cadvisor
static_configs:
- targets: ["cadvisor:8080"]
نامهای node-exporter و cadvisor همان نام سرویسهای Composeاند که در شبکهی مشترک resolve میشوند. برای افزودن سرورهای دیگر، آدرس IP:9100 هر یک را به targets job مربوط به node اضافه کنید.
قواعد هشدار اولیه
groups:
- name: basics
rules:
- alert: InstanceDown
expr: up == 0
for: 2m
labels: { severity: critical }
annotations:
summary: "{{ $labels.job }} on {{ $labels.instance }} is down"
- alert: DiskSpaceLow
expr: |
node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}
/ node_filesystem_size_bytes{fstype!~"tmpfs|overlay"} < 0.10
for: 10m
labels: { severity: warning }
annotations:
summary: "Less than 10% disk space left on {{ $labels.instance }} ({{ $labels.mountpoint }})"
- alert: HighMemoryUsage
expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) > 0.90
for: 10m
labels: { severity: warning }
annotations:
summary: "Memory usage above 90% on {{ $labels.instance }}"
بخش for مهم است: هشدار فقط وقتی فعال میشود که شرط برای آن مدت پیوسته برقرار باشد؛ این کار جلوی هشدارهای کاذب از نوسانهای کوتاه را میگیرد. اصول انتخاب و طراحی هشدار در راهنمای هشداردهی اصولی آمده است.
Alertmanager
Alertmanager هشدارها را گروهبندی میکند و به مقصد میفرستد. نمونهی ساده با webhook (برای مثال یک ربات پیامرسان یا سرویس داخلی):
route:
receiver: team
group_by: [alertname, instance]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receivers:
- name: team
webhook_configs:
- url: http://notifier.internal:8080/alerts
send_resolved: true
گزینهی send_resolved پیام «برطرف شد» را هم میفرستد و repeat_interval فاصلهی یادآوری هشدار هنوز فعال را تعیین میکند؛ مقدار کم آن باعث نویز میشود.
اتصال Grafana به Prometheus
با provisioning، اتصال هنگام بالاآمدن Grafana خودکار ساخته میشود و نیازی به کلیک در رابط نیست (grafana/provisioning/datasources/prometheus.yml):
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
برای شروع سریع، یک داشبورد آماده وارد کنید: در Grafana مسیر Dashboards → New → Import و شناسهی 1860 (Node Exporter Full) را وارد کنید. برای cAdvisor هم در grafana.com داشبوردهای آماده با عبارت «cadvisor» پیدا میشوند.
اجرا و راستیآزمایی
mkdir -p secrets && openssl rand -base64 24 > secrets/grafana_admin.txt
docker compose up -d
docker compose ps
curl -s localhost:9090/-/ready # Prometheus آماده است؟
curl -s 'localhost:9090/api/v1/query?query=up'
خروجی کوئری up باید برای هر هدف مقدار 1 نشان دهد. نمای کامل هدفها در رابط Prometheus، بخش Status → Targets، است. از راه دور با تونل SSH به رابطها دسترسی بگیرید:
ssh -L 3000:localhost:3000 -L 9090:localhost:9090 user@server
قواعد را بدون ریاستارت میتوان بازخوانی کرد (بهخاطر --web.enable-lifecycle): curl -X POST localhost:9090/-/reload. این endpoint نباید از بیرون در دسترس باشد.
نکتههای بهرهبرداری
- دیسک: رشد دیسک با تعداد سریهای زمانی و مدت نگهداری تعیین میشود. متریک
prometheus_tsdb_head_seriesرا زیر نظر بگیرید و روی labelهایی که مقدارهای بیپایان دارند (شناسهی کاربر، URL کامل) سری نسازید. - پشتیبان: اگر دادهی تاریخی مهم است، snapshot بگیرید یا از ذخیرهسازی راه دور (remote write) استفاده کنید.
- مانیتور خود مانیتورینگ: اگر خود Prometheus از کار بیفتد، هیچ هشداری ارسال نمیشود. یک بررسی مستقل بیرونی (heartbeat) برای آن بگذارید.
- اگر روی Kubernetes هستید: بهجای Compose معمولاً از kube-prometheus-stack (Helm) استفاده میشود، ولی مفاهیم و PromQL همان است.
Grafana و Docker را روی سرور ایران میتوانید از مخزن داخلی نصب کنید؛ مراحل در راهنمای نصب از مخزن داخلی آمده است.
جمعبندی و مطالعهی بعدی
با یک فایل Compose و سه فایل پیکربندی، مانیتورینگ پایهی میزبان و کانتینرها آماده است. گام بعدی یادگرفتن زبان کوئری است: PromQL برای شروع کوئریهای ضروری را با مثال نشان میدهد و هشداردهی اصولی کمک میکند هشدارهایی بنویسید که واقعاً ارزش بیدارشدن را داشته باشند.
پرسشهای متداول
Prometheus بهجای push، چرا متریکها را pull میکند؟
up). برای کارهای کوتاهمدت که اجازهی scrape ندارند، Pushgateway وجود دارد، ولی استفادهی عمومی از آن توصیه نمیشود.دادهها چقدر نگه داشته میشوند و چقدر دیسک لازم است؟
--storage.tsdb.retention.time). بهطور تقریبی هر نمونه حدود ۱ تا ۲ بایت فشرده میشود؛ پس دیسک ≈ نمونهی در ثانیه × بایت هر نمونه × ثانیههای نگهداری. با prometheus_tsdb_head_series تعداد سریهای فعال را ببینید و بر اساس آن تخمین بزنید.Grafana یا Prometheus: کدام برای هشدار بهتر است؟
برای چند سرور چه کنم؟
targets یا با service discovery (فایل، DNS یا Kubernetes) به Prometheus بدهید. ارتباط را روی شبکهی خصوصی یا VPN نگه دارید، نه اینترنت عمومی.