Краткое введение в Elasticsearch

Насколько замечательно Grafana, Graphite и Prometheus справляются с численными данными мониторинга, вроде загрузки процессора по времени, настолько же они бесполезны для работы с логами. А ведь с теми приходится работать даже чаще, чем с метриками.

Инструментов для работы с логами тоже навалом, но сегодня мы посмотрим в сторону ELK стека от Elastic. А именно: Elasticsearch, Logstash и Kibana — хранилище/поисковик, обработчик данных и тулза для их визуализации. А начнём, естественно, с первой буквы этого трёх-буквенного алфавита — «E».

Что такое Elasticsearch

Elasticsearch — это быстрый, горизонтально масштабируемый и очень бесплатный гибрид NoSQL базы данных и гугла для неё. С миром он общается через HTTP API и через него уже получает на вход JSON документы для индексации и хранения. Хранение, правда, можно отключить, и тогда останется только поисковик, возвращающий айдишки когда-то проиндексированных документов.

Установка

Так как Elasticsearch написан на Java, устанавливается он очень просто:  качаем архив, распаковываем и запускаем bin/elasticsearch. Правда, запустить его через Docker будет еще проще: docker run -d -p9200:9200 elasticsearch. Всё общение будет проходить через порт 9200, так что самое время в него постучаться.

Осматриваемся

Вэбинары и официальная документация обычно показывают демки, используя еще один продукт от Elastic — Kibana. Но так речь идёт об обычном HTTP и JSON, отправлять и получать запросы можно чем угодно. Наверное, самый простой готовый инструмент — консоль и curl.

Итак, у нас есть порт 9200. Попробуем его пнуть просто так:

Неплохо. Номер версии в середине ответа и шутка юмора внизу — запрос определенно того стоил.

Есть и другие полезные запросы, для которых в индексе не обязательно должны быть данные. Например, можно проверить статус узла:

Или получить список индексов:

Так как установка свежая, то, разумеется, индексов в ней никаких еще нет. Но мы как-то внезапно начали оперировать специфическими терминами, вроде узла и индекса, так что стоит сначала разобраться с терминологией.

Терминология Elasticsearch

Итак, мы уже упомянули узел (node), что на самом деле означает отдельно взятый процесс elasticsearch с его данными и настройками. Даже один узел образует кластер. Но если узлов в кластере несколько, то включённый по умолчанию шардинг (дробление) индексов и репликация шардов (shards) резко повысит и выживаемость индексов за счёт избыточности, и скорость запросов к ним за счёт параллелизации. Похожий подход, кстати, работает и в Kafka, только там шарды называются разделами.

Сам по себе индекс — это просто коллекция документов. В пределах кластера их может быть уйма. Внутри индекса документы можно организовать по типам — произвольным именам, описывающим похожие по структуре документы. Наконец, сам документ — это просто JSON. Обычный скучный JSON.

Создание, чтение, обновление и удаление

С двумя абзацами теории разобрались, самое время что-нибудь сделать.

Создание

Добавить документ в elasticsearch так же просто, как и сделать HTTP POST. Ну один в один:

Мы отправили документ { "kind": "info", "message": "..."} в индекс под названием monitor, и тип с названием  logs. Ни индекса, ни типа до этого не существовало, и elasticsearch создал их, взяв названия из URL. Вдобавок, он разродился ответным JSON, в который положил сгенерированный идентификатор документа (_id) и немного других деталей. Кстати, можно задать и свой _id, просто заменив POST на PUT и передав идентификатор в URL. Например, вот так -X PUT monitor/logs/42. Слово ?pretty в строке запроса просто включает форматирование ответов.

Так как добавлять документы по одному то еще удовольствие, можно сразу добвить целую пачку через bulk запрос:

В bulk запросе на каждый документ идёт 2 JSON фрагмента. Один показывает, что именно нужно делать с документом (в нашем случае «index»). Второй фрагмент — сам документ.

Чтение

Теперь, раз уж у нас уже есть что-то в индексе, можно запросить что-нибудь назад. Если сделать пустой поиск, то мы получим в ответ всё, что успели добавить:

Но можно запросить конкретный документ по его ID:

Обновление

По аналогии, зная идентификатор документа, можно его обновить. Так как моё начальство нервно относится к фразам в логах вроде «Epic fail has just happened», его стоит заменить на что-нибудь другое:

Но на самом деле в этом случае elasticsearch не обновляет документ, а просто заменяет его на другой, сохраняя прежний ID.

Удаление

Чтобы удалить что-нибудь есть HTTP DELETE. Например,

curl -X DELETE 127.0.0.1:9200/monitor/logs/AVoWe_7d6fU5oFCNC7jb

Поиск

Но добавлять и получать назад JSON умеют многие NoSQL базы. Самая мощная фишка в elasticsearch — это, конечно, поиск. Есть два способа, чтобы искать документы по индексу: REST Request API для простых поисковых запросов, и более серьёзный Query DSL.

REST Request API просто добавляет дополнительный параметр в URL запроса, вроде такого:

Но через один ‘q='-параметр сложный запрос не соберешь. В Query DSL, с другой стороны, можно и комбинировать ключевые слова, и собирать булевы выражения, добавлять фильтры — много чего можно сделать, чтобы найти что-то конкретное.

Query DSL поиск это всё тот же HTTP GET запрос, но с немного более замороченным синтаксисом. Например, если мы хотим найти логи, которые так или иначе касаются памяти, но при этом не критичны, можно собрать такой запрос:

Агрегирование

В довесок к поиску данные можно еще и агрегировать. Агрегирование само по себе огромный топик, но в качестве примера можно просто посчитать, сколько логов у нас скопилось по категориям:

Так как _search URL делает и поиск и агрегацию, а ключевые слова для поиска мы не предоставили, в параметры пришлось добавить "size": 0, чтобы запрос не вернул всё коллекцию документов в довесок к статистике.

Завершение

Обычно в этом месте я пишу «сегодня мы едва прошлись по X», но elasticsearch настолько огромный, что даже слово «едва» ошибочно создаёт иллюзию объёма. Обновление документов через отправку скрипта, схемы полей, фильтры, сложные запросы  и агрегирование, работа в кластерах, анализаторы документов и куча других вещей — мы их вообще не затронули.

Но и того, что мы посмотрели, надеюсь, должно хватить, чтобы понять: elasticsearch — это вменяемо простой поисковый движок с понятным API и миллионом фич, которые нужно гуглить и гуглить. В следующий раз мы посмотрим, как заполнять его текстовыми данными мониторинга при помощи Logstash.

2 комментария для “Краткое введение в Elasticsearch

  1. спасибо за пост.
    просто, понятно и сразу можно начинать.
    может быть вы знаете, как сконфигурировать стандартные логи пайтона для добавления этих логов сразу в ElasticSearch?

    1. Пожалуйста.
      Насчёт питона и его логов, не скажу, что я в этом спец, но я бы пытался добавить соответствующий хэндлер (для elasticsearch или logstash) к стандартному питоновскому логгеру. Если гуглить что-то вроде «python logging handler elasticsearch» то сразу попадается что-то вроде такого — https://github.com/cmanaha/python-elasticsearch-logger. И там примеры кода очень похожие на то, что я бы ожидал увидеть:

      from cmreslogging.handlers import CMRESHandler
      handler = CMRESHandler(hosts=[{'host': 'localhost', 'port': 9200}],
      auth_type=CMRESHandler.AuthType.NO_AUTH,
      es_index_name="my_python_index")
      log = logging.getLogger("PythonTest")
      log.setLevel(logging.INFO)
      log.addHandler(handler)

Добавить комментарий

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