Многоуровневая архитектура Elasticsearch: Горячая, теплая, холодная и замороженная

В этом полном руководстве мы представим концепцию и объясним, как реализовать многоуровневую кластерную архитектуру Elasticsearch. Сначала мы поговорим о том, что такое многоуровневая архитектура, ее преимуществах, вариантах использования и о том, как она реализована в Elasticsearch +7.10. Мы рассмотрим уровни данных, настройку узлов кластера и распределение индексов.

Во второй части руководства мы представим экспериментальный стек для наглядной демонстрации некоторых концепций, который также может быть использован для дальнейших экспериментов. Мы настроим пару узлов, как было описано в первой части.

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

В четвертой части этой серии мы рассмотрим, как обеспечить автоматическую миграцию данных при определенных условиях срабатывания.

Практическая часть этой серии будет выполнена с помощью стека docker-compose, поэтому убедитесь, что он установлен в вашей системе, если вы хотите следовать за ним.

Часть 1 - Введение в архитектуру горячий-теплый-холодный-замороженный

Многоуровневая архитектура позволяет лучше организовать ресурсы в соответствии с различными сценариями поиска. Узлы кластера могут быть организованы таким образом, что имеется пул узлов с быстрым аппаратным профилем для работы с данными, которые ищутся чаще всего, а затем различные профили, каждый из которых имеет менее мощный аппаратный профиль, для работы с поисковыми запросами, которые запрашивают данные не так часто. Кроме аппаратного профиля, количество узлов в каждом уровне также может отличаться друг от друга, то есть наиболее часто запрашиваемые данные могут храниться в уровне, который масштабируется на наибольшее количество узлов, и на эти узлы будет устанавливаться самый быстрый профиль.

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

В многоуровневой реализации Elasticsearch уровни называются "горячий", "теплый", "холодный" и "замороженный". И на протяжении своего жизненного цикла данные проходят их в таком порядке. Не обязательно реализовывать все уровни, в большинстве случаев присутствует только горячий уровень, поскольку он служит точкой входа. На диаграмме ниже показан пример многоуровневой архитектуры.

Многоуровневая архитектура Elasticsearch

Мотивация и примеры использования

Существует множество примеров использования данных, которые с течением времени ищутся все реже. Данные временных рядов, такие как журналы, метрики и транзакции в целом, являются хорошим примером данных, которые с течением дней/недель/лет представляют все меньший интерес для пользователей.

Любой случай использования временных рядов является серьезным кандидатом на использование архитектуры "горячий/теплый/холодный/замороженный" и, вероятно, выиграет от нее, но вот несколько примеров:

  • Финансовые транзакции (баланс, кредитная карта, фондовая биржа, ...)
  • Наблюдаемость (метрики, журналы, трассы, ...)
  • История пользователей электронной коммерции (заказы, телеметрия сайта, обращения в службу поддержки, ...)

Реализация многоуровневой архитектуры в Elasticsearch 7.10+

Уровни данных

В Elasticsearch 7.10 появилась концепция ярусов данных, реализованных в виде ролей узлов. С тех пор это правильный и рекомендуемый способ реализации архитектуры hot/warm/cold/frozen.

Ярус данных - это набор узлов, которые имеют некоторые общие характеристики, в основном связанные с аппаратным профилем и доступностью ресурсов. В настоящее время существует пять ролей узлов, представляющих различные уровни данных:

  • Контентный уровень: обычно содержит данные, содержание которых, в отличие от данных временных рядов, будет оставаться относительно постоянным с течением времени, без необходимости переноса документов на другие уровни. Обычно оптимизирован для производительности запросов и в большинстве случаев не требует такого индексирования, как данные временных рядов, например журналы и метрики (хотя это определенно уровень, на котором документы будут индексироваться, просто не с такой скоростью, как в индексе высокочастотных временных рядов). Это необходимый уровень, поскольку через него будут индексироваться системные индексы и любые другие индексы, не являющиеся частью потока данных. Если рассматривать вариант использования электронной коммерции, то список товаров, возможно, будет индексироваться в индексе, хранящемся на этом уровне.
  • Горячий уровень: считается точкой входа для данных временных рядов. Здесь хранятся самые последние проиндексированные и наиболее часто запрашиваемые данные. Узлы, как правило, имеют быстрые аппаратные профили, особенно в части ввода-вывода. Также требуется, чтобы потоки данных индексировали новые данные в этом уровне. Когда пользователи сайта электронной коммерции просматривают историю своих заказов, их, вероятно, больше интересуют заказы за последний месяц или около того, чем, например, заказы за прошлый год.
  • Теплый уровень: когда поиск данных в горячем уровне становится менее частым, их можно переместить в менее дорогой аппаратный профиль. Это зависит от конкретного случая использования, но после определения момента в жизненном цикле данных, когда поиск данных становится реже, можно настроить политику, которая переместит их на теплый уровень. Данные в этом уровне все еще могут обновляться, но реже, чем в горячем уровне. Если рассматривать пример с электронной коммерцией, то пользователю могут быть не очень интересны покупки, совершенные, скажем, не более трех месяцев назад.
  • Холодный уровень: документы, которые, скорее всего, больше не будут обновляться, можно переместить в холодный уровень. Здесь поиск данных по-прежнему возможен, но происходит он еще реже, чем в предыдущем уровне. При переносе данных в этот уровень есть возможность уменьшить и сжать их, чтобы сэкономить дисковое пространство. Кроме того, вместо реплик данные на этом уровне могут полагаться на снимки с возможностью поиска, чтобы обеспечить их отказоустойчивость. История заказов пользователя за прошлый год и ранее может быть кандидатом на размещение в этом уровне, если мы рассматриваем пример электронной коммерции.
  • Замороженный: наконец, холодный уровень - это место, где данные, скорее всего, будут лежать до конца своих дней, это место, где жизненный цикл подходит к концу. В этом случае документы больше не запрашиваются (или это происходит редко). Этот уровень реализован с помощью частично смонтированных индексов, загружающих данные из моментальных снимков, что снижает потребности в хранении и общие затраты на обработку. Для этого уровня рекомендуется использовать выделенные узлы.

Настройка узлов

Чтобы реализовать многоуровневую архитектуру, первым шагом будет настройка роли узла для каждого узла в кластере. Для этого нужно установить атрибут node.role в файле конфигурации elasticsearch.yml. Вот возможные значения ролей узлов данных: data (это общий выделенный узел данных, без реализации ярусов), data_content, data_hot. data_warm, data_cold и data_frozen.

Здесь следует помнить о некоторых моментах:

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

Вот пример того, как можно настроить многоуровневую архитектуру данных с помощью атрибута node.roles в elasticsearch.yml для группы из всего трех узлов:

Другие необходимые атрибуты конфигурации скрыты. Кроме того, здесь основное внимание уделяется уровню данных в кластере, поэтому узлы с другими ролями, например master, также были исключены.

data_node_01:

data_node_02:

data_node_03:

Распределение индексов

Когда вы создаете индекс, Elasticsearch отдает предпочтение распределению его в ярусе контента. Для этого он смотрит на параметр индекса index.routing.allocation.include._tier_preference, который по умолчанию имеет значение data_content. С другой стороны, когда Elasticsearch создает индекс как часть абстракции потока данных, этот индекс будет выделен в горячем ярусе.

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

  • Переопределить автоматическое распределение на основе ярусов, указав параметры фильтрации распределения по осколкам в вашем индексе или в соответствующем шаблоне индекса.
  • Установить index.routing.allocation.include._tier_preference в null, тем самым отказавшись от распределения на основе ярусов по умолчанию (роли ярусов данных будут игнорироваться при распределении).

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

Вот тут-то и пригодится управление жизненным циклом индексов (Index-Lifecycle Management). ILM помогает управлять жизненным циклом индексов, определяя политики, которые будут применять действия при достижении условия, вызывающего фазовый переход. Таким условием может быть возраст индекса, количество хранящихся в нем документов или даже его размер.

Среди множества действий, которые можно настроить для выполнения при наступлении фазового перехода, при реализации многоуровневой архитектуры интерес представляет действие Migrate. Это действие изменит параметр индекса index.routing.allocation.include._tier_preference на значение, соответствующее уровню, который представляет собой фаза жизненного цикла, так что индекс будет перемещен на нужный уровень данных.

Некоторые важные аспекты работы этого действия заключаются в следующем:

  • Это действие автоматически выполняется в теплой и холодной фазах.
  • Естественно, нет смысла выполнять действие Migrate для горячей фазы, поскольку не существует более высокого уровня, чем горячий. Данные индексируются на горячем уровне автоматически.
  • В теплой фазе действие Migrate установит параметр предпочтения уровня индекса как на data_warm (предпочтительно), так и на data_hot (в качестве запасного варианта). Это необходимо, поскольку может не быть узла, настроенного на роль data_warm, но требуется, чтобы хотя бы один узел был настроен на роль data_hot, поэтому в этом случае индекс будет храниться в горячем ярусе.
  • То же самое касается холодной фазы. Поскольку не может быть узла, настроенного ни как холодный, ни как теплый, действие Migrate устанавливает для индекса настройки предпочтения уровней: data_cold (предпочтительно), data_warm (первый запасной вариант, если нет узла с ролью холодного) и data_hot (второй запасной вариант, если нет узла ни с ролью холодного, ни с ролью теплого).
  • Наконец, также для замороженной фазы действие Migrate упорядочивает предпочтительные роли узлов таким образом, чтобы всегда возвращаться к предыдущему уровню (если он есть), а горячий уровень использовать в качестве последнего возможного возврата. Вот предпочтительный порядок уровней для этой фазы: data_frozen, data_cold, data_warm и, наконец, data_hot.

Часть 2 - Построение экспериментальной многоуровневой архитектуры с помощью docker-compose

Чтобы поэкспериментировать с многоуровневой архитектурой, мы можем создать стек docker-compose, который инициализирует три контейнера Elasticsearch и один Kibana. Каждый контейнер Elasticsearch будет сконфигурирован с соответствующими ролями узлов, так что мы сможем смоделировать многоуровневую архитектуру с узлами, играющими разные роли, как показано ниже:

  • es01: master, data_content, data_hot
  • es02: master, data_warm
  • es03: master, data_cold
  • es04: data_frozen

Если у вас не установлен Docker или docker-compose, обратитесь к официальной документации, чтобы узнать, как его получить, чтобы следовать этому руководству. Другой вариант - запустить сервисы вручную, что вполне подойдет для данного примера. Главное - убедиться, что ваши сервисы настроены с учетом соответствующих параметров конфигурации (node.roles).

Сохраните следующую спецификацию docker-compose в файле docker-compose.yml:

Обратите внимание, что для каждого контейнера Elasticsearch задана переменная окружения, которая определяет, какую роль должна играть служба Elasticsearch. Чтобы не поднимать выделенные узлы (сервисы), отвечающие требованиям мастера, все сервисы играют роль данных, а также роль мастера. В реальном сценарии вы, вероятно, захотите иметь выделенные узлы с правами мастера и отдельные узлы данных (которые, безусловно, будут иметь более мощный профиль аппаратных ресурсов для выполнения поисковых запросов).

Этот файл docker-compose основан на файле, предложенном компанией Elastic в ее официальной документации. Кроме ролей узлов, в него был добавлен только том для хранения снимков, который затем был включен и смонтирован в каждом сервисе Elasticsearch, а также параметр path.repo, указывающий на него. Это нам понадобится для получения снимков и их поиска на нашем замороженном уровне.

Чтобы поднять стек, нужно просто находиться в той же директории, что и файл docker-compose.yml, и выполнить следующую команду:

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

Вот схема, показывающая, как выглядит наш кластер:

Построение экспериментальной многоуровневой архитектуры с помощью docker-composeЕще один дополнительный шаг, который мы должны сделать, - это изменить права собственности на каталог моментальных снимков. Docker-compose смонтирует его от имени root, но поскольку сервис Elasticsearch работает от имени пользователя elasticsearch, у него не будет доступа к записи в этот каталог. Поэтому каждый раз при первом запуске стека вам придется выполнять следующую команду:

Если все прошло нормально, вы сможете получить доступ к экземпляру Kibana, перейдя по следующему url в браузере: http://localhost:5601

Настройка моментальных снимков с возможностью поиска и репозитория

Когда наш стек создан и работает, мы почти готовы к экспериментам с многоуровневой архитектурой. Но сначала нам нужно настроить пару вещей. Итак, теперь вы можете перейти к Kibana, зайти в приложение Dev Tools, и мы быстро закончим с этим.

Первое, о чем нам нужно позаботиться, - это запуск пробной лицензии, которая необходима, поскольку мы собираемся использовать функцию поиска по снимкам в замороженном уровне нашей многоуровневой архитектуры, а она не включена в базовую лицензию. Выполните следующую команду, чтобы начать пробный период в 30 дней, который даст вам доступ ко всем премиум-функциям Elasticsearch:

При желании вы можете выполнить ту же команду с помощью curl из терминала:

Последнее, что нам нужно сделать перед погружением в работу, - это зарегистрировать хранилище моментальных снимков, указывающее на path.repo, которое мы настроили для наших узлов. Выполните следующую команду:

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

Часть 3 - Демонстрация работы многоуровневой архитектуры (перенос данных вручную)

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

Вы можете убедиться, что все наши узлы правильно настроили свои роли, выполнив следующую команду в Dev Tools:

Вы получите ответ со списком наших узлов и всеми ролями, которые каждый из них играет в нашем кластере:

  • m: главный узел
  • s: уровень контента
  • h: горячий уровень данных
  • w: теплый ярус данных
  • c: холодный уровень данных
  • f: уровень замороженных данных

Перенос данных по уровням вручную (сложный путь)

Здесь мы воспользуемся фильтрацией распределения шардов, чтобы повлиять на то, где (то есть в каких узлах) кластер должен распределять наши индексы.

Фильтрация распределения осколков работает путем установки атрибутов индекса, которые определяют стратегию маршрутизации, которой Elasticsearch будет следовать при распределении осколков. В двух словах, вы определяете атрибуты узла в файле конфигурации elasticsearch.yml для каждого узла в вашем кластере, а затем все, что вам нужно сделать, это настроить политику маршрутизации ваших индексов, вручную или через шаблон индекса, чтобы направлять шарды индекса на узлы, которые включают/исключают/требуют определенного значения для этого атрибута.

Начиная с Elasticsearch 7.10 мы можем определять уровни данных как пользовательские роли узлов, что мы и сделали для каждого узла (сервиса) в нашем стеке docker-compose. Теперь мы можем задать политику маршрутизации, которая будет использовать эти значения для гипотетического индекса. Для этого мы устанавливаем специальный атрибут index.routing.allocation.include._tier_preference. Это внутренний атрибут, который Elasticsearch будет учитывать при принятии решения о распределении индексов. По умолчанию его значение установлено на data_content для индексов в целом. Если индекс был создан через поток данных, то по умолчанию для этого атрибута установлено значение data_hot. Возможными значениями этого атрибута являются либо имя роли уровня данных (data_content, data_hot, data_warm, data_cold или data_frozen), либо null, если вы хотите, чтобы Elasticsearch полностью игнорировал роли уровня данных при распределении индексов.

Учитывая это, давайте немного поэкспериментируем. Мы смоделируем сценарий, в котором история заказов пользователей гипотетического сайта электронной коммерции хранится в индексах Elasticsearch. Каждый день мы создаем новый индекс для хранения заказов за этот день. Мы хотим, чтобы наши индексы мигрировали с яруса на ярус в соответствии со следующей политикой:

  • Заказы, размещенные сегодня: сохраните их в горячем ярусе
  • Заказы, размещенные за последние 30 дней (но не сегодня): переместите их в теплый ярус
  • Заказы, размещенные за последние 365 дней (до этого месяца): переместите их на холодный уровень
  • Заказы старше 365 дней: снимок, удаление и перемещение в замороженный ярус

В данном примере мы считаем, что текущая дата - 15 дккабря 2023 года.

Чтобы упростить задачу, мы определим шаблон индекса, который будет применяться к каждому индексу заказа. Он отображает только пару полей и устанавливает количество шардов и реплик на 1 и 0 соответственно, чтобы у нас не было НЕЗАВИСИМЫХ шардов, поскольку архитектура нашего примера определенно не может обеспечить высокую доступность (но это не страшно, поскольку она предназначена только для учебной песочницы, а не для производственной среды). Выполните следующую команду, чтобы создать шаблон индекса:

Теперь мы можем создать несколько индексов, которые будут представлять различные моменты времени в нашей истории заказов электронной коммерции. Выполните все приведенные ниже команды, чтобы создать индексы, которые нам понадобятся для дальнейшей работы:

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

Прежде чем двигаться дальше, давайте проверим, где Elasticsearch решил выделить шарды для этих четырех индексов:

Вы видите, что все они были распределены на узел es01, как и должно быть, потому что именно этот узел мы настроили на работу в качестве уровня контента, а для индексов, которые не являются частью потоков данных, этот уровень данных является предпочтительным для Elasticsearch для распределения индексов.

Пока все хорошо, но теперь давайте применим нашу определенную многоуровневую политику распределения. Здесь мы делаем это вручную, чтобы объяснить, как это работает, но в следующем разделе мы рассмотрим, как сделать так, чтобы Elasticsearch позаботился обо всем этом автоматически.

Миграция наших индексов на соответствующие уровни данных - это просто вопрос настройки маршрутизации индекса соответствующим образом. Вы можете представить, что у вас есть фоновое задание, которое будет выполнять эту задачу ежедневно. Это задание будет проверять список индексов, а затем устанавливать маршрутизацию распределения по шардам в соответствии с датой, присутствующей в имени индекса, и текущей датой. В итоге это задание выполнило бы следующие команды для реорганизации индексов в нашей многоуровневой архитектуре:

Обратите внимание, что мы не отдали команду на перемещение индекса orders-20200601 (прошлогодние заказы) на замороженный уровень. Мы сделаем это в ближайшее время. Давайте сначала проверим распределение шардов после обработки этих команд кластером, чтобы убедиться, что все они были перемещены на узлы с ожидаемыми ролями:

orders-20231215, orders-20231116 и orders-20231215 были перемещены соответственно в узлы es01, es02 и es03, которые соответственно представляют горячий, теплый и холодный ярусы данных, как мы и предполагали.

Итак, что же происходит с индексом, представляющим заказы, размещенные в прошлом году? Политика распределения, которую мы определили, гласит, что его следует переместить на "замороженный" уровень, поскольку он содержит данные, которые пользователь редко хочет запрашивать. Давайте посмотрим, что произойдет, если мы попытаемся изменить настройки распределения маршрутизации этого индекса, чтобы переместить осколки на наш замороженный уровень:

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

Elasticsearch 7.10 представил снимки с возможностью поиска в рамках подписки Enterprise. Снимки с возможностью поиска позволяют хранить менее часто запрашиваемые данные в недорогом объектном хранилище (например, AWS S3) в виде снимков, которые будут возвращаться в сеть только при необходимости.

Для поиска по моментальным снимкам сначала необходимо смонтировать их в виде индексов. Это можно сделать двумя способами:

  • Полностью смонтированный индекс: будет загружена полная копия индекса моментального снимка. Этот вариант ILM использует для горячей и холодной фаз.
  • Частично смонтированный индекс: загружаются только части моментального снимка индекса в локальный кэш, который совместно используется узлами, работающими в замороженном уровне. Если для поиска требуются данные, которых нет в кэше, они будут извлечены из моментального снимка. Этот вариант ILM использует для замороженной фазы.

Это возможность смоделировать то, что произошло бы в реальном сценарии. Вероятно, у вас есть политика моментальных снимков, так что к этому моменту этот индекс был бы включен в моментальный снимок, хранящийся в нашем репозитории. Давайте сделаем это вручную:

Теперь, когда индекс надежно сохранен в нашем хранилище, мы можем избавиться от него (как это, вероятно, произошло бы в реальной политике снимков и восстановления):

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

Теперь давайте в последний раз проверим распределение наших индексов:

Наконец, все наши индексы распределяются в соответствии с нашей политикой распределения:

  • orders-20211020 (сегодняшние заказы) → es01 → горячий уровень данных
  • orders-20211010 (заказы этого месяца) → es02 → теплый уровень данных
  • orders-20210601 (заказы этого года) → es03 → холодный уровень данных
  • orders-20200601 (заказы прошлого года и ранее) → es04 → замороженный уровень данных

Итак, чтобы вручную применить политику распределения, вот какие шаги мы предприняли:

  • Мы создали шаблон индекса, чтобы задать некоторые общие характеристики наших индексов.
  • Затем мы создали четыре индекса, представляющих разные моменты времени.
  • Для трех из них мы смогли распределить данные по соответствующим уровням "горячий", "теплый" и "холодный".
  • Для индекса, представляющего данные за прошлый год, мы сделали снимок и удалили его.
  • И наконец, мы смонтировали индекс из снимка в наш замороженный уровень.

В следующей части мы рассмотрим, как автоматизировать весь этот процесс с помощью функции управления жизненным циклом индексов Elasticsearch.

Часть 4 - Автоматическое перемещение данных по уровням

Этот подход в значительной степени основан на управлении жизненным циклом индексов (Index Lifecycle Management, ILM). ILM организует жизненный цикл ваших индексов в пять фаз и позволяет вам настраивать как критерии перехода между фазами, так и действия, которые будут выполняться, когда индекс достигнет этой фазы.

В настоящее время вы можете настроить политику ILM, состоящую из следующих пяти фаз:

  • Горячий: индекс активно обновляется и запрашивается.
  • Теплый: Индекс больше не обновляется, но все еще запрашивается.
  • Холодный: Индекс больше не обновляется и запрашивается нечасто. Информация по-прежнему должна быть доступна для поиска, но ничего страшного, если запросы будут выполняться медленнее.
  • Замороженный: Индекс больше не обновляется и запрашивается редко. Информация по-прежнему должна быть доступна для поиска, но ничего страшного, если запросы будут выполняться крайне медленно.
  • Удалить: Индекс больше не нужен, и его можно смело удалять.

Вы уже видите, что ILM - это то, что нам нужно для управления потоком данных от уровня к уровню. Для каждой фазы вы можете определить и настроить набор действий, которые будут выполняться. Вы можете взглянуть на список ниже, чтобы увидеть, какие действия разрешены в каждой фазе, а затем перейти по ссылкам на официальную документацию, чтобы узнать больше о каждом действии.

  • Горячие: установить приоритет, отменить, перевернуть, только для чтения, уменьшить, принудительно объединить, моментальный снимок с возможностью поиска
  • Теплые: Установить приоритет, Снять, Только чтение, Распределить, Перенести, Сократить, Принудительное слияние
  • Холодные: Установить приоритет, Снять, Только чтение, Распределить, Мигрировать, Снимок с возможностью поиска, Заморозить
  • Заморозить: Снимок с возможностью поиска
  • Удалить: Подождать моментальный снимок, Удалить

Для целей данного руководства нас особенно интересуют действия Rollover, Migrate и Searchable Snapshot. В двух словах, действие Rollover будет создавать новый индекс при достижении определенного условия (возраст, количество документов, размер). Действие Searchable Snapshot гарантирует, что индексы, хранящиеся в моментальных снимках, будут монтироваться по мере необходимости (это премиум-функция, требующая подписки) и возвращаться в сеть для решения запросов.

Теперь действие Migrate - то, что нас действительно интересует. Это действие перемещает индексы на уровень, соответствующий данной фазе, устанавливая соответствующим образом предпочтение index.routing.allocation.include._tier_preference. ILM автоматически выполняет действие Migrate в теплой и холодной фазах, если в действии Allocate не указаны параметры распределения. Некоторые другие аспекты действия Migrate, о которых вам следует знать:

  • Если в холодной фазе определено действие Searchable Snapshot, действие Migrate не будет введено автоматически, поскольку индекс будет смонтирован непосредственно на целевом уровне с использованием той же инфраструктуры index.routing.allocation.include._tier_preference, которую настраивает действие migrate.
  • В теплой фазе параметр index.routing.allocation.include._tier_preference индекса устанавливается на data_warm и data_hot, что гарантирует, что индекс будет выделен на одном из этих уровней с соблюдением этого порядка старшинства.
  • В холодной фазе параметр index.routing.allocation.include._tier_preference индекса устанавливается в значения data_cold, data_warm и data_hot, что гарантирует, что индекс будет выделен в одном из этих уровней с соблюдением этого порядка старшинства.
  • Это не разрешается на этапе заморозки, поскольку на этом этапе будет смонтирован снимок и для параметра index.routing.allocation.include._tier_preference установлено значение data_frozen, data_cold, data_warm и data_hot и будет предпринята попытка выделить индекс на одном из этих уровней с соблюдением этого порядка старшинства.

Наша политика будет строго определяться возрастом наших индексов. Мы хотим, чтобы они мигрировали с яруса на ярус по мере того, как они становятся все старше и старше. Согласно предложенной нами политике, индекс должен переходить из горячей стадии в теплую через 1 день, из теплой в холодную через 30 дней и из холодной в замороженную через 365 дней. Когда индекс достигнет стадии заморозки, он также может быть удален (поскольку его все еще можно будет найти, смонтировав из моментальных снимков). Чтобы было интереснее, давайте добавим действие rollover в горячую фазу нашей политики ILM, чтобы каждый час создавался новый индекс для записи.

Для демонстрации рассмотрим следующие временные адаптации (чтобы мы могли видеть, что все происходит менее чем за 5 минут, а не за 365 дней):

  • Переход каждый час → каждые 30 секунд
  • Переход от горячего к теплому через 1 день → через 1 минуту
  • Мигрировать из теплого в холодный через 30 дней → через 2 минуты
  • Миграция из холодного состояния в замороженное и последующее удаление через 365 дней → через 3 минуты

Последняя часть головоломки заключается в том, что нам понадобятся снимки, чтобы иметь замороженный уровень, на котором можно искать снимки данных. Мы можем легко делать снимки вручную, как мы это делали в предыдущем разделе, но здесь мы пытаемся все автоматизировать. Elasticsearch предоставляет возможность делать снимки автоматически, настраивая политики Snapshot Lifecycle Management. Сделать это очень просто, но, к сожалению, мы не можем запланировать выполнение политики SLM чаще, чем через 15 минут, что не подходит для нашего тестового сценария. Мы решим эту проблему позже, а сейчас просто выполните следующую команду, чтобы у нас была политика моментальных снимков, которая будет использоваться в фазе удаления нашей политики ILM:

Учитывая все вышесказанное, мы начнем с создания политики ILM для управления индексами заказов.

Обратите внимание, что мы не включили действие Migrate в наши фазы, но помните, что оно автоматически вводится ILM в теплой и холодной фазах.

По умолчанию ILM проверяет каждые 10 минут, есть ли какое-либо действие для выполнения. В нашем примере мы должны были использовать очень маленькие интервалы (секунды, минуты), чтобы мы могли наблюдать, как Elasticsearch перемещает наши индексы по фазам их жизненного цикла. В связи с этим нам также придется настроить параметр переходного кластера, уменьшающий интервал, через который ILM проверяет необходимость выполнения действий. Прежде чем двигаться дальше, выполните следующую команду:

Теперь, когда мы настроили ILM-часть нашей демонстрации, как нам её использовать? Вы можете назначить политику ILM индексу, определив атрибут index.lifecycle.name как имя политики ILM в настройках индекса:

Мы хотим, чтобы эта политика применялась к каждому создаваемому индексу заказа, но не хотим делать это вручную. Правильным способом решения этой проблемы является использование шаблона индекса. С помощью шаблона индекса вы можете определить некоторые общие настройки и сопоставления, которые должны применяться к каждому создаваемому индексу, и чтобы его название соответствовало шаблону, определенному в шаблоне. Это именно то, что нам нужно, потому что если вы посмотрите на горячую фазу нашей политики ILM, то увидите, что она будет выполнять действие Rollover. Это действие создает новый индекс записи каждый раз, когда достигается определенное условие (возраст, количество документов или размер). Этот новый индекс должен иметь такие характеристики, как политика жизненного цикла, и его отображения должны быть установлены так же, как и у других индексов, созданных ранее. Поскольку имя вновь созданного индекса будет соответствовать шаблону (orders-*), легко создать шаблон индекса, который обеспечит наличие всех общих характеристик в каждом индексе.

Для создания шаблона индекса нам сначала нужно создать компоненты шаблона, а затем использовать их при создании шаблона. Выполните приведенные ниже команды, чтобы создать компоненты настроек и сопоставлений:

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

Мы готовы к работе. У нас есть политика жизненного цикла индекса, созданная и настроенная в шаблоне индекса, который будет применяться к каждому индексу с именем, следующим за шаблоном orders*. Пора, наконец, создать наш индекс и проверить, работает ли вся эта схема.

Здесь у нас есть два варианта. Первый - создать индекс вручную с именем, соответствующим шаблону ^.*-\d+$ (например, orders-000001), а затем создать псевдоним, указывающий на него (orders → orders-000001). Таким образом, все ваши приложения будут использовать только псевдоним, а политика ILM будет отвечать за развертывание нижних индексов.

Второй вариант - использовать потоки данных, которые появились в Elasticsearch 7.9 и упрощают реализацию этого паттерна, когда у вас есть данные только для приложения, которые будут распределены по нескольким индексам и должны быть доступны клиентам в виде одного именованного ресурса. Когда вы создаете поток данных, Elasticsearch фактически создает скрытый индекс для хранения документов.

Мы выберем второй вариант. Помните, что у нас уже есть политика ILM, и она выполняется Elasticsearch каждые 15 секунд. Как только мы создадим наш поток данных, все начнет двигаться быстро. Поскольку мы хотим проследить за всеми шагами, давайте оставим терминал открытым, наблюдая за тем, что происходит с нашими индексами:

Теперь, наконец, создайте поток данных для индекса заказов.

Вот способ решения проблемы для нашей политики SLM. Мы не можем ждать 15 минут, пока будет сделан снимок, поэтому мы можем сделать его вручную, как только будет создан первый индекс в потоке данных.

В более реалистичном сценарии в этом не было бы необходимости, мы бы позволили политике SLM позаботиться о снимках за нас, но поскольку наши фиктивные ограничения на старение политики ILM выражаются в минутах (и даже секундах), нам придется пойти этим путем. Нам понадобятся моментальные снимки, иначе ILM не сможет перевести наши индексы в замороженную фазу, поскольку она зависит от этого.

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

Теперь мы наконец-то можем посмотреть в терминале, как Elasticsearch применяет нашу политику ILM. Вы должны увидеть следующие события:

Заключение

Чтобы автоматически применять нашу политику распределения, мы:

  • Создали политику Snapshot Lifecycle Management (SLM), которая автоматически создает снимок наших данных по расписанию.
  • Создали политику управления жизненным циклом индекса (ILM), которая будет выполнять определенные действия для каждой из пяти фаз, которые наши индексы будут проходить на протяжении всего своего существования, от создания до удаления.
  • Определили шаблон индекса, который, помимо прочего, устанавливает нашу политику ILM в качестве политики, которая будет использоваться для управления жизненным циклом всех создаваемых индексов с именем, соответствующим шаблону, определенному в шаблоне индекса, так что нам не нужно делать это вручную.
  • Наконец, мы создали потоки данных и наблюдали за тем, как резервные индексы переносятся, мигрируют, делают снимки и удаляются, поскольку наша политика ILM выполняла заданные действия каждый раз, когда определяла, что возраст индекса достиг настроенного порога.
Понравилась статья? Поделиться с друзьями:
Добавить комментарий