Prometheus وGrafana

المُصدِّرون واكتشاف الخدمات

18 دقيقة الدرس 5 من 32

المُصدِّرون واكتشاف الخدمات

لا تقوم Prometheus بقياس أنظمتك مباشرةً، بل تعتمد على المُصدِّرين (Exporters) — وهي خوادم HTTP صغيرة تُحوِّل مقاييس نظام خارجي إلى صيغة عرض Prometheus. ومع اكتشاف الخدمات (Service Discovery)، تستطيع Prometheus العثور على كل مُصدِّر في أسطول ديناميكي وجمع بياناته دون الحاجة إلى كتابة عنوان IP واحد بشكل يدوي.

node_exporter: أساس مقاييس المضيف

يعدّ node_exporter المُصدِّر القياسي لمقاييس مضيفي Linux/Unix. يعرض أكثر من 1,000 مقياس تغطي وحدة المعالجة المركزية والذاكرة وإدخال/إخراج القرص ونظام الملفات وواجهات الشبكة وانحراف NTP وحالة وحدات systemd، وذلك على المنفذ 9100 عبر نقطة النهاية /metrics.

# نشر node_exporter كخدمة systemd (الإصدار v1.8.x، 2025) wget https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz tar xvf node_exporter-1.8.2.linux-amd64.tar.gz install -m 0755 node_exporter-1.8.2.linux-amd64/node_exporter /usr/local/bin/ cat > /etc/systemd/system/node_exporter.service <<'UNIT' [Unit] Description=Prometheus Node Exporter After=network.target [Service] User=node_exporter ExecStart=/usr/local/bin/node_exporter \ --collector.filesystem.mount-points-exclude='^/(dev|proc|sys|var/lib/docker/.+)($|/)' \ --collector.systemd \ --collector.processes \ --web.listen-address=:9100 Restart=on-failure [Install] WantedBy=multi-user.target UNIT useradd -rs /bin/false node_exporter systemctl daemon-reload && systemctl enable --now node_exporter # اختبار سريع curl -s http://localhost:9100/metrics | grep '^node_cpu_seconds_total' | head -3
احرص دائمًا على استبعاد /proc و/sys ووحدات تركيب Docker Overlay من مُجمِّع نظام الملفات. بدون هذا العلم، يُنتج node_exporter مئات المقاييس الزائفة لطبقات الحاويات — مما يُسبب مشاكل في cardinality داخل Prometheus.

نظام المُصدِّرين

يتجاوز النظام البيئي للمُصدِّرين الرسمية والمجتمعية node_exporter ليشمل كل بنية تحتية تقريبًا ستواجهها على نطاق واسع:

  • blackbox_exporter — يختبر HTTP وHTTPS وDNS وTCP وICMP من الخارج. ضروري للمراقبة الاصطناعية وتنبيهات انتهاء صلاحية SSL.
  • mysqld_exporter / postgres_exporter — مقاييس قاعدة البيانات: زمن استجابة الاستعلامات وتشبع مجموعة الاتصالات وتأخر النسخ المتماثلة والاستعلامات البطيئة.
  • redis_exporter — إصابات وأخطاء keyspace ونسبة تجزؤ الذاكرة والعملاء المتصلين وإزاحة النسخ المتماثلة.
  • kube-state-metrics — حالة كائنات Kubernetes (النسخ المطلوبة مقابل الجاهزة في Deployment، وإعادة تشغيل Pod، وحالة ربط PVC). يختلف عن cAdvisor الذي يقيس استهلاك الموارد.
  • process-exporter — وحدة المعالجة المركزية والذاكرة لكل عملية عندما تحتاج لتتبع خوادم بعينها دون الحاجة لتفاصيل المضيف الكاملة.
  • kafka_exporter / rabbitmq_exporter — عمق قائمة الانتظار وتأخر المستهلك وتوزيع قائد القسم.
يمكن لأي تطبيق أن يصبح مُصدِّرًا خاصًا به من خلال عرض نقطة نهاية /metrics باستخدام مكتبة عميل Prometheus (Go أو Java أو Python أو Ruby أو Rust). في بيئات الإنتاج، استخدم نمط push-gateway فقط للمهام الدفعية قصيرة العمر؛ أما الخدمات طويلة الأمد فيجب أن تعرض /metrics مباشرةً.

kubernetes_sd: اكتشاف الخدمات في الأنظمة الديناميكية

في Kubernetes، تكون حياة الـ pods قصيرة — تتغير عناوين IP مع كل إصدار. لا تستطيع scrape_configs الثابتة مواكبة هذا التغيير. يحل kubernetes_sd_configs هذه المشكلة بالاستعلام المستمر عن Kubernetes API وعرض الأهداف مجمَّعةً حسب الدور: node أو pod أو service أو endpoints أو ingress.

Prometheus Kubernetes Service Discovery and Relabeling Flow Kubernetes API Server kubernetes_sd role: endpoints role: pod role: node Relabeling keep / drop replace labels set __address__ Prometheus Scrape Loop pod A:8080 pod B:8080 filtered target set
تستخدم Prometheus الـ kubernetes_sd لاكتشاف الأهداف من Kubernetes API، ثم تعيد Relabeling تصفية مجموعة الأهداف وإعادة تشكيلها قبل عملية الجمع.
# prometheus.yml — جمع بيانات Pods التي تحمل الـ annotation # prometheus.io/scrape: "true" scrape_configs: - job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: pod relabel_configs: # تجاهل pods غير المشتركة - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] action: keep regex: "true" # إعادة كتابة العنوان باستخدام IP الـ pod والمنفذ المُحدَّد - source_labels: [__meta_kubernetes_pod_ip, __meta_kubernetes_pod_annotation_prometheus_io_port] action: replace regex: (.+);(\d+) replacement: $1:$2 target_label: __address__ # إضافة namespace واسم الـ pod لكل سلسلة بيانات - source_labels: [__meta_kubernetes_namespace] target_label: namespace - source_labels: [__meta_kubernetes_pod_name] target_label: pod - source_labels: [__meta_kubernetes_pod_label_app] target_label: app

Relabeling: تشكيل مجموعة الأهداف

يُعدّ Relabeling من أقوى الميزات — وأكثرها سوء فهمًا — في إعداد Prometheus. يعمل في مرحلتين: relabel_configs (قبل عملية الجمع، يُحدِّد ما إذا كان يجب جمع البيانات وكيفية ذلك) وmetric_relabel_configs (بعد عملية الجمع، على كل سلسلة زمنية مُستردَّة).

يحمل كل هدف مجموعة من التسميات الوصفية ذات البادئة __meta_ التي تملأها آلية SD. لا تُخزَّن هذه التسميات أبدًا في TSDB — بل توجد فقط أثناء Relabeling لتمكينك من بناء التسميات الحقيقية.

  • keep — يُبقي فقط الأهداف التي يتطابق تسمية مصدرها مع التعبير النمطي؛ يسقط الباقي.
  • drop — عكس keep. مفيد لتعطيل مُصدِّرات مزعجة في مساحات أسماء محددة.
  • replace — يستخرج قيمة (اختياريًا بمجموعة التقاط) ويكتبها في تسمية الهدف.
  • labelmap — يُوزِّع التسميات الوصفية المتطابقة في تسميات حقيقية. الاستخدام الشائع: الترقية المنتقاة للتسميات من __meta_kubernetes_pod_label_*.
  • labeldrop / labelkeep — يحذف أو يُبقي أسماء تسميات محددة فقط في السلاسل النهائية.
# مثال metric_relabel_configs: إسقاط مقاييس kubelet عالية الـ cardinality # التي تُجمَع لكنها لا تُستعلَم أبدًا، لتقليل تكلفة استيعاب TSDB - job_name: 'kubelet' kubernetes_sd_configs: - role: node scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token relabel_configs: - action: labelmap regex: __meta_kubernetes_node_label_(.+) metric_relabel_configs: # إسقاط مقاييس الموارد لكل حاوية — استخدم kube-state-metrics بدلاً منها - source_labels: [__name__] regex: 'container_(cpu_cfs_throttled_seconds_total|network_tcp_usage_total)' action: drop # تطبيع تسمية id لتجنب انفجار قيم التسميات - source_labels: [id] regex: '/kubepods/.+/pod.+/(.{12}).+' replacement: '$1' target_label: container_id
لا تستخدم labelmap لترقية جميع تسميات pod الخاصة بـ Kubernetes (__meta_kubernetes_pod_label_.*) إلى تسميات Prometheus دون مراجعتها أولاً. إذا أضاف مطوِّر تسمية مثل git-commit-sha أو تسمية تحمل UUID، فإن كل قيمة فريدة ستصبح سلسلة جديدة. هذا هو السبب الرئيسي لانفجارات الـ cardinality في Prometheus على نطاق واسع. استخدم دائمًا قائمة مسموح بها: regex: __meta_kubernetes_pod_label_(app|version|env|team).

الاتحاد وأنماط التسلسل الهرمي

على نطاق الأسطول، لا يستطيع خادم Prometheus واحد جمع بيانات 10,000 عقدة. تستخدم البنية القياسية الاتحاد الهرمي: تجمع خوادم Prometheus لكل مركز بيانات أو كل مجموعة بيانات المُصدِّرين المحليين؛ ثم يجمع خادم Prometheus عالمي من المستوى الأعلى قواعد التسجيل المجمَّعة مسبقًا فقط. تدعم نقطة النهاية /federate هذا النمط عبر مُعامِل match[].

في بيئات Kubernetes، أفضل ممارسة على نطاق المؤسسات حاليًا هي Prometheus Operator + kube-prometheus-stack (عبر Helm). يأتي مزوَّدًا بـ ServiceMonitor CRDs مُسبقة البناء وتنبيهات افتراضية ونسخة مدمجة من Grafana. تعرِّف أهداف الجمع بشكل تعريفي كـ Kubernetes objects بدلاً من تعديل prometheus.yml مباشرةً — يُراقب Operator موارد ServiceMonitor/PodMonitor ويُعيد توليد الإعداد تلقائيًا.

أنماط الفشل في بيئات الإنتاج

فهم ما يتعطل في البيئات الحقيقية لا يقل أهمية عن معرفة كيفية الإعداد:

  • تعارض scrape_timeout مع scrape_interval — إذا استغرق هدف وقتًا أطول من scrape_timeout للاستجابة، تُصنِّفه Prometheus كـ up=0 ولا تُصدر أي مقاييس لتلك الدورة. المهلة الافتراضية (10 ثوانٍ) قصيرة في الغالب لمُصدِّرات MySQL أو JVM تحت ضغط GC. اضبطها لكل job.
  • تقادم ذاكرة التخزين المؤقت لـ SD — يستطلع kubernetes_sd الـ API كل refresh_interval (الافتراضي 5 دقائق). قد يُجمَع pod مات وأُعيد تشغيله خلال تلك النافذة من عنوان قديم. استخدم دور endpoints بدلاً من pod عندما تحتاج لاتساق أقل من دقيقة.
  • صلاحيات RBAC مفقودة — تحتاج Prometheus إلى ClusterRole يمنح get/list/watch على العقد والـ pods والخدمات ونقاط النهاية، مع ClusterRoleBinding لحساب الخدمة الخاص بها. الصلاحيات المفقودة تُنتج أخطاء 403 صامتة في السجلات؛ تعيد scrape_config صفر أهداف بصمت.
  • منفذ node_exporter محجوب — قواعد Security Group أو NetworkPolicy التي تحجب المنفذ 9100 سبب شائع بعد تصليب الكتلة. الأعراض: up{job="node"} == 0.