Многие я думаю читали о применении Elasticsearch, Logstash и Kibana для сбора и анализа логов, но часто статьи начинаются с длинного мануала как поднять сервисы ELK и заставить работать их совместно.
Здесь я хочу рассказать о быстром старте с помощью Docker.

Напишу заранее, что статья ориентирована на тех кто уже знаком с Docker и имеет желание поднять стек ELK для ознакомления или будущего использования в продуктиве. А для тех кто не знает нужен ли им ELK, рекомендую причитать статью Kibana-мать или Зачем вам вообще нужны логи?.

Итак, в идеале задача сводится к тому, чтобы найти контейнер с ELK на hub.docker.com и запустить его. Предлагаю так и сделать с некоторыми доработками. В примере рассмотрим отправку логов nginx в elasticSearch.

Аббревиатура сервисов ELK предусматривает следующие задачи:
1) Обработку поступающих данных и доставку их в Elasticsearch — за это отвечает сервис Logstash
2) Поисковый движок и интерфейс доступа к данным — за это отвечают сам Elasticsearch и Kibana

Но по хорошему Logstash не должен отвечать за доставку данных. Доставку данных делегируем четвертому сервису — Filebeat.

Общая схема работы выглядит следующим образом:

image

В сети может находится различное количество сервисов, с которых необходимо собирать данные и сервис Filebeat является провайдером логов для сервиса Logstash.

Другими словами я веду к тому, что нам необходимо заиметь еще один контейнер с сервисом Filebeat.

Приступим к делу. Я настоятельно рекомендую вам пользоваться сервисом Docker Compose — описывать параметры в одном файле формата YAML, гораздо удобнее чем каждый раз выполнять команды с параметрами. А на этапе отладки запустить и остановить придется не 1 раз.

1. Создадим папку с проектом, например myElk и создадим там файл следующего имени docker-compose.yml, который мы будем дополнять.

2. Ищем и находим контейнер с filebeat. Я рекомендую взять вот этот olinicola/filebeat или выполнить docker pull olinicola/filebeat
Настройка контейнера с filebeat заключается в подготовке конфигурационного файла в формате YAML для сервиса filebeat.
У нас он будет выглядеть следующим образом:

prospectors:
        -
            paths:
                - "/etc/logs/nginx/access.log"
            document_type: nginx-access
        -
            paths:
                - "/var/log/nginx/error.log"
            document_type: nginx-error
output:
    logstash:
        hosts: ["elk:5044"]
        tls:
          certificate_authorities:
            - /etc/pki/tls/certs/logstash-beats.crt
        timeout: 15
    file:
        path: "/tmp/filebeat"


Если коротко, то берем логи nginx с определенного места сервера и отправляем их на ELK сервер, который готов принимать от нас сообщения на порт 5044.
В данном конфигурационном файле «elk» — имя прилинкованного контейнера — подробнее ниже.
Я также дополнительно указал выгрузку в файл, для более удобной отладке на этапе запуска.

На данном этапе вы уже можете дополнить docker-compose.yml следующим кодом:

version: '2'
services:
    filebeat:
        build: .
        image: [ваш imageId образа filebeat]
        volumes:
            - /path/to/myElk/log/nginx:/etc/logs/nginx # логи nginx
            - /path/to/myElk/filebeat:/etc/filebeat
            - /path/to/myElk/filebeat/tmp:/tmp/filebeat


Вы уже можете запустить поднять контейнер командой docker-compose up. И посмотреть как при изменении файла access.log данные будут отправляться в файл "/tmp/filebeat", только на данном этапе еще нет контейнера elk, поэтому output logstash лучше закомментировать.

3. Ок, нас появился первый контейнер с filebeat. Теперь нам нужен второй контейнер с ELK. Идем на hub.docker.com и находим sebp/elk или выполняем команду docker pull sebp/elk.

Настройка контейнера ELK.
Единственное, что нужно настроить здесь это logstash, причем тут 2 варианта: а) оставить все как есть и это будет работать, так как logstash в данном контейнере уже настроен на получение логов nginx сервера.
Однако после того как вы запуститесь вам захочется пойти по пути б)-то есть настроить логи так как нужно именно вам. Потому что от того как будут переданы логи в elasticsearch вам будет более или менее удобно анализировать данные, приходящие с nginx.
Итак поясню файлы конфигурации logstash. Файлы логов, которые нас интересуют следующие:
Входные параметры:
02-beats-input.conf — можно не трогать

input {
	  beats {
	    port => 5044
	    ssl => true
	    ssl_certificate => "/etc/pki/tls/certs/logstash-beats.crt"
	    ssl_key => "/etc/pki/tls/private/logstash-beats.key"
	  }
	}



Здесь мы видим, что сервис готов принимать данные по порту 5044.
Выходные параметры:
30-output.conf — можно не трогать

output {
	  elasticsearch {
	    hosts => ["localhost"]
	    sniffing => true
	    manage_template => false
	    index => "%{[@metadata][beat]}-%{+YYYY.MM.dd}"
	    document_type => "%{[@metadata][type]}"
	  }
	  stdout { codec => rubydebug }
	}


Самое интересное — преобразование данных. По умолчанию файл 11-nginx.conf выглядит так

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


Но возможно после того как вы наиграетесь с шаблоном NGINXACCESS вы захотите обработать ваши логи именно так как нужно вам.
Для этого вам нужно будет изменять секцию filter. Там может быть несколько параметров — очень хорошо описано здесь Собираем, парсим и отдаём логи с помощью Logstash.
От себя хочу добавить, что для отладки grok фильтров хорошо подходит следующий сервис: Grok Debugger

3. Компоновка 2х контейнеров.

Здесь я настоятельно рекумендую вам пользоваться сервисом Docker Compose — описывать параметры в одном файле формата YAML, гораздо удобнее чем каждый раз выполнять команды с параметрами. А на этапе отладки запустить и остановить придется не 1 раз.
Для этого вам необходимо создать папку с проектом, например myElk и создать там файл следующего имени docker-compose.yml и например следующего содержания:

version: '2'
services:
    filebeat:
        build: .
        image: [ваш imageId образа filebeat]
        volumes:
            - /path/to/myElk/log/nginx:/etc/logs/nginx # логи nginx
            - /path/to/myElk/filebeat:/etc/filebeat
            - /path/to/myElk/filebeat/tmp:/tmp/filebeat
            - /path/to/myElk/filebeat/certs:/etc/pki/tls/certs
        links:
            - "elk"
        depends_on:
            - "elk"
        #entrypoint: ./time-to-start.sh
    elk:
        image: [ваш imageId образа elk]
        ports:
            - "5601:5601" #kibana
            - "9200:9200" #elastic
            - "5044:5044" #logstash beats filebeat


Данный конфигурационный файл описывает два контейнера и их взаимосвязь, а т
Пробуйте запустить контейнер, если все ОК, то по адресу localhost:5601 вы увидите первую страницу Kibana, где вам нужно будет выбрать первый index, он будет сформирован вида filebeat-[дата], наберите filebeat и если данные начали поступать, то он будет сформирован автоматически.

Для тех кто запускает docker на mac — вам необходимо будет дополнительно пробросить порты через проброс портов VirtualBox, чтобы localhost:5601 был доступен на хостовой машине.

Комментарии (16)


  1. tolkkv
    03.05.2016 22:38

    Спасибо за статью, приятно видеть, что ELK стек активно развивается.
    Я еще не пробовал filebeat, но у меня сразу возникают два вопроса:
    1 — если будет рестарт filebeat, то как он узнает с какого места перечитывать файл? Или же он снова начнет отправлять все файлы?
    2 — Вы сказали, что logstash не должен отвечать за доставку данных и этим должен заниматься filebeat. Но не объяснли — почему? :)


    1. gibson_dev
      04.05.2016 09:11

      Он хранит состояние работы и в частности смещение файла до которого он уже отправил данные


      1. tolkkv
        04.05.2016 12:14

        Интересно было как и где, но ссылка ниже дает исчерпывающий ответ)


    1. deklin
      04.05.2016 11:04
      +1

      2 — Вы сказали, что logstash не должен отвечать за доставку данных и этим должен заниматься filebeat. Но не объяснли — почему? :)

      Logstash может выступать в качестве шиппера логов, конечно, но футпринт, мягко говоря, значительный. Написан на JRuby, требует целую JVM и гору памяти. Ставить такого монстра на каждый хост — лучше ресурсы веб-серверу или аппликухе отдать… А вот filebeat — это наследник logstash-forwarder (экс. lumberjack) — написан на Go, быстрый, портабельный (один бинарник) и нетребовательный к ресурсам. Что еще надо от агента?


    1. robertsz
      04.05.2016 11:19

      Здравствуйте. Ответ на вопрос 1: filebeat ведет свой реестр, чтобы знать где было последнее чтение. Можно посмотреть здесь: https://www.elastic.co/guide/en/beats/filebeat/current/_updating_the_registry_file.html
      Ответ на вопрос 2: Даже если посмотреть на сайт https://www.elastic.co то в разделении по продуктам вы увидете, что logstash занимается своими задачами, а доставка данных вынесена в отдельные сервисы. Этих сервисов у вас может быть много, а сервер обработки данных 1.


  1. k3NGuru
    04.05.2016 05:04
    +1

    Вообще не понял, где тут ELK контейнер?
    Вот тут https://github.com/sqshq/ELK-docker отличный docker-compose для сбора ELK.


  1. dyakhnov
    04.05.2016 05:43

    Если Kibana в Docker будет падать с OOM ошибкой:
    https://github.com/elastic/kibana/issues/5170


  1. kt97679
    04.05.2016 06:04
    +1

    Прежде чем строить ELK инфраструктуру настоятельно рекомендую оценить потянет ли она ваши объемы логирования и во что выльется поддержка. Я уже больше года пытаюсь приручить этого зверя (в частности для логирования из контейнеров) и на данный момент принято решение отказаться от ELK, использовать обычный syslog, логи загружать в hadoop и анализировать уже там. Для отслеживания ситуации в реальном времени использовать стриминг on demand возможно с минимальной фильтрацией. ELK не взлетел, хотя мы очень старались.


    1. Sheh
      04.05.2016 08:53

      Расскажите подробнее. Стоит такая же задача.
      Почему приняли решение отказаться?
      Производительность сильно упала по сравнению с syslog? Что, если в ELK отправлять не всё подряд, а наиболее значимую информацию?

      для отслеживания ситуации в реальном времени использовать стриминг on demand

      Как вы это реализуете и с помощью чего?


      1. kt97679
        04.05.2016 19:33
        +1

        Вот мои предыдущие комментарии на эту тему:

        https://habrahabr.ru/company/uteam/blog/278729/#comment_8799489
        https://habrahabr.ru/post/275815/#comment_8751947

        Кратко подытоживая: причины отказа низкая производительность, плохое масштабирование и проблемы со стабильностью. На данный момент у меня кластер А 10 машин (каждая машина 24 ядра 48 гб памяти) с трудом тянет 15к логов в секунду. На кластере Б памяти 128 гб на машину, что дает порядка 50к логов в секунду. Это при дневных индексах, 7-ми дневно ретеншене и около 1000 шард на кластер А, около 3000 шард на кластер Б. Если переключится на часовые индексы и снизить ретеншен до 3-х дней количество шард на кластере Б поднимается до 25к и он начинает падать с завидной периодичностью. У всех машин стоит по 4 диска 1.8тб. На кластере А количество документов около 7г и диски заняты от 26% до 45%, на кластере Б документов около 3.5г, диски заняты от 9% до 14%. Полный траффик логов у меня 130 логов/с, что значит мне нужно кластер А расширить до как минимум 200 машин, что будет 2 миллиона долларов только на покупку железа, обслуживание встанет в отдельные деньги. Глядя на подобные суммы начинаешь уже задумываться о спланке, который безумно дорог, но тебе вообще не надо думать об инфраструктуре.

        Real time log streaming пока в стадии обдумывания. Самое простое решение, которое на данный момент обсуждается, это логировать все в локальные файлы на лог сервере с очень короткой ротацией и tail-ом отдавать их по http возможно фильтруя grep-ом. Но это предварительно, возможно все будет сложнее.

        Отвечая на ваш вопрос об ограничении трафика в ELK: да, на маленьких объемах все работает нормально. Только вот объяснить людям, что не надо лить в логи все подряд (у меня был прецедент, когда начали заливали целиком http ответы, каждый log entry был за 100к) задача крайне не простая. И опять же мое крайне субъективное мнение: когда кто-то требует ELK утверждая, что только так он может гарантировать нормальную работу своего сервиса скорее всего что-то сильно не так с самим сервисом.


        1. tolkkv
          05.05.2016 11:08

          Интересный опыт, спасибо. Подскажите, а к какому решению в итоге пришли? Что занимается сбором/агрегацией потока логов у вас?


          1. kt97679
            05.05.2016 17:18

            В настоящий момент scribe, но ведется работа над новой инфраструктурой, пока, к сожалению, стадия дизайна-обсуждений.


            1. tolkkv
              05.05.2016 19:07

              Буду с нетерпением ждать результатов на хабре. Надеюсь они будут :)


    1. novikovSU
      04.05.2016 14:26

      Было бы круто, если бы вы подробнее описали конкретные проблемы, с которыми столкнулись. Особенно те, что повлияли на решение об отказе.


      1. kt97679
        04.05.2016 19:41

        Ответил выше.


  1. shuvalov
    04.05.2016 09:11
    +1

    у sebp/elk есть один минус — до недавнего времени он не использовал тэги, кроме latest. Сейчас с этим чуть лучше. Мы на эти грабли наступили однажды, когда latest переключился на новый logstash, который стал несовместим с нашими конфигами. Рекомендую в продакшене использовать не один контейнер, а три, примерно по такой схеме:


    logstash:
      image: logstash:2.1.1
      links:
        - elasticsearch
    elasticsearch:
      image: elasticsearch:2.2.2
    kibana:
      image: kibana:4.3.1
      ports:
        - 5601:5601
      links:
        - elasticsearch