مانیتورینگ سرور با Prometheus و Grafana: راهاندازی با Docker Compose و تعریف هشدار
بیشتر تیمها از کاربرانشان میشنوند که سرور مشکل دارد: «سایت باز نمیشود»، «خیلی کند است». مانیتورینگ این ترتیب را برعکس میکند. شما قبل از کاربر خبردار میشوید و، مهمتر از آن، وقتی مشکلی پیش آمد، نمودار چند روز گذشته را دارید تا بفهمید از کی و چرا شروع شده است.
در این آموزش یک مجموعهی استاندارد و متنباز راهاندازی میکنیم:
- Prometheus: متریکها را در فواصل منظم جمعآوری و ذخیره میکند و قوانین هشدار را ارزیابی میکند.
- Node Exporter: متریکهای سیستمعامل (CPU، RAM، دیسک، شبکه) را در اختیار Prometheus میگذارد.
- Grafana: داشبورد و نمودار.
- Alertmanager (اختیاری): هشدارها را به ایمیل، تلگرام یا Webhook میفرستد.
پیشنیازها
- یک سرور Ubuntu 24.04 با Docker و Docker Compose. برای چند ده سرور، ۲ هسته و ۴ گیگابایت RAM معمولاً کافی است؛ حجم دیسک به تعداد متریکها و مدت نگهداری بستگی دارد.
- ترجیحاً سرور مانیتورینگ جدا از سرورهایی باشد که مانیتور میکند؛ وگرنه وقتی سرور از کار بیفتد، مانیتورینگ هم با آن از کار میافتد.
- اگر روی سرور داخل ایران هستید و ایمیجها دانلود نمیشوند، مقالهی دسترسی به Docker Hub از ایران را ببینید.
قدم ۱: ساختار پوشهها و docker-compose.yml
mkdir -p /opt/monitoring/{prometheus,alertmanager}
cd /opt/monitoring
فایل docker-compose.yml:
services:
prometheus:
image: prom/prometheus:latest
restart: unless-stopped
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.path=/prometheus
- --storage.tsdb.retention.time=30d
volumes:
- ./prometheus:/etc/prometheus:ro
- prometheus-data:/prometheus
ports:
- "127.0.0.1:9090:9090"
extra_hosts:
- "host.docker.internal:host-gateway"
node-exporter:
image: prom/node-exporter:latest
restart: unless-stopped
command:
- --path.rootfs=/host
network_mode: host
pid: host
volumes:
- /:/host:ro,rslave
alertmanager:
image: prom/alertmanager:latest
restart: unless-stopped
volumes:
- ./alertmanager:/etc/alertmanager:ro
ports:
- "127.0.0.1:9093:9093"
grafana:
image: grafana/grafana:latest
restart: unless-stopped
environment:
GF_SECURITY_ADMIN_PASSWORD: "change-this-password"
GF_USERS_ALLOW_SIGN_UP: "false"
volumes:
- grafana-data:/var/lib/grafana
ports:
- "127.0.0.1:3000:3000"
volumes:
prometheus-data:
grafana-data:
چند نکته دربارهی این فایل:
- همهی پورتها فقط روی
127.0.0.1باز شدهاند. هیچکدام از این سرویسها نباید مستقیم روی اینترنت در دسترس باشد (در بخش امنیت توضیح میدهیم). - Node Exporter با
network_mode: hostاجرا میشود تا متریکهای شبکهی واقعی میزبان را ببیند، و روی پورت9100میزبان گوش میدهد. چون در این حالت نمیتوان پورت را به 127.0.0.1 محدود کرد، پورت 9100 را با فایروال از بیرون ببندید. - در Production بهجای
latestنسخهی مشخص بنویسید تا ارتقا تحت کنترل شما باشد.
قدم ۲: تنظیم Prometheus
فایل prometheus/prometheus.yml:
global:
scrape_interval: 30s
evaluation_interval: 30s
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:9093"]
rule_files:
- /etc/prometheus/alerts.yml
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ["localhost:9090"]
- job_name: node
static_configs:
- targets:
- "host.docker.internal:9100" # همین سرور
- "10.0.0.21:9100" # سرورهای دیگر
- "10.0.0.22:9100"
برای مانیتور کردن سرورهای دیگر، روی هر کدام Node Exporter را نصب کنید. سادهترین راه بدون Docker، بستهی خود Ubuntu است:
apt install -y prometheus-node-exporter
systemctl enable --now prometheus-node-exporter
و در فایروال آن سرور، پورت 9100 را فقط برای IP سرور مانیتورینگ باز کنید:
ufw allow from 10.0.0.10 to any port 9100 proto tcp
اگر سرورها در شبکهی خصوصی مشترک نیستند و ترافیک از اینترنت عبور میکند، از TLS و احراز هویت Node Exporter یا یک تونل (مثل WireGuard) استفاده کنید.
قدم ۳: قوانین هشدار
فایل prometheus/alerts.yml با سه هشدار پایه که تقریباً همهی سرورها به آن نیاز دارند:
groups:
- name: node
rules:
- alert: InstanceDown
expr: up == 0
for: 2m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} در دسترس نیست"
- alert: DiskAlmostFull
expr: |
(1 - node_filesystem_avail_bytes{fstype!~"tmpfs|overlay|squashfs"}
/ node_filesystem_size_bytes{fstype!~"tmpfs|overlay|squashfs"}) * 100 > 85
for: 10m
labels:
severity: warning
annotations:
summary: "دیسک {{ $labels.mountpoint }} روی {{ $labels.instance }} بیش از ۸۵٪ پر است"
- alert: HighLoad
expr: |
node_load5 / on(instance)
count by (instance) (node_cpu_seconds_total{mode="idle"}) > 1.5
for: 15m
labels:
severity: warning
annotations:
summary: "بار پردازشی {{ $labels.instance }} بیش از ۱.۵ برابر تعداد هستهها است"
هشدار HighLoad، Load پنجدقیقهای را به تعداد هستهها تقسیم میکند تا یک آستانه برای سرورهای کوچک و بزرگ معنی داشته باشد. عدد ۱.۵ نقطهی شروع است؛ آن را با رفتار عادی سرورهای خودتان تنظیم کنید. گزینهی for جلوی هشدارهای لحظهای و بیاهمیت را میگیرد. هشدار زیاد و بیمورد بدترین دشمن مانیتورینگ است، چون تیم یاد میگیرد هشدارها را نادیده بگیرد.
قبل از اجرا، تنظیمات را تست کنید:
docker run --rm -v /opt/monitoring/prometheus:/etc/prometheus:ro --entrypoint promtool \
prom/prometheus:latest check config /etc/prometheus/prometheus.yml
promtool هم فایل اصلی و هم فایل قوانین هشدار را بررسی میکند. اگر بعداً تنظیمات را تغییر دادید، بعد از همین تست، با docker compose restart prometheus آن را اعمال کنید.
قدم ۴: Alertmanager
فایل alertmanager/alertmanager.yml با یک گیرندهی ایمیل:
route:
receiver: team-email
group_by: [alertname, instance]
repeat_interval: 4h
receivers:
- name: team-email
email_configs:
- to: ops@example.com
from: alerts@example.com
smarthost: mail.example.com:587
auth_username: alerts@example.com
auth_password: "smtp-password"
Alertmanager گیرندههای دیگری مثل Telegram و Webhook را هم پشتیبانی میکند. فهرست کامل و فیلدهای هر کدام را در مستندات رسمی نسخهای که نصب کردهاید ببینید. حالا همهچیز را بالا بیاورید:
docker compose up -d
docker compose ps
با یک تونل SSH وضعیت Targetها را ببینید (روی سیستم خودتان اجرا کنید):
ssh -L 9090:127.0.0.1:9090 -L 3000:127.0.0.1:3000 user@monitoring-server
و در مرورگر http://localhost:9090/targets را باز کنید. همهی Targetها باید وضعیت UP داشته باشند.
قدم ۵: Grafana و داشبورد Node Exporter Full
با همان تونل، http://localhost:3000 را باز کنید و با کاربر admin و رمزی که در Compose گذاشتید وارد شوید.
- از Connections ← Data sources ← Add data source، نوع Prometheus را انتخاب کنید و آدرس
http://prometheus:9090را وارد کنید. - از Dashboards ← New ← Import، شناسهی 1860 را وارد کنید. این شناسهی داشبورد محبوب و جامع «Node Exporter Full» در سایت grafana.com است.
- Data Source را Prometheus انتخاب کنید و Import را بزنید.
اگر Import با شناسه از ایران کار نکرد
Grafana برای Import با شناسه باید به grafana.com وصل شود که ممکن است از سرورهای داخل ایران در دسترس نباشد. در این صورت فایل JSON داشبورد را از صفحهی آن در grafana.com (با گزینهی Download JSON) روی سیستمی که دسترسی دارد دانلود کنید و در همان صفحهی Import، بهجای شناسه، فایل را آپلود یا محتوای آن را Paste کنید. اگر داشبوردها را در مخزن Git نگه دارید، میتوانید آنها را با قابلیت Provisioning خود Grafana بهصورت خودکار بارگذاری کنید.
قدم ۶: امنیت؛ مهمتر از آنچه به نظر میرسد
- هیچ پورتی را عمومی نکنید. Prometheus و Alertmanager بهطور پیشفرض احراز هویت ندارند و هر کسی که به آنها دسترسی داشته باشد، نقشهی کامل زیرساخت شما را میبیند. Node Exporter هم اطلاعات زیادی دربارهی سیستم فاش میکند.
- Reverse Proxy با SSL و احراز هویت: اگر Grafana باید از بیرون در دسترس باشد، آن را پشت Nginx یا Caddy با HTTPS قرار دهید، و اگر ممکن است، دسترسی را به IPهای دفتر یا VPN محدود کنید. برای Prometheus در صورت نیاز، حداقل Basic Auth بگذارید.
- رمز admin را عوض کنید و برای هر نفر کاربر جداگانه با کمترین سطح دسترسی لازم بسازید.
- Docker و ufw: پورتهایی که Docker منتشر میکند، قوانین ufw را دور میزنند. به همین دلیل در Compose پورتها را به 127.0.0.1 بستیم. جزئیات بیشتر در چکلیست امنیت کانتینرهای Docker.
قدم بعدی
این مجموعه پایهی مانیتورینگ است. بعد از آن معمولاً Exporterهای سرویسها اضافه میشوند: mysqld_exporter برای دیتابیس، blackbox_exporter برای بررسی در دسترس بودن سایتها و تاریخ انقضای SSL، و Exporter وبسرور. اگر دیسک سرورتان قبلاً پر شده، هشدار دیسک را اول از همه فعال کنید؛ راهحل وضعیت فعلی را در پر شدن دیسک سرور لینوکس ببینید.
نمیخواهید این کار را خودتان انجام دهید؟ تیم مروانت مانیتورینگ، داشبورد و هشدارهای متناسب با سرویسهای شما را راهاندازی میکند و هشدارها را به کانال تیمتان وصل میکند. صفحهی مدیریت و پشتیبانی سرور را ببینید.
