DevOps

Elasticsearch Index Lifecycle Management (ILM) en 2026: gestión automática de índices y optimización del almacenamiento

Ruslan Ismailov Publicado 12 min de lectura
E

Introducción: el problema del crecimiento de índices y la gestión manual

En un entorno de producción con Elasticsearch, los índices crecen de forma continua. Los logs de aplicaciones, métricas y eventos de auditoría generan nuevos documentos cada segundo. Sin automatización, los ingenieros se ven obligados a crear nuevos índices manualmente, migrar datos antiguos a nodos fríos, eliminar shards obsoletos y controlar el balance del espacio en disco. Con volúmenes de cientos de gigabytes al día, esto se convierte en una tarea operativa de primer nivel.

Index Lifecycle Management (ILM) es el mecanismo integrado de Elasticsearch que resuelve este problema de forma declarativa. Se define la política de ciclo de vida una sola vez, se vincula a una plantilla de índice o a un data stream, y el clúster gestiona automáticamente el movimiento, la optimización y la eliminación de los datos. En 2026, ILM se ha convertido en el estándar de facto para cualquier proyecto de alta carga sobre Elasticsearch.

Concepto de ILM: fases y su propósito

Una política ILM describe la secuencia de fases por las que pasa un índice a lo largo de su vida. Cada fase corresponde a un estado determinado de los datos, desde la escritura activa hasta el archivo.

Hot

Fase de escritura activa y lectura frecuente. El índice reside en nodos rápidos (generalmente SSD). Aquí se configura el rollover, la condición bajo la cual se crea un nuevo índice. Es el mecanismo clave para evitar que un único índice crezca hasta alcanzar tamaños inmanejables.

Warm

Los datos ya no se escriben, pero se leen con cierta frecuencia. En esta fase se ejecutan force merge (fusión de segmentos para reducir el número de archivos) y shrink (reducción del número de shards primarios). Los nodos warm suelen utilizar discos más lentos y económicos.

Cold

Los datos se leen con poca frecuencia. Elasticsearch puede mover el índice a nodos cold o aplicar searchable snapshots, un mecanismo por el cual el índice se monta desde un almacenamiento de objetos (S3, GCS, Azure Blob) sin necesidad de copiarlo completamente al disco del nodo.

Frozen

Máximo ahorro de recursos: el índice se descarga completamente de la memoria y se carga únicamente cuando se consulta. El tiempo de respuesta es significativamente mayor que en fases anteriores, pero el coste de almacenamiento es mínimo. Es ideal para datos que se necesitan de forma esporádica, por ejemplo para auditorías de cumplimiento normativo.

Delete

El índice se elimina al cumplirse el tiempo de vida definido u otras condiciones. Es la fase final de la política de retención.

Configuración de una política ILM mediante REST API: guía paso a paso

Una política ILM puede crearse a través de Kibana (sección Stack Management → Index Lifecycle Policies) o directamente mediante la REST API. Veremos el enfoque por API, el más reproducible en pipelines de CI/CD.

Ejemplo de política para logs de aplicación con retención de 90 días:

PUT _ilm/policy/app-logs-policy\n{\n  \"policy\": {\n    \"phases\": {\n      \"hot\": {\n        \"min_age\": \"0ms\",\n        \"actions\": {\n          \"rollover\": {\n            \"max_primary_shard_size\": \"50gb\",\n            \"max_age\": \"1d\",\n            \"max_docs\": 50000000\n          },\n          \"set_priority\": {\n            \"priority\": 100\n          }\n        }\n      },\n      \"warm\": {\n        \"min_age\": \"3d\",\n        \"actions\": {\n          \"forcemerge\": {\n            \"max_num_segments\": 1\n          },\n          \"shrink\": {\n            \"number_of_shards\": 1\n          },\n          \"set_priority\": {\n            \"priority\": 50\n          }\n        }\n      },\n      \"cold\": {\n        \"min_age\": \"14d\",\n        \"actions\": {\n          \"searchable_snapshot\": {\n            \"snapshot_repository\": \"my-s3-repository\"\n          },\n          \"set_priority\": {\n            \"priority\": 0\n          }\n        }\n      },\n      \"frozen\": {\n        \"min_age\": \"45d\",\n        \"actions\": {\n          \"searchable_snapshot\": {\n            \"snapshot_repository\": \"my-s3-repository\"\n          }\n        }\n      },\n      \"delete\": {\n        \"min_age\": \"90d\",\n        \"actions\": {\n          \"delete\": {}\n        }\n      }\n    }\n  }\n}

Nota importante: el valor de min_age en las fases warm, cold y siguientes se calcula a partir del momento del rollover (creación del nuevo índice), no desde la fecha de creación del índice original. Esto es relevante para diagnosticar retrasos en las transiciones entre fases.

Vinculación de la política a una plantilla de índice y a un data stream

La política ILM no se aplica directamente a cada índice en el momento de su creación, sino que se vincula a un index template. Todos los nuevos índices que coincidan con la plantilla heredan automáticamente la política.

Ejemplo de creación de un component template con la configuración de ILM:

PUT _component_template/app-logs-settings\n{\n  \"template\": {\n    \"settings\": {\n      \"index.lifecycle.name\": \"app-logs-policy\",\n      \"index.lifecycle.rollover_alias\": \"app-logs\",\n      \"number_of_shards\": 3,\n      \"number_of_replicas\": 1\n    }\n  }\n}

A continuación, se crea el index template que referencia el component template:

PUT _index_template/app-logs-template\n{\n  \"index_patterns\": [\"app-logs-*\"],\n  \"data_stream\": {},\n  \"composed_of\": [\"app-logs-settings\"],\n  \"priority\": 200\n}

Al utilizar data streams (enfoque recomendado desde Elasticsearch 7.9+), el campo "data_stream": {} activa automáticamente el mecanismo de rollover sin necesidad de gestionar el alias manualmente. Un data stream siempre escribe en el backing index activo, y al producirse el rollover se crea el siguiente.

Rollovers: condiciones y detalles de configuración

El rollover es el núcleo de ILM en la fase hot. Crea un nuevo índice sucesor y redirige la escritura hacia él. Las condiciones del rollover funcionan con lógica OR: basta con que se cumpla cualquiera de ellas.

  • max_primary_shard_size — tamaño máximo del shard primario (por ejemplo, 50gb). Es el valor recomendado para la mayoría de los casos.
  • max_age — antigüedad máxima del índice (por ejemplo, 1d para rotación diaria de logs).
  • max_docs — número máximo de documentos. Útil cuando el volumen de datos es irregular.
  • max_size — tamaño total del índice (todos los shards). Ha quedado en desuso en favor de max_primary_shard_size, aunque sigue siendo compatible.

Para índices clásicos (no data streams) es necesario crear el índice inicial con el alias de forma manual:

PUT app-logs-000001\n{\n  \"aliases\": {\n    \"app-logs\": {\n      \"is_write_index\": true\n    }\n  }\n}

A partir de ese momento, ILM creará automáticamente app-logs-000002, app-logs-000003, etc., al cumplirse las condiciones del rollover.

Optimización del almacenamiento: force merge, shrink, freeze y searchable snapshots

Force Merge

Elasticsearch almacena los datos en segmentos de Lucene. Cada documento indexado genera nuevos segmentos, que el proceso en segundo plano fusiona periódicamente. Force merge fusiona de forma forzada todos los segmentos de un índice en uno solo (o en el número definido), lo que reduce el uso de memoria heap, acelera las búsquedas y disminuye el número de descriptores de archivo. Solo se ejecuta en índices de solo lectura.

Shrink

La operación shrink reduce el número de shards primarios de un índice. Si un índice se creó con 3 shards y los datos ya no crecen activamente, shrink permite comprimirlo a 1 shard, reduciendo la sobrecarga del clúster. El nuevo número de shards debe ser un divisor del número original.

Searchable Snapshots

Es una de las herramientas más potentes para optimizar el coste de almacenamiento en 2026. En lugar de mantener el índice en los discos de los nodos, Elasticsearch lo monta directamente desde el repositorio de snapshots (S3, GCS). Los datos se cachean localmente solo cuando se accede a ellos. En la fase frozen, la caché es mínima, lo que hace que el coste de almacenamiento sea comparable al de un almacenamiento de objetos en crudo.

Para usar searchable snapshots es necesario registrar el repositorio:

PUT _snapshot/my-s3-repository\n{\n  \"type\": \"s3\",\n  \"settings\": {\n    \"bucket\": \"my-elasticsearch-snapshots\",\n    \"region\": \"eu-west-1\",\n    \"base_path\": \"ilm-snapshots\"\n  }\n}

Monitorización del estado de las políticas: Explain API y diagnóstico

Para verificar el estado actual de un índice en su ciclo de vida se utiliza la Explain API:

GET app-logs-000001/_ilm/explain

La respuesta incluye la fase actual, la acción, el paso y la hora del último cambio de estado. Los campos más relevantes para el análisis son: phase, action, step y step_info (que contiene el mensaje de error en caso de fallo).

Problemas más frecuentes y sus causas:

  • El índice se queda bloqueado en la fase warm/cold — generalmente porque los nodos con el atributo requerido (data_warm, data_cold) no están disponibles o no existen en el clúster. Revisa la configuración de node allocation.
  • Shrink se bloquea — el índice no se ha puesto en modo solo lectura antes del shrink. ILM lo hace automáticamente, pero si hay solicitudes de escritura activas sobre el índice, la operación quedará bloqueada.
  • El rollover no se activa — el alias no está configurado como is_write_index, o para el data stream no se ha creado el primer backing index mediante la creación del data stream.
  • La política no se aplica a nuevos índices — el index template tiene menor prioridad que otra plantilla en conflicto. Comprueba el campo priority en la plantilla.

Para consultar todos los índices con errores ILM de forma cómoda:

GET */_ilm/explain?only_errors=true

Integración de ILM en una arquitectura de microservicios

En entornos de microservicios surge frecuentemente la pregunta: ¿quién se encarga de crear los índices y aplicar las políticas? La práctica en 2026 propone el siguiente enfoque.

El index template y la política ILM los crea el equipo de plataforma (DevOps/SRE) como parte del código de infraestructura: Terraform, Ansible o mediante un pipeline GitOps con llamadas a la REST API de Elasticsearch. Los propios microservicios escriben los datos en el data stream (o en el alias) sin conocer los detalles de sharding ni de la rotación de índices.

Esta separación de responsabilidades permite:

  • Modificar la política de retención sin necesidad de redesplegar la aplicación.
  • Gestionar el coste de almacenamiento de forma centralizada.
  • Aplicar distintas políticas para diferentes entornos (dev, staging, producción) mediante plantillas con diferentes patrones de nombres.

Al crear un data stream automáticamente mediante la REST API basta con una sola solicitud: Elasticsearch creará el primer backing index y aplicará la política definida en la plantilla:

PUT _data_stream/app-logs

Caso práctico: configuración de ILM para logs con retención de 90 días

Veamos el escenario completo para una aplicación de producción típica: un microservicio genera logs estructurados en JSON que deben conservarse durante 90 días. Los primeros 3 días en acceso caliente, de 3 a 14 días en acceso templado, de 14 a 45 días en frío (searchable snapshot), de 45 a 90 días en modo frozen y, pasado ese tiempo, eliminación.

Paso 1: creación de la política (ver el ejemplo anterior en la sección REST API).

Paso 2: creación del mapeo mediante un component template:

PUT _component_template/app-logs-mappings\n{\n  \"template\": {\n    \"mappings\": {\n      \"properties\": {\n        \"@timestamp\": { \"type\": \"date\" },\n        \"service\": { \"type\": \"keyword\" },\n        \"level\": { \"type\": \"keyword\" },\n        \"message\": { \"type\": \"text\" },\n        \"trace_id\": { \"type\": \"keyword\" }\n      }\n    }\n  }\n}

Paso 3: index template final que agrupa todo:

PUT _index_template/app-logs-template\n{\n  \"index_patterns\": [\"app-logs\"],\n  \"data_stream\": {},\n  \"composed_of\": [\"app-logs-settings\", \"app-logs-mappings\"],\n  \"priority\": 200,\n  \"_meta\": {\n    \"description\": \"Template for application logs with 90-day retention\"\n  }\n}

Paso 4: activación del data stream:

PUT _data_stream/app-logs

A partir de aquí, el microservicio puede escribir logs en el índice app-logs mediante la bulk API estándar. ILM ejecutará automáticamente toda la cadena de transiciones a lo largo de los 90 días.

Para verificar la configuración unas horas después del arranque:

GET _data_stream/app-logs\nGET app-logs/_ilm/explain

Conclusión

Elasticsearch Index Lifecycle Management en 2026 no es solo una función conveniente, sino un componente imprescindible en cualquier arquitectura de producción con Elasticsearch. Una política ILM correctamente configurada resuelve automáticamente la rotación de índices, la optimización del espacio en disco mediante force merge y shrink, la reducción de costes a través de searchable snapshots y el cumplimiento de los requisitos de retención mediante la eliminación automática.

Recomendaciones clave para la implementación práctica: utiliza data streams en lugar de índices clásicos con aliases; separa las responsabilidades entre el equipo de plataforma y los desarrolladores de microservicios; monitoriza regularmente el estado de las políticas mediante la Explain API; y prueba las transiciones entre fases en un entorno de staging antes de aplicarlas en producción. La inversión de tiempo en una configuración correcta de ILM se amortiza con creces gracias a la reducción de la carga operativa y la optimización de los costes de infraestructura.

Tecnologías

Etiquetas

Ruslan Ismailov

Desarrollador Senior Web / Backend. Desarrollador senior web/backend con 9 años de experiencia. Stack: PHP, Laravel, PostgreSQL, Redis, Docker, Kubernetes, REST, microservicios, CI/CD. Más sobre mí →