Учимся готовить Log4j + Logstash + ElasticSearch + Kibana 3 + Auth (Google OAuth2/BasicAuth/CAS Authentication)


Задача


Настройка удобного средства для обработки и получения логов.

Условия


  1. Лицензия MIT или Apache 2.0
  2. Возможность приема и обработки многострочных сообщений
  3. Простота в настройке и использовании
  4. Возможность работы с логами из Log4j


Решение


Logstash + ElasticSearch + Kibana 3.

Реализация


Для начала развернем Logstash + ElasticSearch + Kibana 3 на нашем сервере:


#Проверяем версию джавы, нам нужна 7 или выше
java -version

#Если установлена, то переходим в директорию в которой будет находится Logstash
cd /srv

#Создаем папку для всей системы
mkdir slog

#Переходим в нее
cd slog

#Качаем последнюю версию Logstash, найти последнюю версию можно тут http://logstash.net/
curl -O https://download.elasticsearch.org/logstash/logstash/logstash-1.4.2.tar.gz

#Распаковываем tar.gz
tar zxvf logstash-1.4.2.tar.gz

#Переходим в директорию с распакованным Logstash
cd logstash-1.4.2

#Проверяем работу Logstash командой
bin/logstash -e 'input { stdin { } } output { stdout {} }'

#После этого любой ввод с клавиатуры должен обработаться логсташем. Если все в порядке, останавливаем процесс (Ctrl + C).


Теперь настроим конфигурационный файл для Logstash, подробно тут
Файл можно сохранить где угодно, например я сохраняю в logstash/conf/main.conf.
Мой вариант конфигурационного файла:
input {
 log4j {
  mode => "server"
  host => "logstash_server_ip"
  port => logstash_server_port
  type => "log4j"
 }
}

output {
 elasticsearch {
  embedded => "true"
 }
}

Подробнее:

input
mode — Тип сервиса, сервер/клиент
host — IP адрес сервера, адрес к которому будет передавать логи log4j
port = logstash_server_port — порт для обмена логами
type — тип сообщений, для обозначения логов.
output
embedded — Нужно ли запускать собственный сервис elasticsearch или нужно будет устанавливать подключение к уже существующему

Теперь настроим передачу логов с Log4j:

Для этого будем использовать плагин Logstash для Log4j, и SocketAppender со стороны Log4j.

Добавим настройки в Log4j:

logstash_server_port — порт который мы укажем в настройках Logstash для обмена логами
logstash_server_ip — ip адрес сервера, на котором расположен Logstash
xml
<appender name="LOGSTASH" class="org.apache.log4j.net.SocketAppender">
	<param name="port" value="logstash_server_port" />
	<param name="remoteHost" value="logstash_server_ip" />
</appender>
<root>
	<appender-ref ref="LOGSTASH" />
</root>


properties
log4j.rootLogger=logstash
log4j.appender.logstash=org.apache.log4j.net.SocketAppender
log4j.appender.logstash.port=logstash_server_port
log4j.appender.logstash.remoteHost=logstash_server_ip


Теперь пробуем запустить систему:

#Для начала переходим в папку с Logstash
cd /srv/slog/logstash-1.4.2/

#Запускаем службу при помощи конфигурационного файла:
bin/logstash agent -f conf/main.conf

#В нашем случае мы еще хотим запустить визуальную часть, так что добавим в конце web
bin/logstash agent -f conf/main.conf web

По окончании запуска на экран будет выведено подобное сообщение:
Using milestone 1 input plugin 'log4j'. This plugin should work, but would benefit from use by folks like you. Please let us know if you find bugs or have suggestions on how to improve this plugin.  For more information on plugin milestones, see http://logstash.net/docs/1.4.2/plugin-milestones {:level=>:warn}

Которое говорит что плагин Log4j находится в тестовом состоянии.

Теперь переходим на визуальную часть
http://logstash_server_ip:9292

logstash_server_ip — ip адрес сервера
9292 — порт по умолчанию, его можно изменить в конфигурационном файле.

Стандартное представление Kibana мне показалось не сильно удобным, но его можно настроить под себя. Лично я взял за основу вариант из этой статьи и сделал представление более удобным, на мой взгляд.

Вот мой вариант
{
  "title": "Home dashboard dark",
  "services": {
    "query": {
      "idQueue": [],
      "list": {
        "0": {
          "id": 0,
          "color": "#7EB26D",
          "alias": "",
          "pin": false,
          "type": "lucene",
          "enable": true,
          "query": "priority: \"INFO\""
        },
        "1": {
          "id": 1,
          "color": "#E24D42",
          "query": "priority: \"ERROR\"",
          "alias": "",
          "pin": false,
          "type": "lucene",
          "enable": true
        },
        "2": {
          "id": 2,
          "color": "#6ED0E0",
          "alias": "",
          "pin": false,
          "type": "lucene",
          "enable": true,
          "query": "priority: \"WARN\""
        }
      },
      "ids": [
        0,
        1,
        2
      ]
    },
    "filter": {
      "idQueue": [],
      "list": {
        "0": {
          "type": "time",
          "field": "@timestamp",
          "from": "now-6h",
          "to": "now",
          "mandate": "must",
          "active": true,
          "alias": "",
          "id": 0
        }
      },
      "ids": [
        0
      ]
    }
  },
  "rows": [
    {
      "title": "Filtering",
      "height": "150px",
      "editable": true,
      "collapse": false,
      "collapsable": true,
      "panels": [
        {
          "error": false,
          "type": "filtering",
          "span": 12
        },
        {
          "loading": false,
          "error": false,
          "sizeable": false,
          "span": 12,
          "height": "150px",
          "editable": true,
          "type": "query",
          "query": "*",
          "pinned": true,
          "history": [
            "priority: \"WARN\"",
            "priority: \"ERROR\"",
            "priority: \"INFO\"",
            "@&~(HHH.+)",
            "@&~(foo.+)",
            "*",
            "level:\"WARN\"",
            "level:\"ERROR\"",
            "level:\"INFO\""
          ],
          "remember": 10
        }
      ],
      "notice": true
    },
    {
      "title": "Graph",
      "height": "200px",
      "editable": true,
      "collapse": false,
      "collapsable": true,
      "panels": [
        {
          "span": 12,
          "editable": true,
          "group": [
            "default"
          ],
          "type": "histogram",
          "mode": "count",
          "time_field": "@timestamp",
          "value_field": null,
          "auto_int": true,
          "resolution": 99,
          "interval": "5m",
          "fill": 2,
          "linewidth": 3,
          "timezone": "browser",
          "spyable": true,
          "zoomlinks": true,
          "bars": false,
          "stack": false,
          "points": false,
          "lines": true,
          "legend": true,
          "x-axis": true,
          "y-axis": true,
          "percentage": false,
          "interactive": true,
          "queries": {
            "mode": "all",
            "ids": [
              0,
              1,
              2
            ]
          },
          "title": "Events over time",
          "intervals": [
            "auto",
            "1s",
            "1m",
            "5m",
            "10m",
            "30m",
            "1h",
            "3h",
            "12h",
            "1d",
            "1w",
            "1M",
            "1y"
          ],
          "options": true,
          "tooltip": {
            "value_type": "cumulative",
            "query_as_alias": true
          },
          "scale": 1,
          "y_format": "none",
          "grid": {
            "max": null,
            "min": 0
          },
          "annotate": {
            "enable": false,
            "query": "*",
            "size": 20,
            "field": "_type",
            "sort": [
              "_score",
              "desc"
            ]
          },
          "pointradius": 5,
          "show_query": true,
          "legend_counts": true,
          "zerofill": true,
          "derivative": false
        }
      ],
      "notice": false
    },
    {
      "title": "Events",
      "height": "150px",
      "editable": true,
      "collapse": false,
      "collapsable": true,
      "panels": [
        {
          "title": "All events",
          "error": false,
          "span": 12,
          "editable": true,
          "group": [
            "default"
          ],
          "type": "table",
          "size": 100,
          "pages": 5,
          "offset": 0,
          "sort": [
            "@timestamp",
            "desc"
          ],
          "style": {
            "font-size": "9pt"
          },
          "overflow": "min-height",
          "fields": [
            "@timestamp",
            "priority",
            "message",
            "class",
            "host"
          ],
          "highlight": [
            "level"
          ],
          "sortable": true,
          "header": true,
          "paging": true,
          "spyable": true,
          "queries": {
            "mode": "all",
            "ids": [
              0,
              1,
              2
            ]
          },
          "field_list": false,
          "status": "Stable",
          "trimFactor": 300,
          "normTimes": true,
          "all_fields": false,
          "localTime": false,
          "timeField": "@timestamp"
        }
      ],
      "notice": false
    }
  ],
  "editable": true,
  "failover": false,
  "index": {
    "interval": "day",
    "pattern": "[logstash-]YYYY.MM.DD",
    "default": "NO_TIME_FILTER_OR_INDEX_PATTERN_NOT_MATCHED",
    "warm_fields": true
  },
  "style": "dark",
  "panel_hints": true,
  "pulldowns": [
    {
      "type": "query",
      "collapse": false,
      "notice": false,
      "query": "*",
      "pinned": true,
      "history": [],
      "remember": 10,
      "enable": false
    },
    {
      "type": "filtering",
      "collapse": true,
      "notice": true,
      "enable": false
    }
  ],
  "nav": [
    {
      "type": "timepicker",
      "collapse": false,
      "notice": false,
      "status": "Stable",
      "time_options": [
        "5m",
        "15m",
        "1h",
        "6h",
        "12h",
        "24h",
        "2d",
        "7d",
        "30d"
      ],
      "refresh_intervals": [
        "5s",
        "10s",
        "30s",
        "1m",
        "5m",
        "15m",
        "30m",
        "1h",
        "2h",
        "1d"
      ],
      "timefield": "@timestamp",
      "now": true,
      "filter_id": 0,
      "enable": true
    }
  ],
  "loader": {
    "save_gist": false,
    "save_elasticsearch": true,
    "save_local": true,
    "save_default": true,
    "save_temp": true,
    "save_temp_ttl_enable": true,
    "save_temp_ttl": "30d",
    "load_gist": true,
    "load_elasticsearch": true,
    "load_elasticsearch_size": 20,
    "load_local": true,
    "hide": false
  },
  "refresh": false
}


Аутентификация:

Недостатком данной системы является отсутствие любой аутентификации, из за того, что она была рассчитана на внутренние сети. Но это достаточно быстро решается вот этим форком из github.

Для того что бы им воспользоваться для начала мы должны установить node.js на наш сервер. Лично я использовал данный туториал.

#Переходим в директорию
cd /usr/src

#Заходим на http://nodejs.org/download/. и получаем линк на последнюю версию
#Например http://nodejs.org/dist/v0.10.31/node-v0.10.31.tar.gz
#Теперь вводим
wget http://nodejs.org/dist/v0.10.31/node-v0.10.31.tar.gz

#Распаковываем архив
tar zxf node-v0.10.4.tar.gz

#Переходим в директорию с node.js
cd node-v0.10.4

#Выполняем конфигурацию
./configure

#Далее выполняем непосредственную инсталяцию командами последовательно
make
make install

#Теперь у нас есть установленный node.js
#Приступим к установке и настройки форка с аутентификацией.
#Для начала перейдем в директорию которую создали ранее
cd /srv/slog

#Далее выполняем последовательно:
git clone https://github.com/fangli/kibana-authentication-proxy
cd kibana-authentication-proxy/
git submodule init
git submodule update
npm install

#Далее проверяем и обновляем Kibana до последней версии
cd kibana && git checkout master && git pull

#Следующим шагом является настройка config.js файла.
#Я люблю пользоваться nano редактором, так что в моем случае
nano /srv/slog/kibana-authentication-proxy/config.js


Для первоначального запуска нужно отредактировать следующие настройки: es_host/es_port
В них мы задаем настройки подключения к ElasticSearch. Если в предыдущем случае мы использовали встроенный ElasticSearch для встроенной Kibana, то теперь нам нужно настроить его на отдельную кастомную Kibana. Для этого редактируем наш main.conf файл, добавляя настройки порта ElasticSearch:

elasticsearch_server_port — порт по которому будет доступен elasticsearch
Финальная версия:
input {
 log4j {
  mode => "server"
  host => "logstash_server_ip"
  port => logstash_server_port
  type => "log4j"
 }
}

output {
 elasticsearch {
  embedded => "true"
  embedded_http_port => elasticsearch_server_port
 }
}


Теперь меняем настройки в config.js

«es_host»: logstash_server_ip
«es_port»: elasticsearch_server_port

Теперь аутентификация. Данный форк позволяет настроить одну из 3х аутентификаций: Google OAuth2/Basic Authentication/CAS Authentication.

Для примера настроим Basic Authentication:
    "enable_basic_auth": true,
        "basic_auth_users": [
            {"user": "admin", "password": "admin"},
        ],


Запуск:

#Для начала запустим Logstash + ElasticSearch
#Без приставки web так как теперь мы будем запускать на собственной вьюхе
cd /srv/slog/logstash-1.4.2/
bin/logstash agent -f conf/main.conf

#После того как Logstash стартует мы можем запустить вьюху.
cd /srv/slog/kibana-authentication-proxy/
node app.js

По умолчанию порт для данного форка Kibana — 9201
Так что теперь она доступна по адресу:
http://logstash_server_ip:9201. 


Результат






UPD: После обновления Logstash до версии 1.5.* рецепт не работает, будет время — выложу обновленную версию.
Метки:
Поделиться публикацией
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама
Комментарии 47
  • 0
    Спасибо за статью!

    Только зачем все это ставить и настраивать в ручную, когда есть Chef cookbook?
    • +3
      Какой смысл использовать комбайн, когда можно затратить куда меньше времени на единичный случай?!
      • 0
        Если вы считаете, что команды типа:
        vagrant provision
        chef-solo
        knife bootstrap
        другой способ
        занимает больше врмени, тогда ОК.
        • 0
          Все кроме вас так считают.
          • 0
            А не много ли вы на себя берёте, отвечая за всех?
          • 0
            Если нет chef`а? Установить предложите ?!
        • 0
          Примерное время настройки этого решения для одного проекта 1-2 часа, для моих целей это было лучшим вариантом.
          • 0
            Sorry, а vim и обычный файл логов уже отменили?
            • +2
              Не vim, а less. Если речь про просмотр. Не less, a grep — если про первичный анализ. А так, себя хорошо зарекомендовал awk.
              Но logstash не о том, чтобы просто посмотреть логи. Он про то, чтобы собрать эти логи с кучи источников/серверов в одном месте, и сделать их анализ быстро и удобно. С поиском, регулярками и прочим.
              Обычный же файл логов, т.е. сырые данные тоже нужны. Но только после того, когда понятно, что и где мы ищем.
              • 0
                Вполне можно пользоваться только kibana для просмотра и не заходить на хост для grep/awk. Для этого нужны фильтры по времени + фильтр по хосту, приложению и его инстансу. Попробуйте на гистограмме в kibana выделить участок с помощью мыши ;-)
                • 0
                  Я смотрю логи всегда через vim.
                  • 0
                    Я как-то ради интереса пробовал открыть в vim лог на 10+ гигов. Через несколько минут плюнул и прибил процесс.
          • +1
            А этот патч для kibana решает проблему с тем, что при использовании embedded elasticsearch он торчит «голым задом» наружу? А то штатные средства авторизации kibana прикрывают только web-мордочку, при этом обычным curl можно получить дынные с server_ip:9200.
            • 0
              Нет, оно также прикрывает только веб морду, ElasticSearch отдельный модуль, и безопасность там я решал другим способом. Фактически это можно решить открывая только 2 порта с сервера
              1. Для обмена логами (Доступ открывался только для ip адресов серверов с приложениями)
              2. Для веб морды
              Остальные составляющие крутятся внутри, и доступ к ним есть только локально.
              • +1
                Тогда у меня вопрос: чем лучше авторизация средствами этого прокси-патча, к тому же требующего node.js на сервере, чем обычная base auth средствами apache или nginx? Есть очевидные плюсы, если не считать фишек типа Google OAuth2?
                • 0
                  Я выбрал именно этот вид авторизации из за возможной масштабируемости, и лично для меня было проще развернуть этот вид аутентификации, по причине простоты использования и конфигурирования, не хотелось настраивать все это вручную. Также требовалось минимальное время настройки системы, а учитывая уже предустановленный node.js на сервере, это был хороший вариант. Однако вы правы, в части случаев возможно удобнее настроить обычную аутентификацию средствами apache или nginx, будет интересно это попробовать.
                  • 0
                    Спасибо за ответы, аргументацию понял. Просто смутило, что пароли хранятся плэйнтекстом и node.js.
                    • 0
                      В своем проекте я использовал Google OAuth2, base auth использовал в статье для демонстрации работы системы. Так как ее быстрее и проще всего настроить и показать.
              • 0
                В нашем приложении настроил jetty proxy servlet, прикрутил websso фильтр, интегрированный с корпоративным LDAP и живем счастливо и безопасно. Если боитесь update,delete REST запросов, можно создать фильтр по url и также отключить в ES выражения на mvl и groovy и т.п.
              • +1
                в заголовке опечатка — Logj4
              • 0
                А можно ли так по логам искать? Делать срезы по времени, по log level, поиск по тексту?
                • 0
                  Да, можно настраивать фильтрацию как угодно, допустим если нас интересуют только ERROR логи, с текстом начинающимся на Hibernate, и которые были выброшены из определенного класса. К тому же между ними удобно переключаться, по поводу срезов во времени, то возможно или задать рамки явно в фильтрах, или просто на веб морде выделить мышкой необходимый диапазон. Подробней про фильтры можно прочитать тут
                • 0
                  Если верить документации log4j, у SocketAppender'a есть существенный недостаток: если хост, на который нужно писать логи, упал, то приложение, пишущее логи, встаёт колом. Есть ли где-нибудь на просторах Open Source реализация SocketAppendera с буфером и просто дропающая логи при его переполнении?
                  • +1
                    Это не совсем так, при выключенном севере принимающем логи(в нашем случае Logstash) логи просто не доходят до него, но:
                    1. Приложение продолжает работать, и писать логи в файлы как и ранее.
                    2. Через определенные интервалы времени пытается восстановить подключение, и если оно восстановлено, то передача логов возобновляется.
                    Данная система является надстройкой, дополнительной системой, упрощающей работу с логами, особенно если речь идет о логах от разнообразных сервисов.
                    Если вы найдете способ реализации «SocketAppendera с буфером» напишите в комментариях или лс, так как это было бы действительно интересно.
                    Однако также эту систему можно настроить не только на Log4j, но и фактически на любую другую подобную технологию. В моем случае необходима была работа именно с Log4j, без возможности замены.
                    • 0
                      Тогда еще два вопроса:
                      1. А при упавшем хосте и/или потере коннекта (сетка моргнула/упала) до хоста какое будет поведение?
                      2. Если верить опять же документации, если соединение есть, но при этом канал забит/слаб, то скорость работы приложения будет ограничена скоростью записи в этот канал?


                      Правда, я, по умолчанию, веду речь о старом добром Log4j версии 1, на смену которому в июле вышел Log4j версии 2, в котором, как я понял, можно сделать всё логирование асинхронным. Но у меня опыта работы с ним нет, поэтому о минусах говорить не могу.
                      • +1
                        Я использую Log4j 1 версии.
                        1. Проясните ситуацию, я не совсем понял вопрос
                        2. Я тестирую эту систему уже 3 месяца, и за все это время задержек в работе программы не обнаруживал, хотя бывало что и виртуалка падала, или вообще могла пару дней не работать, соединение нормально восстанавливалось, и все продолжало стабильно работать.

                        Единственное что как то обнаружил, это то, что нужно проверять правильная ли дата стоит на самом сервере, так как иначе могут быть проблемы плана: кинули лог, а он не отображается, и появляется только через минут 10, так как по временным рамкам он в другом диапазоне, так что нужно проверять что бы дата и время всегда были правильными.
                        • 0
                          1. Из документации:
                            In particular, if the network link to the the server is down, the client will be blocked.

                            Т.е., допустим, ваш сервер LogStash поднят на хост с ip = 192.168.206.1, при этом падает не LogStash, а сеть, т.е. узел 192.168.206.1 становится недоступен.
                          2. Возможно, в вашей системе не тот объем логов/отличный канал между клиентом (приложением) и сервером (logStash)/лаг в десяток миллисекунд не заметен.

                          Синхронизация времени на серверах — да, это тоже интересный момент, как и выставление timezone, например )

                          В общем, аккуратней нужно быть с SocketAppender'ом из коробки :)
                          • 0
                            Тут вы правы.
                            1. По поводу первого вопроса, я понял ситуацию, но не совсем понял вопрос, но если вы спрашиваете восстановится ли соединение после возобновления узла, то да, в моем случае оно возобновлялось.
                            2. Да, может и так, я использовал его не для просмотра GET/POST логов например, а для просмотра обычных INFO/ERROR/WARN логов кидаемых приложением. Однако есть еще такой момент, при деплое моего приложения, хибернейт кидает порядка 200-300 логов сразу, и даже учитывая это, время на деплой увеличивалось только на время необходимое для установления соединения с Logstash. Но возможно это нужно будет проверить на увеличенном объеме кидаемых логов, и тогда будет сильна видна разница.
                            • 0
                              Проще не SocketAppender использовать, а парсить логи из файловой системы file input модуль. Но соответственно, нужно настроить regexp для извлечения именованных полей в json запись в elasticsearch. И вообще logstash в такой системе не обязателен, если требуется сохранять логи только своего приложения. Буду делать доклад про мониторинг большого in-memory data grid кластера с помощью ELK. Кто будет на конференции, с удовольствием поделюсь опытом. Чуть освобожусь, напишу здесь статью про Elasticsearch в более забавном применении
                              • 0
                                Обязательно прочитаю. Про парсинг логов из файловой системы думал, но в моем случае сервер с приложением и сервер с логсташем находятся в разных странах.
                                • 0
                                  Logstash можно запустить in-process в java программе с помощью jruby, если жалко отдельного процесса. Кроме того можно парсить логи из файловой системы любой своей программой почти на любом языке программирования без logstash. Отправлять через REST API в elasticsearch записи логов в нужном формате(такой же json, как формирует logstash). В этом случае logstash не нужен. Формат можете подсмотреть с помощью elasticHQ, в изучении записей может также помочь elasticsearch-head.

                                  В случае своего парсера логов elasticsearch+kibana будет достаточно. Соответственно в парсере можно предусмотреть ожидание, если elasticsearch не доступен. Продолжить парсинг можно будет с того же места при восстановлении. В этом случае никаких больших буферов в памяти не нужно и сообщения не потеряются.

                                  Если же требования к надежности хранения данных в ES параноидальные, то можно настроить количество реплик для каждой записи логов в индексе и дополнительно использовать механизм snapshot
                                  • 0
                                    Так то оно да, но это нарушает одно из моих условий:
                                    «3. Простота в настройке и использовании»
                                    Условия ставились таким образом, что на реализацию системы выделялось минимальное количество времени, и была необходима система, которую можно было бы быстрее, и проще развернуть. Она не является основной в моем случае, она лишь надстройка помогающая в поиске, а писать свою реализацию этого в моем случае было нецелесообразно.
                                    • 0
                                      Согласен, отличный аргумент для выбора logstash!
                            • 0
                              Network Time Protocol daemon может помочь. Обязательно надо помнить при парсинге дат из логов, что в logstash json записи время передается в timezone UTC.
                    • +1
                      В kibana делать срезы по времени, log level можно с помощью фильтров которые можно сохранить в виде разных дашбордов в тот же инстанс Elasticsearch. В Elasticsearch отличный полнотекстовый поиск, но для. Надо только учитывать, что при поиске по регулярному выражению ищет не по всему полю из множества слов, а по тому что оказалось в индексе после токенизации, но и это можно обойти. Для нормального поиска по русскому тексту требуются небольшие танцы с бубном и настройками
                      • 0
                        Умеет ли это все работать с rsyslog или syslog-ng?

                        Было бы круто, если вы в начале статьи описали что есть что в этой схеме Logstash + ElastickSearch + Kibana 3 и какую роль выполняет каждый из них.
                        • 0
                          Умеет ли это все работать с rsyslog или syslog-ng?

                          Да, но для этого нужно отдельно конфигурировать, и лично я этого не пробовал.
                          Было бы круто, если вы в начале статьи описали что есть что в этой схеме Logstash + ElastickSearch + Kibana 3 и какую роль выполняет каждый из них.

                          Первоначально так и хотел сделать, но из за недостатка времени к сожалению не вышло. Я планирую оптимизировать эту систему, ускорить установку, упростить запуск и остановку. Тогда и постараюсь ответить на все ваши вопросы.
                          • +1
                            Elasticsearch — распределенный поисковый движок, надстройка над apache lucene с автоматическим шардированием индексов, REST сервисами для поиска по индексам, обновления и администрирования хранилища индексов. Упрощенно можно рассматривать как NoSQL базу для хранения и индексирования данных в формате json. Отличный выбор если объем данных огромный, требуется полнотекстовый поиск и простое горизонтальное масштабирование хранилища.

                            Kibana3 — html5 фронтэнд для просмотра данных в elasticsearch, фильтрации и визуализации данных. Кроме ES для работы ему ничего больше не нужно, он взаимодействует c ES по REST.

                            Logstash — парсер/агрегатор логов. Есть input модули, в том числе и для syslog. DSL на ruby для конфигурирования, возможны выражения на ruby, if в конфигурации и т.п. Фильтры для извлечения и обработки информации из input модулей. codec для преобразования форматов данных и output для сохранения в какую либо систему для анализа. Elasticsearch отлично подходит в качестве output системы.

                            ELK высокоинтегрированный стек. Возможен запуск всех трех компонентов в одном java процессе. Logstash(через встроенный jruby), embedded Elasticsearch и получить браузером статику Kibana через веб сервер. Но возможно запускать ES и Logstash в разных процесах, с различной топологией кластера ES(различное количество процессов сервера на различных узлах с записью данных на разные диски, мультикаст или юникаст обнаружение узлов кластера)
                          • –1
                            У вас вначале статьи написано ElastickSearch вместо ElasticSearch.
                          • –1
                            Недостатком такой связки является отсутствие возможности выгрузить какую-то пачку логов в эксель/сsv/txt за 1 клик прямо из кибаны.

                            Соответственно приходится писать микро-приложение которое дернет API и сохранит результат в эксель =(
                            • 0
                              Странно конечно, экспортировать логи в эксель, но должен вас огорчить, логстэш имеет плагин для экспорта в csv.
                              • 0
                                Можно не писать такое приложение, так как elasticsearch-head имеет функцию выгрузки в CSV формат. На 27 слайде моей презентации про Elasticsearch/Logstash/Kibana есть скриншот как это делается
                                • 0
                                  Вот так
                                  выгружать в csv

                                • 0
                                  Я вместо форка использовал nginx с basic_auth.
                                  Можно проксировать запросы на любой порт, при этом есть авторизация.
                                  • 0
                                    kibana-authentication-proxy немного умер, авторы рекомендуют проксировать/авторизовывать другими средствами.

                                    github.com/elasticsearch/kibana/issues/1628

                                    Example for nginx:

                                    Включаем ssl при подключении к elastic в кибана:
                                    kibana/config.js:

                                    — elasticsearch: «http://»+window.location.hostname+":9200",
                                    + elasticsearch: «https://»+window.location.hostname/,

                                    example.org.conf for nginx:

                                    server {
                                    listen *:443 ssl;

                                    server_name example.org

                                    ssl on;


                                    location / {
                                    proxy_pass 127.0.0.1:9292;
                                    proxy_read_timeout 90;
                                    proxy_connect_timeout 90;
                                    proxy_redirect off;
                                    proxy_set_header Host $host;
                                    proxy_set_header X-Real-IP $remote_addr;
                                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                                    }
                                    location ~ ^/.*/_mapping {
                                    proxy_pass 127.0.0.1:9200;
                                    proxy_read_timeout 90;
                                    proxy_connect_timeout 90;
                                    proxy_redirect off;
                                    proxy_set_header Host $host;
                                    proxy_set_header X-Real-IP $remote_addr;
                                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                                    }
                                    location ~ ^/.*/_search$ {
                                    proxy_pass 127.0.0.1:9200;
                                    proxy_read_timeout 90;
                                    proxy_connect_timeout 90;
                                    proxy_redirect off;
                                    proxy_set_header Host $host;
                                    proxy_set_header X-Real-IP $remote_addr;
                                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                                    }
                                    location ~ ^/_aliases$ {
                                    proxy_pass 127.0.0.1:9200;
                                    proxy_read_timeout 90;
                                    proxy_connect_timeout 90;
                                    proxy_redirect off;
                                    proxy_set_header Host $host;
                                    proxy_set_header X-Real-IP $remote_addr;
                                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                                    }
                                    location ~ ^/_nodes$ {
                                    proxy_pass 127.0.0.1:9200;
                                    proxy_read_timeout 90;
                                    proxy_connect_timeout 90;
                                    proxy_redirect off;
                                    proxy_set_header Host $host;
                                    proxy_set_header X-Real-IP $remote_addr;
                                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                                    }
                                    location ~ ^/kibana-int/dashboard/.*$ {
                                    proxy_pass 127.0.0.1:9200;
                                    proxy_read_timeout 90;
                                    proxy_connect_timeout 90;
                                    proxy_redirect off;
                                    proxy_set_header Host $host;
                                    proxy_set_header X-Real-IP $remote_addr;
                                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                                    }
                                    location ~ ^/kibana-int/temp.*$ {
                                    proxy_pass 127.0.0.1:9200;
                                    proxy_read_timeout 90;
                                    proxy_connect_timeout 90;
                                    proxy_redirect off;
                                    proxy_set_header Host $host;
                                    proxy_set_header X-Real-IP $remote_addr;
                                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                                    }
                                    location ~ ^/.*/_aliases$ {
                                    proxy_pass 127.0.0.1:9200;
                                    proxy_read_timeout 90;
                                    proxy_connect_timeout 90;
                                    proxy_redirect off;
                                    proxy_set_header Host $host;
                                    proxy_set_header X-Real-IP $remote_addr;
                                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                                    }

                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.