Como Automatizar o Rollover de Logs no Elasticsearch

11 min de leitura Automação
Como Automatizar o Rollover de Logs no Elasticsearch

A importância da gestão eficiente de logs no Elasticsearch

No ecossistema moderno de infraestrutura e observabilidade, o Elasticsearch consolidou-se como a espinha dorsal para armazenamento e análise de dados de log. Ferramentas como o Elastic Stack (ELK) permitem que equipes de SRE, DevOps e desenvolvedores monitorem a saúde de aplicações em tempo real. No entanto, à medida que o volume de dados cresce exponencialmente, a estratégia padrão de indexação por data — criar um novo índice diariamente ou mensalmente — torna-se insuficiente.

O principal problema reside na fragmentação. Centenas de índices pequenos geram uma sobrecarga significativa no cluster, consumindo recursos valiosos de CPU e memória para gerenciamento de metadados, além de impactar a performance das buscas distribuídas. Para mitigar isso, o Elasticsearch oferece o recurso nativo de Rollover. Diferente da rotação baseada em tempo, o rollover permite que um índice cresça até atingir critérios específicos, como tamanho máximo ou número de documentos, antes de ser fechado e substituído por um novo.

Neste tutorial técnico, demonstraremos como implementar uma automação robusta para o rollover de logs utilizando scripts em Python. Abordaremos a configuração do Index Lifecycle Management (ILM), a criação de templates de índice e a escrita de um script automatizado que monitora o estado dos índices e executa a transição necessária, garantindo uma infraestrutura escalável e performática.

Pré-requisitos e arquitetura da solução

Antes de iniciar a implementação, é fundamental entender os componentes envolvidos na automação do rollover. A solução não depende apenas do script em Python; ela requer uma configuração prévia no cluster Elasticsearch para definir as regras de negócio.

  • Elasticsearch Cluster: Versão 7.x ou superior recomendada. Certifique-se de ter acesso administrativo com privilégios para gerenciar índices e políticas ILM.
  • Python 3.8+: Linguagem escolhida por sua simplicidade e vasta biblioteca de suporte para APIs REST.
  • Biblioteca elasticsearch-py: O cliente oficial Python para o Elasticsearch, que facilita a comunicação com a API REST.
  • Elasticsearch Index Template: Estrutura que define como os novos índices serão criados após o rollover.
  • ILM Policy (Política de Ciclo de Vida): Define o que acontece com o índice após ele ser fechado (ex: deletar após 30 dias, mover para cold storage).

A arquitetura proposta segue um fluxo contínuo: um índice primário (logs-000001) recebe todas as escritas. Quando atinge o limite definido, o sistema executa o rollover, fecha o índice antigo e abre um novo (logs-000002). O script em Python atuará como o gatilho agendado (via cron ou sistema de orquestração) para verificar essa condição.

Passo 1: Configurar a Política ILM e o Template de Índice

O primeiro passo é garantir que o Elasticsearch saiba como lidar com os índices antigos e novos. Vamos criar uma política ILM chamada logs_policy que move o índice para o estado Closed após 1 dia (para economizar recursos durante a retenção curta) e depois o deleta após 7 dias. Em seguida, criamos um template de índice que aplica essa política automaticamente.

Execute os seguintes comandos via curl ou no Kibana Dev Tools para configurar a infraestrutura base:

# 1. Criar a política ILM
PUT _ilm/policy/logs_policy
{
  "policy": {
    "phases": {
      "hot": {
        "actions": {
          "rollover": {
            "max_age": "1d",
            "max_docs": 10000,
            "max_size": "5gb"
          }
        }
      },
      "delete": {
        "min_age": "7d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

Em seguida, definimos o template de índice que será aplicado a todos os índices que começarem com logs-. Note a propriedade is_write_index: true, que indica ao Elasticsearch qual índice deve receber as novas escritas.

# 2. Criar o Index Template
PUT _index_template/logs_template
{
  "index_patterns": ["logs-*"],
  "priority": 100,
  "template": {
    "settings": {
      "number_of_shards": 1,
      "number_of_replicas": 1,
      "index.lifecycle.name": "logs_policy",
      "index.lifecycle.rollover_alias": "logs_write_alias"
    },
    "mappings": {
      "properties": {
        "@timestamp": {
          "type": "date"
        },
        "message": {
          "type": "text"
        },
        "level": {
          "type": "keyword"
        }
      }
    }
  }
}

A chave aqui é o index.lifecycle.rollover_alias. Ao invés de gerenciar nomes de índices específicos, apontamos para um alias. Isso permite que o script e as aplicações escrevam sempre no mesmo endereço lógico, enquanto o Elasticsearch gerencia a troca interna do índice físico.

Passo 2: Inicializar o Índice Primário

Para que o rollover funcione, é necessário criar o primeiro índice manualmente ou via script. Este índice servirá como o ponto de partida. Vamos nomeá-lo logs-000001.

# Criar o índice inicial
PUT logs-000001
{
  "aliases": {
    "logs_write_alias": {
      "is_write_index": true
    }
  }
}

Agora, qualquer dado enviado para o alias logs_write_alias será armazenado no índice logs-000001. Verifique se o índice está ativo:

GET logs_write_alias/_search
{
  "size": 1
}

Passo 3: Desenvolver o Script de Automação em Python

Agora que a infraestrutura está pronta, precisamos do agente de automação. O script verificará se o índice atual atingiu os limites definidos na política ILM e, caso positivo, solicitará o rollover.

Primeiro, instale a dependência necessária:

pip install elasticsearch

Abaixo, apresentamos o código completo do script elastic_rollover.py. Este script conecta ao cluster, verifica o estado do índice de escrita e executa a operação se necessário.

import json
import sys
from elasticsearch import Elasticsearch

def check_and_rollover(es_client, alias_name="logs_write_alias"):
    """
    Verifica o status do índice apontado pelo alias e realiza rollover se necessário.
    """
    try:
        # 1. Obter informações sobre os índices vinculados ao alias
        indices_info = es_client.indices.get_alias(name=alias_name)
        
        if not indices_info:
            print(f"Erro: Alias '{alias_name}' não encontrado.")
            return False

        # Identificar o índice atual que é o write_index
        current_index = None
        for index_name, info in indices_info.items():
            aliases = info.get("aliases", {})
            if alias_name in aliases and aliases[alias_name].get("is_write_index", False):
                current_index = index_name
                break
        
        if not current_index:
            print(f"Erro: Nenhum índice write found para o alias '{alias_name}'.")
            return False

        # 2. Verificar os limites do ILM
        # Precisamos verificar se o rollover foi solicitado ou se as condições foram atingidas.
        # O Elasticsearch não retorna explicitamente "pronto para rollover" via API simples,
        # mas podemos checar o status do ILM ou tentar executar o comando e lidar com o erro.
        
        # Abordagem recomendada: Tentar verificar o status do índice no contexto do ILM
        # Ou simplesmente tentar o rollover. Se já estiver pronto, o ES gerencia.
        # No entanto, para logs limpos, vamos checar o tamanho/docs se possível via stats.
        
        stats = es_client.indices.stats(index=current_index)
        store_stats = stats["_indices"][current_index]["store"]
        
        size_in_bytes = store_stats["size_in_bytes"]
        doc_count = stats["_indices"][current_index]["docs"]["count"]
        
        # Limites definidos na política (exemplo: 5GB ou 10k docs)
        MAX_SIZE_BYTES = 5 * 1024 * 1024 * 1024  # 5 GB
        MAX_DOCS = 10000
        
        print(f"Índice atual: {current_index}")
        print(f"Tamanho: {size_in_bytes / (1024**3):.2f} GB")
        print(f"Documentos: {doc_count}")

        # Verificar condições de rollover
        should_rollover = False
        
        if size_in_bytes >= MAX_SIZE_BYTES:
            print("Condição de tamanho atingida. Iniciando rollover...")
            should_rollover = True
            
        if doc_count >= MAX_DOCS:
            print("Condição de documentos atingida. Iniciando rollover...")
            should_rollover = True
            
        # Nota: A condição de tempo (max_age) é gerenciada internamente pelo ILM,
        # mas o script pode forçar o rollover se quiser basear-se apenas em tamanho/docs.
        # Para uma automação completa via ILM, muitas vezes não é necessário rodar este script
        # se o agente do Elasticsearch estiver ativo, mas para cenários externos ou 
        # triggers customizadas, este check é vital.

        if should_rollover:
            # 3. Executar o Rollover
            print(f"Executando rollover no índice {current_index}...")
            
            response = es_client.indices.rollover(alias=alias_name)
            
            if response.get("acknowledged"):
                new_index = list(response["indices"].keys())[0] if current_index in response["indices"] else "Desconhecido"
                print(f"Scesso! Novo índice criado ou rollover realizado.")
                return True
            else:
                print(f"Falha no rollover: {response}")
                return False
        
        else:
            print("Condições de rollover não atingidas. Nada a fazer.")
            return True

    except Exception as e:
        print(f"Erro ao processar rollover: {str(e)}")
        return False

if __name__ == "__main__":
    # Configuração de conexão
    ES_HOST = "localhost"
    ES_PORT = 9200
    
    es = Elasticsearch([{"host": ES_HOST, "port": ES_PORT}])
    
    # Verificar conectividade básica
    if not es.ping():
        print("Não foi possível conectar ao Elasticsearch.")
        sys.exit(1)

    # Executar a lógica
    check_and_rollover(es)

Passo 4: Implementação em Produção e Agendamento

Com o script funcional, o próximo passo é integrá-lo ao ambiente de produção. Recomenda-se não rodar este script manualmente, mas sim através de um agendador de tarefas.

Opção A: Cron Job (Linux)

Adicione uma entrada no crontab do usuário responsável para verificar a cada 15 minutos:

/15 * * * * /usr/bin/python3 /opt/scripts/elastic_rollover.py >> /var/log/elastic_rollover.log 2>&1

Opção B: Sistema de Orquestração (Kubernetes/Celery)

Se sua infraestrutura estiver em Kubernetes, utilize um CronJob. Isso permite melhor gerenciamento de logs e falhas. Se você utiliza Python para outras automações, considere usar o Airflow ou Celery para criar uma tarefa agendada que invoca a função check_and_rollover.

Considerações de Segurança:

  • Nunca armazene credenciais em texto puro no script. Utilize variáveis de ambiente ou ferramentas como AWS Secrets Manager, HashiCorp Vault ou configurações do próprio Elasticsearch com autenticação básica/NTLM.
  • Configure o script para enviar alertas (via Slack, PagerDuty ou Email) caso a conexão falhe ou o rollover seja interrompido por erro de permissão.

Boas Práticas e Otimizações Avançadas

A automação do rollover é poderosa, mas exige monitoramento contínuo. Aqui estão dicas cruciais para manter a saúde do seu cluster:

  1. Mapeamentos Dinâmicos: Certifique-se de que o template de índice proíba a adição dinâmica de campos não mapeados em índices antigos. Isso evita que novos tipos de logs quebrem buscas existentes. Use "dynamic": "strict" no mapeamento.
  2. Sharding Estratégico: Ao definir o número de shards, lembre-se de que um rollover cria um novo índice com seus próprios shards. Se você criar milhares de índices pequenos por dia, o cluster entrará em colapso. Use max_age ou max_docs para limitar a frequência de criação.
  3. Monitoramento do ILM: Utilize a API GET _ilm/explain para verificar se os índices estão seguindo as políticas corretamente. Erros no ILM são comuns quando há problemas de disco ou permissão.
  4. Alias Naming Convention: Mantenha uma convenção rigorosa de nomes para aliases. Use prefixos claros como -write, -read e -search para evitar ambiguidades em clusters grandes.

Conclusão

A automação do rollover de logs no Elasticsearch não é apenas uma questão de conveniência, mas uma necessidade técnica para escalabilidade. Ao substituir a rotação baseada puramente em tempo por critérios baseados em dados (tamanho e volume), você otimiza o uso de recursos e simplifica a gestão do ciclo de vida dos seus dados.

A combinação de Index Templates, ILM Policies e scripts em Python oferece um controle granular e programável sobre sua infraestrutura de logging. Este tutorial forneceu a base sólida para que sysadmins e desenvolvedores possam implementar essa automação, garantindo que o Elasticsearch permaneça rápido, estável e pronto para lidar com o crescimento exponencial dos dados da organização.

Lembre-se: teste sempre em um ambiente de staging antes de aplicar políticas de deleção ou fechamento automático em produção. A visibilidade é a chave para uma infraestrutura resiliente.

Compartilhar: Link copiado!
Esse tutorial foi útil?

Comentários (0)

Seja o primeiro a comentar.

Deixe seu comentário

Seu comentário será analisado antes de ser publicado.

0/2000