ارسال لاگ Docker container ها به ELK از طریق درایور های لاگ

جهت اطلاع:

بدون استفاده از لاگ درایور های داکر هم می توانید لاگ سرویس های درون کانتینر را به سیستم های مدیریت لاگ مثل ELK یا Graylog ارسال کنید برای این کار می توانید پوشه ی لاگ داخل کانتینر را با استفاده از volumes روی هاست map کنید (یا از لاگ capture شده توسط لاگ درایور پیشفرض داکر استفاده کنید) و فایل ها را با یک ارسال کننده مانند Filebeat یا Fluentd به ELK (یا Graylog) ارسال کنید.

اما هدف این مطلب استفاده از درایور های داکر برای این کار است.

گام اول:

در صورتی که کامند "docker logs" همان لاگی که مد نظر شما هست رو نمایش میدهد از این گام عبور کنید و به گام دوم برید.

قبل از هر چیز باید بدانیم که داکر به صورت پیش فرض standard output یا همان stdout و همچنین stderr مربوط به پروسسی که دارای pid ۱ داخل کانتینر هست را به عنوان لاگ جمع آوری می کند و از طریق کامند زیر نمایش میدهد.

docker logs -f <container-name>

در صورتی که از image های معتبر از پیش ساخته شده استفاده می کنید معمولا این مورد از قبل در نظر گرفته شده و نیازی به تغییر نیست اما اگر خودتان در حال ساختن docker image مورد نیازتان هستید میبایست لاگ مربوط به سرویس را از روش های مختلف به stdout ارسال کنید

یکی از این روش ها استفاده از symbolic link هست به طور مثال برای سرویس رایج nginx می توانید از طریق کامند زیر برای ارسال لاگ به stdout استفاده کنید (مشاهده ی نمونه ی Dockerfile) :

ln -sf /dev/stdout /var/log/nginx/access.log

روش بعدی ارسال مستقیم لاگ به آدرس stdout است به طور مثال برای همان سرویس nginx می توانید داخل فایل کانفیگ nginx از عبارت زیر استفاده کنید:

...
access_log /dev/stdout;
...

در صورتی که سرویس مورد نظر شما به هر دلیل دارای PID به غیر از ۱ باشد (معمولا نباید اینطور باشد) میبایست TTY را در هنگام اجرای کانتینر فعال کنید و لاگ را به مسیر زیر ارسال کنید

/dev/console

گام دوم:

داکر دارای چندین Log Driver است که می توانید با استفاده از آنها لاگ های جمع آوری شده توسط داکر را به ELK ( یا Graylog) ارسال کنید.

توجه داشته باشید که بعد از تغییر لاگ درایور پیش فرض داکر به یکی از موارد زیر کامند "docker logs" یا "docker-compose logs" دیگر لاگ های جمع آوری شده را نمایش نخواهد داد.


GELF

یکی از درایور هایی که می خواهیم بررسی کنیم GELF نام دارد که مخفف Graylog Extended Log Format هست. GELF یک استاندارد برای ارسال لاگ است که توسط log collector های مختلف مانند Logstash یا Fluentd و همچنین Greylog ساپورت می شود. پس با توجه به اینکه Input مربوط به GELF برای Logstash موجود هست می توانید با استفاده از این درایور لاگ ها را به ELK ارسال کنید.

برای استفاده از لاگ درایور GELF می توانید عبارت های "log-driver" و "log-opts" را داخل فایل :

/etc/docker/daemon.json

به صورت زیر تغییر بدهید (یا اضافه کنید):

...

"log-driver": "gelf",
"log-opts": {
  "gelf-address": "udp://logstash.test-server.com:12201"
    },

...

مشخص هست که عبارت gelf-address آدرس سرور logstash است. مانند مثال بالا protocol و port حتما باید در آدرس قید شود. در حال حاظر GELF روی داکر فقط از UDP ساپورت میکند.

در صورت تغییر فایل daemon.json این درایور برای تمامی کانتینر ها استفاده خواهد شد در صورتی که مایل هستید برای کانتینر های مختلف از درایور های مختلف استفاده کنید میتوانید از آپشن های موجود در Docker CLI یا فایل Docker Compose استفاده کنید.

یکی دیگر از "log-opts" هایی که امکان استفاده در این درایور را دارد tag هست استفاده از این آپشن اجباری نیست اما برای دسته بندی لاگ ها و امکان جداسازی لاگ در logstash می توانید از tag استفاده کنید.

و نهایتا کانفیگ logstash به صورتی که لاگ های ارسال شده توسط داکر را دریافت کند.

نمونه ی کانفیگ GELF Input برای Logstash:

input {
    gelf {
        port => 12201
        type => gelf
    }
}


معایب:

  • آدرسی که در قسمت log-opts برای logstash وارد کردید فقط هنگام start کانتینر resolve خواهد شد و بعد از start شدن DNS تاثیری نخواهد داشت بنا بر این به هر دلیل اگر نیاز باشد ip ی logstash تغییر کند مجبور خواهید شد کانتینر را restart کنید. همچنین این درایور در حال حاظر امکان ایجاد failover برای logstash را ندارد.
  • فقط با UDP Protocol کار میکند.


Fluentd

اگر با Fluentd آشنایی ندارید باید بگویم سرویسی شبیه به Logstash هست که امکان ارسال , دریافت , فیلتر کردن , اضافه یا کم کردن فیلد های لاگ , اضافه کردن tag و بسیاری قابلیت های دیگر را دارد.

یکی دیگر از درایور های لاگ Fluentd هست که برای استفاده از این درایور میبایست سرویس Fluentd را نصب کنید (می تواند به صورت کانتینر باشد).

برای استفاده از لاگ درایور Fluentd میتونید عبارت های "log-driver" و "log-opts" رو داخل فایل :

/etc/docker/daemon.json

به صورت زیر تغییر بدید (یا اضافه کنید):

...

"log-driver": "fluentd",
"log-opts": {
  "fluentd-address": "fluentd.test-server.com:12201"
    },

...

مشخص است عبارت fluentd-address همان آدرس سرور fluentd میباشد که به صورت پیشفرض localhost است. Protocol نیز به صورت پیشفرض TCP است.

همچنین کانفیگ Fluentd برای دریافت لاگ از داکر(فایل td-agent.conf) :

<source>
   @type forward
 </source>


در صورت استفاده از درایور Fluentd امکانات و گزینه های زیادی پیش روی شما خواهد بود و می توانید از تمامی Plugin های خروجی Fluentd بسته به نیاز استفاده کنید.

به طور مثال می توانید Fluentd را جایگزین logstash کنید و کار فیلترینگ (grok و ...) , aggregation و ارسال به Elasticsearch را به Fluentd بسپارید.

یا روی هر داکر هاست یک کانتینر Fluentd داشته باشید که کار tag زدن , queueing و buffering و همچنین ارسال به logstash (یا یک Fluentd دیگر) را انجام دهد.

برای اطلاع از تمامی توانایی ها و امکانات Fluentd به مستندات سرویس Fluentd مراجعه کنید.


همچنین برای ارسال لاگ کانتینر ها به ELK یا Greylog گزینه های دیگری نیز مانند درایور syslog دارید. لیست کامل لاگ درایور های داکر را می توانید اینجا مشاهده کنید.