Translate

четвер, 29 січня 2015 р.

Centralize Loggining with Kibana/Logstash/Elasticsearch

Я раніше писав про установку та налаштування серверу централізованого збору логів в основі якого лежав Rsyslog з бекендом LogAnalyzer, та сервер із Syslog-ng. Основним недоліком LogAnalyzer є відсталість його інтерфейсу. Тому якщо цей недолік для вас є основним - раджу спробувати Kibana/Logstash зі зберіганням данних в Elasticsearch.

Kibana/Logstash не є вузькоспеціалізованим продуктом, що призначений лише для збирання логів програм. За його допомогою можна також візуалізувати власні дані за допомогою різноманітних графіків та діаграм, наприклад, статистику використання браузерів чи найбільш популярні сторінки власного сайту та ін.

Спочатку розберемось щодо складових частин серверу збору логів та їхнього призначення.


Logstash читає логи або отримує їх від клієнтів за допомогою Logstash-forwarder, розбирає їх по полям відповідними драйверами та записує їх до Elasticsearch, потім, за допомогою Kibana, можна переглядати логи і будувати різноманітні діаграми чи графіки.

Дистрибутив, що я буду використовувати - Ubuntu 14.04. Навіть для тестів краще брати машину як мінімум із 2 ГБ RAM та 2 CPU.

Почнемо з установки серверної частини. Logstash та Elasticsearch потребують Java 7 для роботи, для чого підійде як Oracle Java 7, так і OpenJDK.

# add-apt-repository -y ppa:webupd8team/java
# apt-get update
# apt-get -y install oracle-java7-installer

Для production середовища, можливо, краще скористатись джавою що надає Oracle на власному сайті та зібрати власний пакет:

# apt-get install java-package
# wget http://download.oracle.com/otn-pub/java/jdk/7u75-b13/server-jre-7u75-linux-x64.tar.gz?AuthParam=1423217016_530b51c9d6c77e8237c6a2f2288d7657 -O jre-7u75-linux-x64.tar.gz
# make-jpkg jre-7u75-linux-x64.tar.gz
# dpkg -i oracle-j2re1.7_1.7.0+update75_amd64.deb
# update-alternatives --auto java

Встановлюємо Elasticsearch, для чого додамо репозиторій із останньою стабільною версією:

# wget -qO - https://packages.elasticsearch.org/GPG-KEY-elasticsearch | sudo apt-key add -
# sudo add-apt-repository "deb http://packages.elasticsearch.org/elasticsearch/1.4/debian stable main"

# apt-get update && sudo apt-get install elasticsearch

Додаємо Elasticsearch в автозавантаження:

# update-rc.d elasticsearch defaults 95 10

Додаємо рядок в конфіг, щоб заборонити динамічні скрипти:

# vim /etc/elasticsearch/elasticsearch.yml
...
script.disable_dynamic: true

Та відкриваємо порт лише локально:

# vim /etc/elasticsearch/elasticsearch.yml
...
network.host: localhost

Запускаємо Elasticsearch та перевіряємо його роботу:

# service elasticsearch start

# curl -XGET 'localhost:9200/_stats'

На останню команду має бути виведена певна статистика.

Установлюємо веб-інтерфейс до Elasticsearch - Kibana. Для чого скачуємо останню стабільну версію з сайту http://www.elasticsearch.org/overview/kibana/installation/:

# wget https://download.elasticsearch.org/kibana/kibana/kibana-3.1.2.tar.gz

Розпаковуємо завантажений архів та переміщаємо його:

# tar xvf kibana-3.1.2.tar.gz
# mkdir -p /var/www/
# mv kibana-3.1.2 /var/www/

Чудово! Тепер редагуємо конфігураційний файл Kibana:

# vim /var/www/kibana-3.1.2/config.js
...
elasticsearch: "http://"+window.location.hostname+":80",
...

80 - це порт, на якому буде доступна Kibana.

У якості веб-сервера будемо використовувати Nginx.

# apt-get install nginx

Створюємо віртуальний хост. Необхідно лише підправити за необхідністю server_name та root:

# vim /etc/nginx/sites-available/kibana-3.1.2.conf

#
# Nginx proxy for Elasticsearch + Kibana
#
# In this setup, we are password protecting the saving of dashboards. You may
# wish to extend the password protection to all paths.
#
# Even though these paths are being called as the result of an ajax request, the
# browser will prompt for a username/password on the first request
#
# If you use this, you'll want to point config.js at http://FQDN:80/ instead of
# http://FQDN:9200
#

server {
  listen                *:80 ;

  server_name           kibana.myhost.org;
  access_log            /var/log/nginx/kibana.myhost.org.access.log;

  location / {
    root  /var/www/kibana-3.1.2;
    index  index.html  index.htm;
  }

  location ~ ^/_aliases$ {
    proxy_pass http://127.0.0.1:9200;
    proxy_read_timeout 90;
  }
  location ~ ^/.*/_aliases$ {
    proxy_pass http://127.0.0.1:9200;
    proxy_read_timeout 90;
  }
  location ~ ^/_nodes$ {
    proxy_pass http://127.0.0.1:9200;
    proxy_read_timeout 90;
  }
  location ~ ^/.*/_search$ {
    proxy_pass http://127.0.0.1:9200;
    proxy_read_timeout 90;
  }
  location ~ ^/.*/_mapping {
    proxy_pass http://127.0.0.1:9200;
    proxy_read_timeout 90;
  }

  # Password protected end points
  location ~ ^/kibana-int/dashboard/.*$ {
    proxy_pass http://127.0.0.1:9200;
    proxy_read_timeout 90;
    limit_except GET {
      proxy_pass http://127.0.0.1:9200;
      auth_basic "Restricted";
      auth_basic_user_file /etc/nginx/conf.d/kibana.myhost.org.htpasswd;
    }
  }
  location ~ ^/kibana-int/temp.*$ {
    proxy_pass http://127.0.0.1:9200;
    proxy_read_timeout 90;
    limit_except GET {
      proxy_pass http://127.0.0.1:9200;
      auth_basic "Restricted";
      auth_basic_user_file /etc/nginx/conf.d/kibana.myhost.org.htpasswd;
    }
  }
}

Приклад конфігураційного файлу для віртуального хосту я взяв звідси
Під паролем приховані лише права на зміну панелі Kibana та її елементів, що звісно можна поширити на віртуалхост повністю. До речі, пароль генерується таким чином:

# apt-get install apache2-utils
# htpasswd -c /etc/nginx/conf.d/kibana.myhost.org.htpasswd user

Врешті-решт активуємо новий віртуалхост та перевантажуємо Nginx:

# ln -s /etc/nginx/sites-available/kibana-3.1.2.conf /etc/nginx/sites-enabled/kibana-3.1.2.conf
# service nginx restart

Переходимо до налаштування Logstash. Logstash - це демон, написаний на Java, що буде отримувати логи з віддалених систем за допомогою Logstash Forwarder, який власне їх і відсилатиме по протоколу Lumberjack. Про останній трішки далі, поки сфокусуємось на Logstash. Додаємо репозиторій та встановлюємо Logstash:

# echo 'deb http://packages.elasticsearch.org/logstash/1.4/debian stable main' | sudo tee /etc/apt/sources.list.d/logstash.list
# apt-get update
# apt-get install logstash

Передача логів між сервером і клієнтом буде зашифрована, для чого необхідно згенерувати сертифікат та ключ:

# mkdir -p /etc/pki/tls/certs
# mkdir /etc/pki/tls/private

# cd /etc/pki/tls; openssl req -x509 -batch -nodes -days 3650 -newkey rsa:2048 -keyout private/logstash-forwarder.key -out certs/logstash-forwarder.crt

Публічну частину надалі необхідно скопіювати на клієнти, котрі будуть присилати логи, але про це пізніше.

Створюємо конфігураційний файл базових налаштувань Logstash та пишемо в нього таке:

# vim /etc/logstash/conf.d/01-lumberjack-input.conf

input {
  lumberjack {
    port => 5000
    type => "logs"
    ssl_certificate => "/etc/pki/tls/certs/logstash-forwarder.crt"
    ssl_key => "/etc/pki/tls/private/logstash-forwarder.key"
  }
}

Тобто вказуємо протокол lumberjack, по якому і буде проходити передача інформації, порт 5000 (не забуваємо його не блокувати фаерволом) та ключі, що згенерували раніше.

Наразі створимо конфігураційний файл у якому опишемо правила розбору лог-файлу:

# vim /etc/logstash/conf.d/10-syslog.conf

filter {
  if [type] == "syslog" {
    grok {
      match => { "message" => "%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: %{GREEDYDATA:syslog_message}" }
      add_field => [ "received_at", "%{@timestamp}" ]
      add_field => [ "received_from", "%{host}" ]
    }
    syslog_pri { }
    date {
      match => [ "syslog_timestamp", "MMM  d HH:mm:ss", "MMM dd HH:mm:ss" ]
    }
  }
}

type - це мітка, яку буде виставляти Logstash Forwarder на кліенті. Якщо ця мітка виставлена в значення syslog - будуть виконані подані нище правила парсинку драйвером grok. Також будуть додані додаткові поля: час отримання лог-запису, ім'я хосту звідки повідомлення прийшло.

Останній конфігураційний файл - правило запису логів на сервер:

# vim /etc/logstash/conf.d/30-lumberjack-output.conf

output {
  elasticsearch { host => localhost }
  stdout { codec => rubydebug }
}

Логи будуть писатись локально до бази elasticsearch. Готово, перезапускаємо:

# service logstash restart

На хості, логи якого і бажаємо пересилати на сервер, встановлюємо Logstash Forwarder. Спочатку скопіюємо згенерований публічний ключ на кліент з Logstash-серверу:

# scp /etc/pki/tls/certs/logstash-forwarder.crt user@server_private_IP:/tmp

server_private_IP - адреса віддаленого кліента.

Надалі сертифікат копіюємо в коректне місце:

# mkdir -p /etc/pki/tls/certs
# cp /tmp/logstash-forwarder.crt /etc/pki/tls/certs/

Додамо додатковий репозиторій та ключ:

# echo 'deb http://packages.elasticsearch.org/logstashforwarder/debian stable main' | sudo tee /etc/apt/sources.list.d/logstashforwarder.list
# wget -O - http://packages.elasticsearch.org/GPG-KEY-elasticsearch | sudo apt-key add -

Встановлюємо Logstash Forwarder:

# apt-get update
# apt-get install logstash-forwarder

Конфігуруємо сервіс:

# vim /etc/logstash-forwarder

{
  "network": {
    "servers": [ "logstash_server_private_IP:5000" ],
    "timeout": 15,
    "ssl ca": "/etc/pki/tls/certs/logstash-forwarder.crt"
  },
  "files": [
    {
      "paths": [
        "/var/log/syslog",
        "/var/log/auth.log"
       ],
      "fields": { "type": "syslog" }
    }
   ]
}

logstash_server_private_IP - адреса сервера Logstash, котру необхідно вписати. "type": "syslog" вказує на відмітку для парсера на сервері Logstash. Перевантажуємо сервіс:

# service logstash-forwarder restart

Тепер можна побачити, що показує веб-адмінка відкривши в браузері http://kibana.myhost.org:


Побачити початкові графіки можна перейшовши за посиланням Logstash Dashboard (посилання на правій панелі стартової сторінки):


Додам, що можна увімкнути світлу тему оформлення (як я зрозумів, є люди які полюбляють або темну, або світлу) та пододавати додаткові статистичні дані: кругові діаграми та т.п.


Проте ми на цьому не зупинемось і додамо правила для відправки логів Apache та Nginx.  Це зовсім не складно. Спочатку відредагуємо правила Logstash Forwarder, що знаходиться на клієнті. Результат має виглядати так:

# vim /etc/logstash-forwarder

{
  "network": {
    "servers": [ "logstash_server_private_IP:5000" ],
    "timeout": 15,
    "ssl ca": "/etc/pki/tls/certs/logstash-forwarder.crt"
  },
  "files": [
    {
      "paths": [
        "/var/log/syslog",
        "/var/log/auth.log"
       ],
      "fields": { "type": "syslog" }
    },

    {
      "paths": [
        "/var/log/apache2/access.log"
       ],
      "fields": { "type": "apache-access" }
    },

    {
      "paths": [
        "/var/log/nginx/access.log",
        "/var/log/nginx/drupal.access.log"
       ],
      "fields": { "type": "nginx-access" }
    }
   ]
}

Отже логи від Apache /var/log/apache2/access.log ми помічаємо тегом apache-access, а логи від Nginx /var/log/nginx/access.log - тегом nginx-access і відправляємо на лог-сервер Logstash.

Додатково необхідно налаштувати правила парсингу логів доступу Apache/Nginx вже на самому лог-сервері. Почнемо з розбору правил Nginx. Створимо патерн:

# vim /opt/logstash/patterns/nginx

NGUSERNAME [a-zA-Z\.\@\-\+_%]+
NGUSER %{NGUSERNAME}
NGINXACCESS %{IPORHOST:clientip} %{NGUSER:ident} %{NGUSER:auth} \[%{HTTPDATE:timestamp}\] "%{WORD:verb} %{URIPATHPARAM:request} HTTP/%{NUMBER:httpversion}" %{NUMBER:response} (?:%{NUMBER:bytes}|-) (?:"(?:%{URI:referrer}|-)"|%{QS:referrer}) %{QS:agent}

# chown logstash:logstash /opt/logstash/patterns/nginx

Та використовуючи його створимо правило:

# vim /etc/logstash/conf.d/11-nginx.conf

filter {
  if [type] == "nginx-access" {
    grok {
      match => { "message" => "%{NGINXACCESS}" }
    }
  }
}

В директорії /opt/logstash/patterns є багато готових патернів, тому при їх наявності не обов'язково створвати свої власні. Наприклад, для Apache такий патерн вже існує і описаний в /opt/logstash/patterns/grok-patterns, лишилось описати лише фільтр:

# vim /etc/logstash/conf.d/12-apache.conf

filter {
  if [type] == "apache-access" {
    grok {
      match => { "message" => "%{COMBINEDAPACHELOG}" }
    }
  }
}

Готово. Рестартуємо Logstash:

# service logstash restart

Перевіряємо в адмінці Kibana що з'явилось нового (я маю на увазі нові логи веб-серверів):


Перевірити новостворені Grok правила можна за посиланням http://grokdebug.herokuapp.com/

Тут, до речі, описано як відсилати логи із віддаленої Windows-машини.

Доступ до даних Elasticsearch відбувається за допомогою curl. Раніше я згадував як переглянути статистику використання бази, а очистити базу повність можна наприклад таким чином:

# curl -XDELETE localhost:9200/*

Пошук необхідних даних Kibana проводить приблизно таким чином:

# curl -XGET 'http://localhost:9200/logstash-2015.01.29/_search?pretty' -d '{
  "facets": {
    "0": {
      "date_histogram": {
        "field": "@timestamp",
        "interval": "12h"
      },
      "global": true,
      "facet_filter": {
        "fquery": {
          "query": {
            "filtered": {
              "query": {
                "query_string": {
                  "query": "syslog_program: \"logstash-forwarder\""
                }
              },
              "filter": {
                "bool": {
                  "must": [
                    {
                      "range": {
                        "@timestamp": {
                          "from": 1419898633224,
                          "to": 1422490633225
                        }
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      }
    }
  },
  "size": 0
}'

Про всі інші запити можна прочитати тут.

Звісно, що чим більше записів в Elasticsearch - тим повільніше вона робитиме виборки. Тому розумним буде закривати індекси чи просто чистити базу:

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-delete-index.html
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-open-close.html

Простіше це можна зробити з elasticsearch-curator:

# pip install elasticsearch-curator

Та запускати його по крону, скажімо, вночі:

20 0 * * * /usr/local/bin/curator --host 127.0.0.1 delete --older-than 120
20 1 * * * /usr/local/bin/curator --host 127.0.0.1 close --older-than 90

delete --older-than 120 - видалення індексів, що стіріші 120 днів.
close --older-than 90 - закриття індексів старіших 90 днів (пізніше їх можна відкрити).

Більш детально про elasticsearch-curator можна почитати за посиланням.

Посилання:

https://www.digitalocean.com/community/tutorials/how-to-use-logstash-and-kibana-to-centralize-and-visualize-logs-on-ubuntu-14-04

Немає коментарів:

Дописати коментар