Мигрируем ELK 5.6 -> 6.0: переиндексация нескольких терабайт логов через Reindex API
Elastic Stack 6.0 GA запрещает multiple types на индекс. Автоматизируем переиндексацию терабайт логов через Reindex API и Logstash pipeline перед апгрейдом.
Elasticsearch / Kibana / Logstash 6.0 GA - один тип на индекс, улучшен Cross-Cluster Search, Kibana Canvas preview
Elastic Stack 6.0 GA вышел. Когда мы смотрели на 5.6 в сентябре, главным сюрпризом оказались multiple types - несколько типов документов в одном индексе. В 6.0 это запрещено: один индекс - один тип, точка. Тогда мы составили список проблемных индексов и пообещали себе разобраться с этим до GA. GA пришёл, пора выполнять обещания.
Для наших managed-проектов апгрейд не в воздухе висит - это реальные кластеры с несколькими терабайтами исторических логов. Просто обновить бинарники нельзя: сначала надо разобраться с данными.
Что нашёл Upgrade Assistant
Картина у каждого кластера своя, но паттерн общий. Исторические индексы вида logs-app-2016.* создавались в период когда мы ещё разбирались с маппингами. Один индекс, в нём типы nginx, app, cron. Казалось удобным - всё про одно приложение лежит рядом. В 5.x это работало нормально. В 6.0 такой индекс просто не откроется.
Свежие индексы - уже нормальные, один тип на индекс. Но архив за 2016-й и начало 2017-го заражён.
Дополнительно Upgrade Assistant нашёл индексы созданные ещё на ES 2.x - они требуют переиндексации независимо от типов, потому что 6.0 их формат не читает. Таких оказалось немного, но они есть.
Стратегия: что переиндексировать, что удалить
Первое что сделали - прошлись по всем проблемным индексам и честно ответили на вопрос: эти данные кто-нибудь смотрит? Часть архива была нужна только для compliance - лоб-бумаги требуют хранить логи год. Но есть разница между «хранить» и «индексировать в ES». Старые логи мы архивируем в S3 в сыром виде, а из ES удаляем.
Это сразу срезало объём работы раза в три.
Остались индексы где данные действительно живые или могут понадобиться - туда надо Reindex API.
Для независимых типов (nginx и app в одном индексе - это реально разные вещи) - разносим в отдельные индексы: logs-app-nginx-2017.* и logs-app-app-2017.*. Logstash pipeline переключается на новые имена. Kibana Saved Searches и Dashboards обновляются вручную.
Для связанных типов - объединяем в один с полем doc_type в качестве дискриминатора. Reindex с _script добавляет поле, маппинги выравниваются.
Reindex API: механика и подводные камни
Reindex API в ES позволяет перекачать данные из одного индекса в другой без выгрузки наружу. Базовый запрос выглядит примерно так:
POST /_reindex
{
"source": { "index": "logs-app-2017.01", "type": "nginx" },
"dest": { "index": "logs-app-nginx-2017.01" }
}
На практике выяснилось несколько вещей.
Первое - скорость. На кластере из трёх узлов переиндексация идёт заметно медленнее чем исходная индексация. Мы включили "conflicts": "proceed" и выставили "size": 1000 в source - это помогло, но не радикально. Для нескольких сотен гигабайт это часы.
Второе - async. Reindex умеет работать асинхронно через wait_for_completion=false. Получаешь task id, потом смотришь статус через Tasks API. Для больших индексов это единственный вменяемый способ - синхронный запрос просто timeout-нется.
Третье - маппинги. Reindex не копирует маппинг автоматически. Создаёшь целевой индекс вручную с нужным маппингом, потом запускаешь reindex. Если пропустить этот шаг - ES создаст индекс с dynamic mapping по первым документам, и можно получить keyword там где ожидался text, или наоборот.
Logstash pipeline для живых данных
Архивные индексы - это одна история. Но логи продолжают идти. Нужно одновременно переключить Logstash pipeline на новые имена индексов - иначе после удаления старых индексов и переезда на 6.0 новые данные снова пойдут куда не надо.
Мы поменяли output в Logstash: вместо одного индекса logs-%{app}-%{+YYYY.MM.dd} с document_type - явный паттерн logs-%{app}-%{log_type}-%{+YYYY.MM.dd} без типов. В 6.0 Logstash по умолчанию ставит тип _doc, что и нужно.
Переключение сделали атомарно - ночью, в окно минимальной нагрузки. Несколько минут между остановкой старого pipeline и запуском нового теряется, но для логов это некритично.
Kibana 6.0 и Canvas
Kibana 6.0 вышла с Canvas в preview. Это новый способ делать презентационные дашборды - ближе к Keynote чем к обычному Kibana dashboard. Мы посмотрели: интересно, но сыро. Для операционных дашбордов оно не нужно, для отчётов заказчикам - надо поиграться.
Cross-Cluster Search в 6.0 стал заметно проще в настройке. У одного заказчика два кластера - основной и DR. Раньше для поиска по обоим приходилось делать отдельные Index Pattern в Kibana. Теперь можно один pattern, который тянет из обоих. Это реально удобно.
Где сейчас
Переиндексация ещё идёт - большие исторические индексы мы гоним в фоне, не торопясь. Сам ES на большинстве кластеров уже обновлён до 6.0 через rolling upgrade. Logstash и Kibana тоже 6.0.
Один кластер пока на 5.6 - там объём архивных индексов с multiple types самый большой, и мы не хотели делать апгрейд ES до завершения переиндексации. Перейдём на этой неделе.
Главный вывод по итогам: проблема multiple types выглядела страшнее на бумаге чем оказалась на практике. Большую часть «проблемных» индексов мы просто удалили - они были артефактами давно забытых экспериментов. Реально переиндексировать пришлось в несколько раз меньше чем изначально казалось.
- Elasticsearch 5.6: готовимся к rolling upgrade на 6.0 через Upgrade Assistant · 25 сентября 2017
- Grafana 4.4: LDAP-группы для Teams и автоматический provisioning дашбордов · 28 августа 2017