مانیتورینگ سرور با 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 گذاشتید وارد شوید.

  1. از Connections ← Data sources ← Add data source، نوع Prometheus را انتخاب کنید و آدرس http://prometheus:9090 را وارد کنید.
  2. از Dashboards ← New ← Import، شناسه‌ی 1860 را وارد کنید. این شناسه‌ی داشبورد محبوب و جامع «Node Exporter Full» در سایت grafana.com است.
  3. 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 وب‌سرور. اگر دیسک سرورتان قبلاً پر شده، هشدار دیسک را اول از همه فعال کنید؛ راه‌حل وضعیت فعلی را در پر شدن دیسک سرور لینوکس ببینید.

نمی‌خواهید این کار را خودتان انجام دهید؟ تیم مروانت مانیتورینگ، داشبورد و هشدارهای متناسب با سرویس‌های شما را راه‌اندازی می‌کند و هشدارها را به کانال تیمتان وصل می‌کند. صفحه‌ی مدیریت و پشتیبانی سرور را ببینید.

دیدگاهتان را بنویسید

جستجو

فهرست مطالب