Управление жизненным циклом индексов Elasticsearch (ILM)

Published: 2026-03-22

Без ILM индексы Elasticsearch растут бесконечно. На одноузловом кластере с PVC 50 ГБ диск переполнится за несколько недель. ILM автоматизирует жизненный цикл: rollover при достижении максимального размера, forcemerge на старых данных, удаление по истечении срока хранения.


Четыре фазы

Фаза Триггер Действия
hot текущий индекс для записи rollover по размеру или возрасту
warm после rollover forcemerge, shrink (только multi-node)
cold старые данные, редкие запросы freeze (read-only)
delete истёк срок хранения удаление

Для одноузловой конфигурации: пропустить shrink и freeze, использовать только hot → delete.


Создание ILM-политики

bashcurl -X PUT "http://elasticsearch:9200/_ilm/policy/vector-logs" \
  -H "Content-Type: application/json" \
  -d '{
    "policy": {
      "phases": {
        "hot": {
          "min_age": "0ms",
          "actions": {
            "rollover": {
              "max_primary_shard_size": "20gb",
              "max_age": "7d"
            },
            "set_priority": { "priority": 100 }
          }
        },
        "delete": {
          "min_age": "30d",
          "actions": { "delete": {} }
        }
      }
    }
  }'

Rollover при достижении 20 ГБ или 7 дней. Удаление через 30 дней после rollover.


Шаблон индекса

bashcurl -X PUT "http://elasticsearch:9200/_index_template/vector-logs" \
  -H "Content-Type: application/json" \
  -d '{
    "index_patterns": ["vector-*"],
    "template": {
      "settings": {
        "index.lifecycle.name": "vector-logs",
        "index.lifecycle.rollover_alias": "vector-logs",
        "number_of_replicas": 0,
        "number_of_shards": 1
      },
      "mappings": {
        "properties": {
          "@timestamp": {"type": "date"},
          "message": {"type": "text"},
          "level": {"type": "keyword"},
          "kubernetes.namespace": {"type": "keyword"},
          "kubernetes.pod.name": {"type": "keyword"}
        }
      }
    }
  }'

number_of_replicas: 0 — обязательно для одноузлового кластера. При replicas=1 шарды уйдут в yellow. number_of_shards: 1 — оптимально для небольших объёмов.


Bootstrap write alias

ILM требует write alias на начальный индекс:

bashcurl -X PUT "http://elasticsearch:9200/vector-logs-000001" \
  -H "Content-Type: application/json" \
  -d '{
    "aliases": {
      "vector-logs": {
        "is_write_index": true
      }
    }
  }'

Vector пишет в alias vector-logs. ILM создаёт vector-logs-000002, vector-logs-000003 и т.д. при rollover.


Bootstrap-скрипт как Kubernetes Job

bash#!/bin/bash
set -e

ES_URL="http://elasticsearch-master.observability.svc.cluster.local:9200"

until curl -sf "$ES_URL/_cluster/health?wait_for_status=yellow"; do
  echo "ожидание elasticsearch..."
  sleep 5
done

curl -sf -X PUT "$ES_URL/_ilm/policy/vector-logs" \
  -H "Content-Type: application/json" \
  --data-binary @/bootstrap/ilm-policy.json

curl -sf -X PUT "$ES_URL/_index_template/vector-logs" \
  -H "Content-Type: application/json" \
  --data-binary @/bootstrap/index-template.json

curl -sf -X PUT "$ES_URL/vector-logs-000001" \
  -H "Content-Type: application/json" \
  --data-binary @/bootstrap/initial-index.json \
  || true

echo "Bootstrap завершён"

|| true делает Job идемпотентным — повторный запуск после пересборки кластера не падает, если индекс уже существует.


Мониторинг ILM

bash# Фаза каждого индекса
curl http://elasticsearch:9200/vector-*/_ilm/explain?filter_path=indices.*.phase,indices.*.age

# Ошибки ILM
curl http://elasticsearch:9200/vector-*/_ilm/explain | jq '.indices | to_entries[] | select(.value.step_info.type != null)'

# Ручной rollover
curl -X POST "http://elasticsearch:9200/vector-logs/_rollover"

# Перезапуск застрявшего шага ILM
curl -X POST "http://elasticsearch:9200/vector-logs-000001/_ilm/retry"

Ориентиры по шардам

Объём данных Шарды Размер шарда
< 5 ГБ/день 1 < 10 ГБ
5–20 ГБ/день 1–3 10–30 ГБ
> 50 ГБ/день 3–6 20–50 ГБ

Избыточное количество шардов — частая ошибка. Каждый шард потребляет файловые дескрипторы и память.


Диагностика

Ошибка «alias не существует» при rollover: bootstrap-скрипт не был выполнен. Запустите его повторно.

Индекс в yellow: number_of_replicas > 0 на одноузловом кластере. Установите replicas=0.

ILM не продвигается по фазам: условия проверяются раз в 10 минут. Текущий шаг и ошибки смотрите через /_ilm/explain.