راهاندازی OpenTelemetry Collector روی سرور مجازی و اختصاصی: مشاهدهپذیری متمرکز معیارها و لاگهای Nginx و MySQL

اگر برای متریک سیستم یک Exporter نصب کردهاید، برای لاگ Nginx یک Agent دیگر و برای MySQL باز هم ابزار سومی، احتمال اینکه یکی از اینها بعد از ریاستارت سرور بالا نیاید زیاد است. OpenTelemetry Collector همین سه کار را با یک فایل تنظیمات و یک سرویس سیستمی انجام میدهد. در این مطلب نصب آن را روی سرور مجازی یا اختصاصی لینوکسی، از صفر تا ارسال داده به Grafana، قدم به قدم میبینیم.
OpenTelemetry Collector چیست
OpenTelemetry Collector یک برنامه مستقل است که داده را از چند منبع میگیرد (Receiver)، روی آن پردازش ساده انجام میدهد (Processor) و به یک یا چند مقصد میفرستد (Exporter). این سه بخش در یک فایل YAML به هم وصل میشوند و Pipeline نهایی را میسازند. نسخهای که در این مطلب استفاده میشود otelcol-contrib نام دارد؛ نسخه Contrib، برخلاف نسخه Core، Receiverهای آماده برای Nginx و MySQL را هم دارد.
چیزی که این ابزار را برای یک سرور تنها بهصرفه میکند این است که بهجای سه برنامه جدا (node_exporter، یک Agent لاگ، یک Exporter برای دیتابیس) یک پردازه واحد همه را جمع میکند. مصرف رم کمتر است و فقط یک سرویس باید سالم بماند.
پیشنیازها
برای ادامه این مطلب به اینها نیاز دارید:
- یک سرور مجازی یا اختصاصی لینوکسی با Ubuntu 22.04 یا 24.04 (دستورها روی Debian هم تقریبا همین است)
- دسترسی root یا sudo
- Nginx و MySQL از قبل روی همان سرور یا سرور دیگری نصب و در حال اجرا
- یک مقصد برای دادهها: یک حساب Grafana Cloud (پلن رایگان آن کافی است) یا یک Grafana خودمیزبان کنار Prometheus و Loki
اگر دسترسی SSH سرور را هنوز امن نکردهاید، قبل از باز کردن پورتهای جدید برای Receiverها بهتر است این مرحله را هم انجام بدهید.
اگر هنوز سرور را نساختهاید و بین VPS و سرور اختصاصی ماندهاید، قاعده ساده است: برای یک سرویس یا چند سایت کوچک، سرور مجازی کافی است. وقتی حجم لاگ یا تعداد کوئری MySQL زیاد میشود و خودِ Collector هم منبع قابلتوجهی از CPU و دیسک میخواهد، به منابع اختصاصی یک سرور اختصاصی نیاز پیدا میکنید.
نصب روی سرور
سادهترین راه، دانلود پکیج .deb از صفحه Releases پروژه open-telemetry/opentelemetry-collector-releases در گیتهاب است. نسخه دقیق را از همان صفحه بگیرید، چون نسخهها مدام بهروز میشوند:
VERSION="0.1XX.0" # نسخه فعلی را از صفحه Releases بگیرید
curl -LO "https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v${VERSION}/otelcol-contrib_${VERSION}_linux_amd64.deb"
sudo dpkg -i otelcol-contrib_${VERSION}_linux_amd64.deb
نصب پکیج یک سرویس systemd بهنام otelcol-contrib میسازد و یک کاربر غیر-root به همین نام میدهد که سرویس با آن اجرا میشود. فایل تنظیمات پیشفرض در /etc/otelcol-contrib/config.yaml قرار میگیرد؛ همین فایل را در مرحله بعد عوض میکنیم.
پیکربندی: متریک سیستم، Nginx و MySQL
فایل config.yaml را با محتوای زیر بازنویسی کنید. این نمونه سه چیز را جمع میکند: متریک سیستم (CPU، رم، دیسک)، متریک و لاگ Nginx، متریک و لاگ MySQL.
receivers:
hostmetrics:
collection_interval: 30s
scrapers:
cpu:
memory:
disk:
filesystem:
load:
network:
nginx:
endpoint: "http://localhost/nginx_status"
collection_interval: 30s
mysql:
endpoint: localhost:3306
username: otel_monitor
password: ${env:MYSQL_MONITOR_PASSWORD}
collection_interval: 30s
filelog/nginx_access:
include: [/var/log/nginx/access.log]
start_at: end
filelog/nginx_error:
include: [/var/log/nginx/error.log]
start_at: end
filelog/mysql_error:
include: [/var/log/mysql/error.log]
start_at: end
processors:
batch:
resourcedetection/system:
detectors:
exporters:
otlphttp/grafana:
endpoint: "https://otlp-gateway-<region>.grafana.net/otlp"
headers:
Authorization: "Basic ${env:GRAFANA_OTLP_TOKEN}"
service:
pipelines:
metrics:
receivers: [hostmetrics, nginx, mysql]
processors: [resourcedetection/system, batch]
exporters: [otlphttp/grafana]
logs:
receivers: [filelog/nginx_access, filelog/nginx_error, filelog/mysql_error]
processors:
exporters: [otlphttp/grafana]

چند نکته درباره همین فایل:
Receiver nginx به ماژول stub_status خودِ Nginx نیاز دارد. اگر فعال نیست، داخل یک بلوک server در تنظیمات Nginx این را اضافه کنید و سرویس را reload کنید:
location /nginx_status {
stub_status on;
allow 127.0.0.1;
deny all;
}
Receiver mysql با یک کاربر جداگانه با دسترسی محدود کار میکند، نه کاربر root دیتابیس. این کاربر را در MySQL بسازید:
CREATE USER 'otel_monitor'@'localhost' IDENTIFIED BY 'یک-رمز-قوی';
GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'otel_monitor'@'localhost';
رمز عبور را بهجای نوشتن مستقیم در config.yaml، در یک فایل environment جدا (مثلا /etc/otelcol-contrib/otelcol-contrib.conf) بهصورت MYSQL_MONITOR_PASSWORD=... بگذارید؛ همین کار را برای توکن Grafana هم بکنید. این فایل را سرویس systemd بهصورت خودکار میخوانَد.
سرویس systemd پایدار
بعد از تغییر فایل تنظیمات، سرویس را دوباره بار کنید:
sudo systemctl daemon-reload
sudo systemctl enable --now otelcol-contrib
sudo systemctl status otelcol-contrib
برای اینکه سرویس بعد از یک خطای موقت (مثلا دیتابیس برای چند ثانیه در دسترس نبود) خودش بالا بیاید، این دو سطر را به بخش [Service] فایل override اضافه کنید:
sudo systemctl edit otelcol-contrib
[Service]
Restart=on-failure
RestartSec=5
این تنظیم همان چیزی است که سرویس را «پایدار» میکند: اگر Collector به هر دلیلی crash کند، systemd خودش پنج ثانیه بعد دوباره آن را اجرا میکند، بدون اینکه کسی باید دستی وارد سرور شود. اگر برای زمانبندی کارهای دیگر روی همین سرور هنوز از cron استفاده میکنید، جایگزینی آن با Systemd Timer همین مزیت ریاستارت خودکار و لاگ یکپارچه را میدهد.
تست و رفع اشکال
برای دیدن اینکه Collector در حال کار است، لاگ خودش را ببینید:
journalctl -u otelcol-contrib -f
اگر پیام خطای اتصال به Grafana یا MySQL میبینید، معمولا یکی از این سه چیز است: توکن یا رمز اشتباه در فایل environment، دسترسی شبکه بسته (فایروال سرور یا امنیتی پنل VPS پورت خروجی ۴۴۳ را بسته)، یا نام endpoint اشتباه کپی شده از پنل Grafana. بعد از رفع هر کدام، چند دقیقه صبر کنید و در Grafana Explore دنبال متریک system_cpu_utilization یا یک خط لاگ تازه از Nginx بگردید؛ اگر دیدید، Pipeline کامل است.
یک Collector واحد در برابر چند ابزار جدا
قبل از OpenTelemetry، راه رایج همین مانیتورینگ جمع کردن چند Exporter کنار هم بود. جدول زیر تفاوت عملی را نشان میدهد:
| چند ابزار جدا (node_exporter + promtail + mysqld_exporter) | یک OpenTelemetry Collector | |
|---|---|---|
| تعداد سرویس برای نگهداری | سه یا چهار سرویس جدا | یک سرویس |
| فایل تنظیمات | چند فایل پخششده | یک فایل YAML |
| مقصد داده | معمولا فقط Prometheus یا فقط Loki | هر دو، با همان Collector |
| تغییر مقصد در آینده (مثلا رفتن از self-hosted به Grafana Cloud) | تغییر در چند جا | فقط تغییر بخش exporters |
| مصرف رم روی یک VPS کوچک | هر Exporter رم خودش را میگیرد، جمعا بیشتر | یک پردازه، جمعا کمتر |
برای یک سرور تنها با چند سرویس، تفاوت رم و تعداد فایل تنظیمات محسوس است. برای زیرساخت بزرگتر با دهها سرور، همین Collector هم میتواند بهصورت متمرکز روی یک Gateway جمعکننده اجرا شود؛ آن یک موضوع جدا است و فعلا نیازی به آن نیست.
داده را کجا نگه دارید
اگر Grafana Cloud را انتخاب کردهاید، چیزی برای نصب کردن روی سرور خودتان نیست؛ فقط endpoint و توکن از پنل آنها را در otlphttp/grafana میگذارید. اگر ترجیح میدهید همه چیز روی زیرساخت خودتان بماند، یک Prometheus و یک Loki کنار Grafana روی همان سرور یا سرور دومی اجرا میشود و در بخش exporters بهجای otlphttp از prometheusremotewrite و loki استفاده میکنید. این گزینه دوم به منابع بیشتری نیاز دارد، چون سه سرویس اضافه در حال اجرا است.
برای هر دو حالت، سرعت دیسک و پهنای باند شبکه سرور روی تاخیر ارسال داده اثر دارد؛ وقتی حجم لاگ Nginx در ساعتهای پرترافیک بالا میرود، یک سرور با دیسک NVMe و شبکه پایدار فرق را در تاخیر داشبورد نشان میدهد. سرور مجازی ابری آریانت روی زیرساخت OVH آلمان همین مشخصات را دارد و برای این نوع کار، از ساخت سرور تا نصب Collector، چند دقیقه بیشتر طول نمیکشد. جزئیات پلنها را در صفحه سرور مجازی ابری آریانت ببینید.
سؤالات متداول
آیا OpenTelemetry Collector فقط برای Nginx و MySQL کار میکند؟ نه، این دو فقط نمونه این مطلب بودند. Receiverهای آماده برای PostgreSQL، Redis، Docker و چند ده سرویس دیگر هم در نسخه Contrib وجود دارد؛ ساختار فایل تنظیمات همین است، فقط نام Receiver عوض میشود.
چرا باید از Grafana Cloud بهجای self-hosted استفاده کنم؟ اگر نمیخواهید Prometheus و Loki را خودتان نگه دارید و آپدیت کنید، پلن رایگان Grafana Cloud برای شروع کافی است. اگر داده باید روی زیرساخت خودتان بماند یا حجم داده بالا است، self-hosted ارزانتر تمام میشود.
Collector چقدر رم و CPU روی سرور میگیرد؟
برای یک سرور با چند سایت و یک دیتابیس، معمولا کمتر از ۱۰۰ مگابایت رم کافی است. اگر لاگ حجیم است یا تعداد Receiver زیاد میشود، همین عدد بالاتر میرود؛ با journalctl و دستور top مصرف واقعی را چک کنید.
اگر سرور ریاستارت شود، Collector دوباره بالا میآید؟
بله، بهشرطی که با systemctl enable فعال شده باشد. دستور enable --now که در این مطلب آمد همین کار را میکند؛ بعد از هر ریاستارت سرور، خودش بدون دخالت دستی اجرا میشود.




