Устранение распространенных ошибок выделения сегментов Elasticsearch

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

Устранение распространенных ошибок выделения сегментов Elasticsearch

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

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

Правильно читайте сигнал здоровья

Начните с здоровья кластера:

GET /_cluster/health?pretty

Важные поля: status, active_primary_shards, active_shards, relocating_shards, initializing_shards, unassigned_shards и delayed_unassigned_shards.

Желтый означает, что все первичные сегменты назначены, но одна или несколько реплик — нет. Ваши данные все еще должны быть доступны, но избыточность снижена.

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

Если relocating_shards или initializing_shards не равны нулю, кластер, возможно, уже восстанавливается. Не прерывайте нормальное восстановление только потому, что цвет временно желтый.

Перечислите неназначенные сегменты

Используйте _cat/shards, чтобы увидеть точную проблему:

GET /_cat/shards?v&h=index,shard,prirep,state,node,unassigned.reason&s=state,index

Ищите UNASSIGNED. Столбец prirep показывает, является ли сегмент первичным (p) или репликой (r). Столбец unassigned.reason дает краткую причину, такую как NODE_LEFT, INDEX_CREATED, CLUSTER_RECOVERED или ALLOCATION_FAILED.

Для большого кластера сузьте поиск:

GET /_cat/shards/logs-*?v&h=index,shard,prirep,state,node,unassigned.reason

Как только вы получите индекс, номер сегмента и флаг первичности/реплики, запросите у Elasticsearch реальное объяснение.

Используйте API объяснения выделения

Для любого текущего неназначенного сегмента:

GET /_cluster/allocation/explain
{}

Для конкретного сегмента:

GET /_cluster/allocation/explain
{
  "index": "logs-2026.05.24",
  "shard": 0,
  "primary": false
}

Читайте can_allocate, allocate_explanation, unassigned_info и node_allocation_decisions. Решения узлов особенно полезны, потому что они показывают, почему каждый узел был отклонен. Распространенные решающие факторы включают пороги диска, правила одного сегмента, фильтры выделения, правила осведомленности и ограничения общего количества сегментов на узел.

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

Причина 1: недостаточно подходящих узлов

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

Проверьте настройки реплик:

GET /my-index/_settings?filter_path=*.settings.index.number_of_replicas

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

PUT /my-index/_settings
{
  "index": {
    "number_of_replicas": 0
  }
}

Для продакшена лучшим ответом обычно является добавление подходящих узлов данных или корректировка нереалистичного количества реплик. Уменьшение реплик снижает избыточность.

Причина 2: дисковые водяные знаки

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

Проверьте выделение и использование диска:

GET /_cat/allocation?v
GET /_cat/nodes?v&h=name,ip,disk.used_percent,disk.avail,heap.percent,ram.percent,node.role

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

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

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

После освобождения места от события стадии затопления проверьте блокировку только для чтения:

GET /my-index/_settings?filter_path=*.settings.index.blocks.write,*.settings.index.blocks.read_only_allow_delete

Удалите блокировку только после устранения давления на диск:

PUT /my-index/_settings
{
  "index.blocks.read_only_allow_delete": null
}

Причина 3: выделение отключено после обслуживания

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

Проверьте настройки кластера:

GET /_cluster/settings?include_defaults=true&pretty

Ищите cluster.routing.allocation.enable. Значения включают all, primaries, new_primaries и none. Если это none, реплики и, возможно, другие перемещения сегментов не будут выделяться нормально.

Включите выделение снова:

PUT /_cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.enable": "all"
  }
}

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

Причина 4: ограничительные фильтры выделения

Фильтры на уровне индекса могут привязать индекс к определенным узлам:

GET /my-index/_settings?filter_path=*.settings.index.routing.allocation.*

Фильтры на уровне кластера могут исключать узлы из выделения:

GET /_cluster/settings?include_defaults=true&filter_path=**.cluster.routing.allocation.*

Атрибуты узлов также важны:

GET /_cat/nodeattrs?v

Типичный сбой выглядит так: индекс требует box_type: hot, но горячие узлы были заменены, и новые узлы не имеют node.attr.box_type: hot. Elasticsearch точно следует правилу; правило теперь неверно.

Чтобы удалить чрезмерно ограничительные фильтры индекса:

PUT /my-index/_settings
{
  "index.routing.allocation.require.box_type": null,
  "index.routing.allocation.include.box_type": null,
  "index.routing.allocation.exclude.box_type": null
}

Используйте точные имена настроек, присутствующие в вашем индексе. Не удаляйте вслепую правила выделения, если они кодируют реальные требования зоны или уровня.

Причина 5: задержанное выделение после ухода узла

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

Проверьте задержанные сегменты:

GET /_cluster/health?pretty

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

GET /my-index/_settings?filter_path=*.settings.index.unassigned.node_left.delayed_timeout

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

Причина 6: слишком много сегментов на узле

index.routing.allocation.total_shards_per_node может ограничить, сколько сегментов от одного индекса может находиться на одном узле. Также могут применяться ограничения на уровне кластера. Эти настройки полезны, но они могут блокировать выделение в небольших кластерах.

Проверьте настройки индекса:

GET /my-index/_settings?filter_path=*.settings.index.routing.allocation.total_shards_per_node

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

Причина 7: нет действительной копии первичного сегмента

Это страшный случай. Объяснение выделения может сообщить, что нет действительной копии сегмента для первичного. Возможно, единственный узел с первичным сегментом исчез. Возможно, диск вышел из строя. Возможно, данные сегмента повреждены.

Сначала попробуйте восстановить отсутствующий узел, если ожидается, что он вернется. Проверьте системные журналы, журналы Elasticsearch, состояние диска и сетевое подключение. Если существует действительная реплика, Elasticsearch обычно должен повысить ее.

Если нет действительной копии, восстановите из снимка:

POST /_snapshot/my_repository/snapshot_name/_restore
{
  "indices": "affected-index"
}

Если данные можно перестроить из исходной системы и вы согласны потерять содержимое сегмента, доступен allocate_empty_primary, но это операция потери данных:

POST /_cluster/reroute
{
  "commands": [
    {
      "allocate_empty_primary": {
        "index": "affected-index",
        "shard": 0,
        "node": "target-node",
        "accept_data_loss": true
      }
    }
  ]
}

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

Следите за восстановлением

После внесения изменений следите за прогрессом:

GET /_cat/recovery?v&active_only=true
GET /_cat/shards?v&h=index,shard,prirep,state,node,unassigned.reason
GET /_cluster/health?pretty

Большие сегменты требуют времени. Если счетчики байтов движутся в _cat/recovery, кластер работает. Если ничего не меняется, проверьте объяснение выделения снова. Решение Elasticsearch могло измениться после вашего первого исправления, выявив следующий блокирующий фактор.

Профилактика, которая действительно помогает

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

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

Поддерживайте актуальность снимков и тестируйте восстановление. Снимок, который вы никогда не восстанавливали, — это всего лишь надежда.

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

Документируйте фильтры выделения и атрибуты узлов. Через шесть месяцев кто-то заменит узел и забудет атрибут, который делал индекс выделяемым.

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

Полевой чек-лист для инцидентов

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

Выполните:

GET /_cluster/health?pretty
GET /_cat/nodes?v&h=name,ip,roles,master,disk.used_percent,heap.percent,ram.percent
GET /_cat/shards?v&h=index,shard,prirep,state,node,unassigned.reason&s=state,index
GET /_cat/allocation?v
GET /_cat/recovery?v&active_only=true
GET /_cluster/settings?include_defaults=true&pretty

Затем выполните объяснение выделения для одного представительного неназначенного сегмента. Если их много, сгруппируйте их по причине. Десять неназначенных реплик, заблокированных дисковыми водяными знаками, — это одна проблема. Три первичных сегмента с no_valid_shard_copy — это другая проблема.

Запишите, можно ли перестроить затронутые данные. Журналы из вышестоящей очереди, метрики от агентов и производные поисковые индексы могут быть восстановлены из исходных систем. Созданный пользователями контент или записи соответствия могут быть невосстановимы. Команды восстановления должны следовать этой бизнес-реальности.

Когда ждать и когда действовать

Ждите, когда восстановление активно прогрессирует, отсутствующий узел ожидается скоро, или задержанное выделение делает именно то, для чего вы его настроили. Вы можете проверить прогресс с помощью _cat/recovery; движущиеся счетчики байтов и файлов — хорошие признаки.

Действуйте, когда объяснение выделения показывает постоянный блокирующий фактор: нет подходящих узлов, дисковые водяные знаки на каждом узле, выделение отключено, отсутствуют атрибуты узлов или нет действительной копии сегмента. Ожидание не исправит правило, которое отклоняет каждый узел.

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

Избегайте замедления восстановления

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

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

Следите за горячими узлами. Выделение может технически быть успешным, но при этом размещать слишком много работы на одном узле из-за размеров сегментов, правил уровня или неравномерного использования диска. Используйте _cat/allocation, статистику узлов и вашу систему мониторинга, чтобы подтвердить, что кластер сбалансирован после устранения непосредственного сбоя.

Исправления после инцидента

Большинство инцидентов с выделением сегментов имеют историю профилактики. Инциденты с дисковыми водяными знаками указывают на хранение, ILM или планирование емкости. Инциденты с фильтрами выделения указывают на отсутствие документации в runbook. Инциденты с отсутствием действительной копии указывают на снимки и воспроизведение из вышестоящих систем. Медленное восстановление указывает на размер сегментов и оборудование.

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

Особый случай: закрытые и скрытые индексы

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

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

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