مراقبة أداء النظام
المراقبة الجيدة ضرورية لاكتشاف المشكلات قبل أن تؤثر على المستخدمين. فالقرص الذي يمتلئ، أو تسرّب الذاكرة في worker لـ PHP، أو العملية التي تستحوذ على المعالج، يظهر دائماً تقريباً في المقاييس قبل ساعات، بل أيام، من العطل. لكن يبقى عليك أن تعرف ما الذي تراقبه، وبأي أدوات، وعند أي عتبة تتدخل.
يغطي هذا المقال مستويين متكاملين: التشخيص المباشر، عندما تكون متصلاً عبر SSH بجهاز بطيء، والمراقبة المستمرة، مع مقاييس محفوظة تاريخياً وتنبيهات تلقائية.
المنهجية قبل الأدوات
أمام خادم بطيء، يكون الإغراء هو تشغيل htop والتحديق في الشاشة. النهج الأكثر فعالية هو المرور على كل مورد (المعالج، الذاكرة، القرص، الشبكة) وطرح ثلاثة أسئلة، وفق منهجية USE التي روّج لها Brendan Gregg:
- الاستخدام (Utilisation): ما النسبة المئوية من الوقت التي يكون فيها المورد مشغولاً؟
- التشبّع (Saturation): هل هناك عمل ينتظر في طابور بسبب نقص السعة؟
- الأخطاء (Errors): هل يبلّغ المورد عن أخطاء (حزم مفقودة، أخطاء إدخال/إخراج)؟
يمكن أن يكون المورد مستخدماً بنسبة 100% دون أي مشكلة، ما دام لا يوجد تشبّع. وعلى العكس، فإن قرصاً مستخدماً بنسبة 60% مع طابور انتظار طويل يُعدّ بالفعل عنق زجاجة.
الأدوات الأساسية
# Real-time CPU and memory
htop
# Disk statistics
iostat -x 1
# Network traffic
iftop -i eth0
# Resource-hungry processes
ps aux --sort=-%mem | head -20
بعض النقاط المرجعية لقراءة هذه المخرجات:
htopيعرض الاستخدام لكل نواة، والذاكرة، والـ swap. رتّب حسب العمود باستخدامF6واعرض شجرة العمليات باستخدامF5لترى أي عملية أب أطلقت أي عمليات أبناء.iostat -x 1(حزمةsysstat) يتحدّث كل ثانية. راقب%util(نسبة انشغال الجهاز)، وr_awaitوw_await(متوسط زمن الاستجابة بالمللي ثانية)، وaqu-sz(متوسط حجم طابور الانتظار). ارتفاع زمن الاستجابة مؤشر على التشبّع.iftopيعرض معدل النقل لكل اتصال. عدّل اسم الواجهة: في التوزيعات الحديثة غالباً ما تسمىens3أوenp0s3بدلاً منeth0(تحقق باستخدامip -br link).ps aux --sort=-%memيسرد العمليات الأكثر استهلاكاً للذاكرة. استبدله بـ--sort=-%cpuللمعالج.
قراءة الذاكرة والحمل بشكل صحيح
مؤشران يُساء فهمهما كثيراً. أولاً الذاكرة: يستخدم Linux الذاكرة الحرة كـ cache للقرص. لذا فإن قيمة free القريبة من الصفر أمر طبيعي. العمود المهم هو available، أي تقدير الذاكرة القابلة للاستخدام دون اللجوء إلى الـ swap.
ثانياً متوسط الحمل (load average): القيم الثلاث التي يعرضها uptime هي متوسطات على مدى 1 و5 و15 دقيقة لعدد العمليات قيد التنفيذ أو المنتظرة للتنفيذ. في Linux، تشمل أيضاً العمليات المحجوبة في انتظار الإدخال/الإخراج. حمل بقيمة 4 على جهاز بأربع أنوية يعني أن المعالج مشغول بالكامل؛ وما فوق ذلك يعني أن هناك مهاماً تنتظر.
# Memory: look at the "available" column, not "free"
free -h
# Load average over 1, 5 and 15 minutes, and number of cores
uptime
nproc
# Summary view every second, 5 times:
# r = processes waiting for CPU, si/so = swap, wa = I/O wait
vmstat 1 5
# Resource pressure (kernel 4.20+)
cat /proc/pressure/cpu /proc/pressure/memory /proc/pressure/io
في مخرجات vmstat، يشير عمود r الذي يتجاوز باستمرار عدد الأنوية إلى تشبّع المعالج، وتعني القيم غير الصفرية في si/so أن الجهاز يستخدم الـ swap بنشاط، مما يضعف الأداء بشدة. أما ملفات /proc/pressure/* (PSI) فتعطي مباشرة النسبة المئوية من الوقت الذي تأخرت فيه المهام بسبب نقص مورد ما.
المراقبة باستخدام Prometheus وNode Exporter
الأدوات التفاعلية لا تعرض إلا اللحظة الحالية. لفهم تدهور تدريجي أو تحليل حادثة وقعت ليلاً، تحتاج إلى مقاييس محفوظة تاريخياً. أصبح الثنائي Prometheus وNode Exporter هو المعيار: يعرض Node Exporter مقاييس النظام (المعالج، الذاكرة، الأقراص، الشبكة، أنظمة الملفات) على المنفذ 9100، ويجمعها Prometheus على فترات منتظمة.
# Install Node Exporter
wget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
tar xvfz node_exporter-*.tar.gz
sudo mv node_exporter-*/node_exporter /usr/local/bin/
تحقق من أحدث إصدار على صفحة إصدارات المشروع قبل التثبيت. بعد ذلك، بدلاً من تشغيل الملف التنفيذي يدوياً، شغّله كخدمة systemd تحت مستخدم مخصص بلا shell:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin node_exporter
# /etc/systemd/system/node_exporter.service
[Unit]
Description=Prometheus Node Exporter
After=network-online.target
Wants=network-online.target
[Service]
User=node_exporter
Group=node_exporter
ExecStart=/usr/local/bin/node_exporter --web.listen-address=127.0.0.1:9100
Restart=on-failure
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
curl -s http://127.0.0.1:9100/metrics | grep node_load1
الاستماع على 127.0.0.1 يتجنب كشف المقاييس على الإنترنت. إذا كان Prometheus يعمل على جهاز آخر، فاستمع على الواجهة الخاصة وقيّد الوصول إلى المنفذ 9100 عبر الجدار الناري. من جهة Prometheus، يكفي إضافة هدف:
# prometheus.yml
scrape_configs:
- job_name: node
scrape_interval: 15s
static_configs:
- targets: ['10.0.0.5:9100']
تنبيهات النظام
اضبط تنبيهات للمقاييس الحرجة:
- المعالج: تنبيه فوق 80% لمدة 5 دقائق
- الذاكرة: تنبيه فوق 90%
- القرص: تنبيه فوق 85%
- متوسط الحمل: تنبيه فوق عدد المعالجات
عند ترجمة هذه العتبات إلى قواعد Prometheus، نحصل على الملف التالي. يفرض البند for أن يبقى الشرط صحيحاً لمدة دنيا، مما يجنّبك الاستيقاظ بسبب ذروة تدوم بضع ثوانٍ:
# /etc/prometheus/rules/node.yml
groups:
- name: node
rules:
- alert: HighCpuUsage
expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
- alert: HighMemoryUsage
expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 90
for: 5m
labels:
severity: critical
- alert: DiskAlmostFull
expr: (1 - node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}) * 100 > 85
for: 10m
labels:
severity: warning
- alert: HighLoadAverage
expr: node_load5 > on (instance) count by (instance) (node_cpu_seconds_total{mode="idle"})
for: 10m
labels:
severity: warning
تعتمد قاعدة الذاكرة على MemAvailable وليس على الذاكرة الحرة، للأسباب الموضحة أعلاه. وتقارن قاعدة الحمل node_load5 بعدد الأنوية، المحسوب من سلاسل المعالج لكل instance. تحقق من صحة الملف باستخدام promtool check rules /etc/prometheus/rules/node.yml قبل إعادة تحميل Prometheus، ثم اترك لـ Alertmanager مهمة إرسال الإشعارات (البريد الإلكتروني، Slack…).
سكربتات مراقبة مخصصة
على خادم صغير منعزل دون منظومة Prometheus، قد يكفي سكربت يشغّله cron لإطلاق الإنذار:
#!/bin/bash
# check_resources.sh
CPU=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}')
MEM=$(free -m | awk 'NR==2{printf "%.1f", $3*100/$2}')
DISK=$(df -h / | awk 'NR==2{print $5}' | tr -d '%')
echo "CPU: ${CPU}% | MEM: ${MEM}% | DISK: ${DISK}%"
if (( $(echo "$CPU > 80" | bc -l) )); then
echo "ALERT: high CPU!" | mail -s "Server alert" admin@example.com
fi
لهذا السكربت بعض الحدود التي يجب معرفتها. قيمة المعالج المستخرجة من top تمثل وقت المستخدم فقط (us)، ويعتمد تنسيق السطر على الإصدار والإعدادات المحلية (locale). والذاكرة المحسوبة هي الذاكرة «المستخدمة» التي تستثني الـ cache. وأخيراً، يفترض الأمر mail وجود وكيل بريد مُعَدّ على الجهاز. يُجدول في crontab:
*/5 * * * * /usr/local/bin/check_resources.sh >> /var/log/check_resources.log 2>&1
أخطاء شائعة
- كثرة التنبيهات: التنبيه الذي ينطلق كل يوم دون أي إجراء سرعان ما يُتجاهل. يجب أن يقابل كل تنبيه إجراءً ملموساً.
- المراقبة من الداخل فقط: قد يمتلك الخادم مقاييس ممتازة ومع ذلك يكون غير قابل للوصول. أضف مسباراً خارجياً على عناوين URL العامة.
- نسيان الـ inodes: قد تنفد الـ inodes من القرص رغم وجود مساحة حرة، عادةً بسبب ملايين الملفات الصغيرة للجلسات أو الـ cache. تحقق باستخدام
df -i. - تجاهل الاتجاه: قرص عند 70% يزداد بنسبة 5% يومياً أكثر إلحاحاً من قرص مستقر عند 88%. تتيح دالة
predict_linearفي Prometheus التنبيه بناءً على تاريخ الامتلاء المتوقع.
باختصار
للتشخيص، اتبع منهجية (الاستخدام، التشبّع، الأخطاء) واقرأ الذاكرة المتاحة والحمل بشكل صحيح. وعلى المدى الطويل، ثبّت Node Exporter كخدمة، واجمع مقاييسه بـ Prometheus، وحدّد عدداً قليلاً من التنبيهات بعتبات ومدد واقعية. أفضل مراقبة ليست تلك التي تقيس كل شيء، بل تلك التي تنبّهك في الوقت المناسب، وفقط عندما يكون ذلك مفيداً.