Полное руководство по управлению индексами Elasticsearch через API-команды

Освойте управление индексами Elasticsearch с помощью этого полного руководства по API-командам. Узнайте, как тщательно создавать индексы с пользовательскими маппингами и настройками с помощью `PUT`, всесторонне просматривать их конфигурации и детали с помощью `GET`, а также безопасно удалять ненужные индексы с помощью `DELETE`. Эта статья содержит практические примеры, лучшие практики и важные предупреждения, позволяя вам эффективно управлять жизненным циклом ваших данных в Elasticsearch для достижения оптимальной производительности и управления ресурсами.

Полное руководство по управлению индексами Elasticsearch через API-команды

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

Индекс Elasticsearch — это не просто корзина для JSON-документов. У него есть маппинги, настройки, алиасы, количество шардов, количество реплик, анализаторы и поведение жизненного цикла. Вам не нужно запоминать каждый API, чтобы хорошо им управлять, но вам нужна тщательная рутина: создавать индексы намеренно, проверять, что Elasticsearch на самом деле создал, обновлять только те настройки, которые можно безопасно изменить, и удалять с защитными механизмами.

Примеры ниже используют стиль запросов Kibana Dev Tools. Если вы предпочитаете curl, те же пути и JSON-тела применимы к http://host:9200.

Что содержит индекс

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

Три части, которые вы будете проверять чаще всего:

  • settings, такие как number_of_shards, number_of_replicas, refresh_interval и конфигурация анализа.
  • mappings, которые определяют типы полей, такие как keyword, text, date, long, double, boolean, ip и вложенные/объектные поля.
  • aliases, которые позволяют приложениям использовать стабильное имя, пока вы меняете реальный базовый индекс за ним.

Хороший рабочий процесс с API индексов начинается до индексации первого документа. Динамический маппинг полезен для исследования, но производственные индексы заслуживают явных маппингов для важных полей. Если user_id случайно отображается как text, агрегации и точные фильтры станут неудобными. Если временная метка отображается как text, запросы по временному диапазону не будут вести себя как запросы по дате. Эти ошибки исправимы, но обычно путем создания нового индекса и переиндексации.

Создание простого индекса

Самый маленький запрос на создание:

PUT /my_first_index

Elasticsearch возвращает подтверждение, если индекс был создан:

{
  "acknowledged": true,
  "shards_acknowledged": true,
  "index": "my_first_index"
}

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

Создание индекса с маппингами и настройками

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

PUT /products-v1
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1,
    "refresh_interval": "5s"
  },
  "mappings": {
    "dynamic": "strict",
    "properties": {
      "product_id": { "type": "keyword" },
      "sku": { "type": "keyword" },
      "name": {
        "type": "text",
        "fields": {
          "raw": { "type": "keyword", "ignore_above": 256 }
        }
      },
      "description": { "type": "text" },
      "category": { "type": "keyword" },
      "price": { "type": "scaled_float", "scaling_factor": 100 },
      "stock": { "type": "integer" },
      "available": { "type": "boolean" },
      "created_at": { "type": "date" },
      "updated_at": { "type": "date" }
    }
  }
}

Некоторые решения здесь сделаны намеренно. product_id, sku и category имеют тип keyword, потому что вы обычно фильтруете, агрегируете или связываете поведение приложения с точными значениями. name имеет тип text для поиска, с подполем name.raw типа keyword для сортировки и точного сопоставления. price использует scaled_float, чтобы цены могли храниться как масштабированные значения в центах вместо двоичных приближений с плавающей точкой. dynamic: strict отклоняет неизвестные поля, что полезно, когда плохие данные от производителя должны вызывать громкую ошибку.

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

Проверка индекса после создания

Всегда проверяйте, что Elasticsearch принял:

GET /products-v1

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

GET /products-v1/_mapping
GET /products-v1/_settings
GET /products-v1/_alias

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

GET /_cat/indices/products-*?v

Полезные столбцы включают health, status, количество первичных шардов, количество реплик, количество документов, количество удаленных документов и размер хранилища. API _cat предназначены для людей. Используйте JSON API для скриптов.

Если вы проверяете, правильно ли отображено поле, используйте:

GET /products-v1/_mapping/field/price
GET /products-v1/_mapping/field/name.raw

Это быстрее читается, чем прокрутка большого маппинга.

Безопасное обновление настроек индекса

Некоторые настройки являются динамическими. Количество реплик — распространенный случай:

PUT /products-v1/_settings
{
  "index": {
    "number_of_replicas": 2
  }
}

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

refresh_interval — еще одна настройка, которую вы можете изменить во время массовых загрузок:

PUT /products-v1/_settings
{
  "index": {
    "refresh_interval": "30s"
  }
}

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

POST /products-v1/_refresh

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

Изменение маппингов без самообмана

Вы можете добавлять новые поля в маппинг:

PUT /products-v1/_mapping
{
  "properties": {
    "brand": { "type": "keyword" }
  }
}

Вы обычно не можете изменить тип существующего поля на месте. Если price уже имеет тип text, это не превратит старые значения в полезное числовое поле. Создайте новый индекс с правильным маппингом и выполните переиндексацию:

POST /_reindex
{
  "source": { "index": "products-v1" },
  "dest": { "index": "products-v2" }
}

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

Использование алиасов для более безопасного доступа приложений

Направьте алиас на первую версию:

POST /_aliases
{
  "actions": [
    { "add": { "index": "products-v1", "alias": "products" } }
  ]
}

Ваше приложение читает из products. Позже создайте products-v2, переиндексируйте данные, протестируйте их, затем атомарно замените алиас:

POST /_aliases
{
  "actions": [
    { "remove": { "index": "products-v1", "alias": "products" } },
    { "add": { "index": "products-v2", "alias": "products" } }
  ]
}

Для систем с интенсивной записью используйте алиас для записи и явно укажите is_write_index:

POST /_aliases
{
  "actions": [
    { "add": { "index": "products-v2", "alias": "products-write", "is_write_index": true } }
  ]
}

Алиасы — один из самых простых способов избежать жесткого кодирования версий индексов в сервисах.

Аккуратное перечисление и поиск имен индексов

Для проверки нескольких индексов:

GET /products-v1,products-v2/_settings
GET /products-*/_mapping
GET /_cat/indices/products-*?v&s=index

Будьте осторожны с широкими подстановочными знаками в больших кластерах. GET /* или GET /_all могут дать огромный ответ и могут включать системные или скрытые индексы в зависимости от версии, настроек и параметров запроса. Предпочитайте узкий шаблон, такой как logs-prod-* или products-*.

Чтобы проверить, существует ли индекс из скрипта, используйте HEAD:

HEAD /products-v1

200 означает, что он существует. 404 означает, что его нет.

Удаление индексов с защитными механизмами

Удаление просто:

DELETE /products-v1

Операционный риск заключается не в синтаксисе. Риск заключается в удалении не того индекса или удалении до завершения снимка.

Перед удалением перечислите, чему именно соответствует шаблон:

GET /_cat/indices/products-old-*?v&s=index

Если вывод правильный и данные восстанавливаемы или больше не нужны, удалите тот же шаблон:

DELETE /products-old-*

Многие кластеры ограничивают разрушительные операции с подстановочными знаками с помощью action.destructive_requires_name. Это хорошая настройка безопасности, поскольку она блокирует широкие удаления, такие как DELETE /*, если не требуются явные имена. Даже с такой защитой относитесь к операциям удаления как к производственным изменениям: подтвердите шаблон индекса, подтвердите снимки и подтвердите, что у вызывающего есть правильные разрешения.

Предпочитайте политики жизненного цикла для временных рядов

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

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

Простая ежедневная рутина

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

Проверьте здоровье:

GET /_cluster/health

Перечислите индексы по шаблону:

GET /_cat/indices/logs-*?v&s=store.size:desc

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

GET /logs-prod-2026.05.24/_settings

Проверьте маппинги перед добавлением новых полей из релиза приложения:

GET /logs-prod-2026.05.24/_mapping

Подтвердите алиасы до и после миграции:

GET /_cat/aliases/products*?v

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

Распространенные ошибки, которых следует избегать

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

Не меняйте маппинги в уме, полагая, что Elasticsearch согласен. Проверьте фактический маппинг.

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

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

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

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

Шаблоны важнее разовых созданий

Если вы создаете один и тот же тип индекса многократно, не полагайтесь на ручные вызовы PUT /index-name. Используйте шаблон индекса или составные шаблоны, чтобы новые индексы автоматически получали правильные маппинги, настройки, алиасы и политику жизненного цикла.

Платформа журналов — классический пример. Если logs-web-2026.05.24 имеет правильный маппинг @timestamp, но завтрашний индекс создается динамически первым документом, одно некорректное событие может неправильно отобразить поле. Ошибка может не проявиться, пока не выйдут из строя дашборды или не исчезнут агрегации. Шаблоны предотвращают этот дрейф.

Простой шаблон может определять шаблон, настройки и маппинги для будущих индексов:

PUT /_index_template/logs_web_template
{
  "index_patterns": ["logs-web-*"],
  "template": {
    "settings": {
      "number_of_shards": 3,
      "number_of_replicas": 1
    },
    "mappings": {
      "properties": {
        "@timestamp": { "type": "date" },
        "service": { "type": "keyword" },
        "level": { "type": "keyword" },
        "message": { "type": "text" },
        "trace_id": { "type": "keyword" }
      }
    }
  }
}

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

Переиндексация без сюрпризов для приложения

Самая чистая миграция индекса обычно такова: создайте новый версионированный индекс, переиндексируйте данные, сравните количество и образцы запросов, затем замените алиас. Не направляйте приложение напрямую на products-v1, если вы не любите экстренные изменения конфигурации.

Тщательная миграция выглядит так:

PUT /products-v2
{
  "mappings": {
    "properties": {
      "product_id": { "type": "keyword" },
      "name": { "type": "text" },
      "price": { "type": "scaled_float", "scaling_factor": 100 }
    }
  }
}

Затем переиндексация:

POST /_reindex?wait_for_completion=false
{
  "source": { "index": "products-v1" },
  "dest": { "index": "products-v2" }
}

Использование wait_for_completion=false возвращает ID задачи, чтобы вы могли отслеживать длительную переиндексацию. После завершения сравните количество документов и выполните репрезентативные поиски. Только после этого меняйте алиасы.

Для индексов с интенсивной записью продумайте двойную запись, окна паузы или воспроизведение из источника истины. API-команды просты; план согласованности — это настоящая работа.

Безопасность и разрешения

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

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

Соглашения об именах уменьшают количество ошибок

Используйте имена, которые кодируют назначение и жизненный цикл: products-v3, logs-web-2026.05.24, metrics-api-000123 или имена потоков данных, соответствующие источнику данных. Избегайте расплывчатых имен, таких как newindex, test2 или prod-final. Во время очистки расплывчатые имена затрудняют понимание того, что можно безопасно удалить.

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