Instalación de Elasticsearch y Logstash

Introducción

El ELK Stack (Elasticsearch, Logstash, Kibana) se ha convertido en el estándar de la industria para el registro centralizado, análisis de logs y visualización de datos. Elasticsearch proporciona potentes capacidades de búsqueda y análisis de texto completo, mientras que Logstash actúa como un pipeline de procesamiento de datos que ingiere, transforma y reenvía logs a Elasticsearch para almacenamiento y análisis.

El registro centralizado es crucial para la gestión moderna de infraestructura, permitiéndote agregar logs de múltiples servidores, aplicaciones y servicios en un repositorio único y consultable. Esta centralización simplifica la solución de problemas, el análisis de seguridad, los informes de cumplimiento y las perspectivas operacionales a través de sistemas distribuidos.

Esta guía completa te lleva a través de la instalación y configuración de Elasticsearch y Logstash en servidores Linux. Aprenderás cómo configurar una infraestructura de registro lista para producción, configurar pipelines de ingesta de datos, optimizar el rendimiento, implementar seguridad e integrar con varias fuentes de logs. Ya sea que estés construyendo un nuevo sistema de registro o migrando desde soluciones heredadas, esta guía proporciona la base para una gestión efectiva de logs.

Requisitos Previos

Antes de instalar Elasticsearch y Logstash, asegúrate de tener:

  • Un servidor Linux (Ubuntu 20.04/22.04, Debian 10/11, CentOS 7/8, Rocky Linux 8/9)
  • Acceso root o sudo para instalación y configuración
  • Java 11 o Java 17 (OpenJDK u Oracle JDK)
  • Mínimo 4 GB RAM (8 GB recomendado para producción)
  • Mínimo 10 GB de espacio en disco (escala con el volumen de logs)
  • Comprensión básica de JSON y formatos de log

Requisitos de Sistema Recomendados:

  • Desarrollo: 4 GB RAM, 2 núcleos CPU, 20 GB disco
  • Producción: 16 GB RAM, 4-8 núcleos CPU, 100+ GB almacenamiento SSD
  • Alto Volumen: 32+ GB RAM, 8+ núcleos CPU, 500+ GB almacenamiento SSD

Instalación de Java

Tanto Elasticsearch como Logstash requieren Java. Instalemos OpenJDK 11 o 17.

En Ubuntu/Debian

# Actualizar repositorio de paquetes
sudo apt update

# Instalar OpenJDK 11
sudo apt install openjdk-11-jdk -y

# O instalar OpenJDK 17
sudo apt install openjdk-17-jdk -y

# Verificar instalación
java -version

# Establecer JAVA_HOME
echo 'export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64' >> ~/.bashrc
source ~/.bashrc

En CentOS/Rocky Linux

# Instalar OpenJDK 11
sudo yum install java-11-openjdk java-11-openjdk-devel -y

# O instalar OpenJDK 17
sudo dnf install java-17-openjdk java-17-openjdk-devel -y

# Verificar instalación
java -version

# Establecer JAVA_HOME
echo 'export JAVA_HOME=/usr/lib/jvm/java-11-openjdk' >> ~/.bashrc
source ~/.bashrc

Instalación de Elasticsearch

Método 1: Repositorio Oficial (Recomendado)

En Ubuntu/Debian:

# Importar clave GPG de Elasticsearch
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg

# Agregar repositorio de Elasticsearch
echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-8.x.list

# Actualizar índice de paquetes
sudo apt update

# Instalar Elasticsearch
sudo apt install elasticsearch -y

En CentOS/Rocky Linux:

# Importar clave GPG de Elasticsearch
sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch

# Crear archivo de repositorio
sudo tee /etc/yum.repos.d/elasticsearch.repo <<EOF
[elasticsearch]
name=Elasticsearch repository for 8.x packages
baseurl=https://artifacts.elastic.co/packages/8.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
EOF

# Instalar Elasticsearch
sudo yum install elasticsearch -y

Método 2: Descarga Directa

# Descargar Elasticsearch (verificar la última versión)
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.11.0-linux-x86_64.tar.gz

# Extraer archivo
tar -xzf elasticsearch-8.11.0-linux-x86_64.tar.gz

# Mover a /opt
sudo mv elasticsearch-8.11.0 /opt/elasticsearch

# Crear usuario elasticsearch
sudo useradd -r -s /bin/false elasticsearch

# Establecer propiedad
sudo chown -R elasticsearch:elasticsearch /opt/elasticsearch

Configuración Inicial de Elasticsearch

Configurar tamaño de heap JVM:

# Editar opciones JVM
sudo nano /etc/elasticsearch/jvm.options

# Establecer tamaño de heap (típicamente 50% de RAM disponible, máx 32GB)
-Xms4g
-Xmx4g

Configuración básica de Elasticsearch:

# Editar configuración principal
sudo nano /etc/elasticsearch/elasticsearch.yml
# Nombre del cluster
cluster.name: my-logging-cluster

# Nombre del nodo
node.name: node-1

# Configuración de red
network.host: 0.0.0.0
http.port: 9200

# Configuración de descubrimiento (nodo único para desarrollo)
discovery.type: single-node

# Rutas de datos y logs
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch

# Deshabilitar seguridad para configuración inicial (habilitar en producción)
xpack.security.enabled: false
xpack.security.enrollment.enabled: false

Iniciar Elasticsearch:

# Habilitar e iniciar Elasticsearch
sudo systemctl daemon-reload
sudo systemctl enable elasticsearch
sudo systemctl start elasticsearch

# Verificar estado
sudo systemctl status elasticsearch

# Ver logs
sudo journalctl -u elasticsearch -f

Verificar que Elasticsearch está ejecutándose:

# Probar conexión (esperar 30-60 segundos para el inicio)
curl -X GET "localhost:9200/"

# Salida esperada:
# {
#   "name" : "node-1",
#   "cluster_name" : "my-logging-cluster",
#   "version" : { ... },
#   ...
# }

# Verificar salud del cluster
curl -X GET "localhost:9200/_cluster/health?pretty"

Instalación de Logstash

Método 1: Repositorio Oficial (Recomendado)

El repositorio de Elasticsearch ya incluye Logstash.

En Ubuntu/Debian:

# Repositorio ya agregado en la instalación de Elasticsearch
sudo apt update
sudo apt install logstash -y

En CentOS/Rocky Linux:

# Repositorio ya agregado en la instalación de Elasticsearch
sudo yum install logstash -y

Método 2: Descarga Directa

# Descargar Logstash
wget https://artifacts.elastic.co/downloads/logstash/logstash-8.11.0-linux-x86_64.tar.gz

# Extraer archivo
tar -xzf logstash-8.11.0-linux-x86_64.tar.gz

# Mover a /opt
sudo mv logstash-8.11.0 /opt/logstash

# Crear usuario logstash
sudo useradd -r -s /bin/false logstash

# Establecer propiedad
sudo chown -R logstash:logstash /opt/logstash

Configuración de Logstash

Configurar heap JVM:

# Editar opciones JVM
sudo nano /etc/logstash/jvm.options

# Establecer tamaño de heap (típicamente 25% de RAM disponible)
-Xms2g
-Xmx2g

Configuración principal de Logstash:

# Editar logstash.yml
sudo nano /etc/logstash/logstash.yml
# Nombre del nodo
node.name: logstash-1

# Ruta de datos
path.data: /var/lib/logstash

# Ruta de configuración del pipeline
path.config: /etc/logstash/conf.d

# Ruta de logs
path.logs: /var/log/logstash

# Configuración del pipeline
pipeline.workers: 2
pipeline.batch.size: 125
pipeline.batch.delay: 50

# Monitoreo
monitoring.enabled: false

Creación de Pipeline de Logstash

Crear directorio de configuración del pipeline:

sudo mkdir -p /etc/logstash/conf.d

Configuración básica del pipeline (ejemplo syslog):

sudo nano /etc/logstash/conf.d/syslog-pipeline.conf
# Sección de entrada
input {
  # Entrada syslog
  tcp {
    port => 5000
    type => "syslog"
  }

  udp {
    port => 5000
    type => "syslog"
  }

  # Entrada de archivo
  file {
    path => "/var/log/syslog"
    start_position => "beginning"
    sincedb_path => "/dev/null"
    type => "syslog-file"
  }
}

# Sección de filtro
filter {
  if [type] == "syslog" {
    grok {
      match => { "message" => "%{SYSLOGLINE}" }
    }

    date {
      match => [ "timestamp", "MMM  d HH:mm:ss", "MMM dd HH:mm:ss" ]
    }
  }
}

# Sección de salida
output {
  elasticsearch {
    hosts => ["localhost:9200"]
    index => "syslog-%{+YYYY.MM.dd}"
  }

  # También salida a stdout para depuración
  stdout {
    codec => rubydebug
  }
}

Iniciar Logstash:

# Habilitar e iniciar Logstash
sudo systemctl enable logstash
sudo systemctl start logstash

# Verificar estado
sudo systemctl status logstash

# Ver logs
sudo journalctl -u logstash -f

Probar pipeline de Logstash:

# Enviar log de prueba vía TCP
echo "<14>Jan 11 10:00:00 testhost test: This is a test message" | nc localhost 5000

# Verificar si los datos llegaron a Elasticsearch
curl -X GET "localhost:9200/syslog-*/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match_all": {}
  }
}
'

Pipelines Avanzados de Logstash

Pipeline de Access Log de Apache/Nginx

sudo nano /etc/logstash/conf.d/apache-access.conf
input {
  file {
    path => "/var/log/apache2/access.log"
    start_position => "beginning"
    sincedb_path => "/var/lib/logstash/sincedb/apache-access"
    type => "apache-access"
  }

  file {
    path => "/var/log/nginx/access.log"
    start_position => "beginning"
    sincedb_path => "/var/lib/logstash/sincedb/nginx-access"
    type => "nginx-access"
  }
}

filter {
  if [type] == "apache-access" {
    grok {
      match => { "message" => '%{IPORHOST:clientip} %{USER:ident} %{USER:auth} \[%{HTTPDATE:timestamp}\] "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})" %{NUMBER:response} (?:%{NUMBER:bytes}|-)' }
    }

    date {
      match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
    }

    geoip {
      source => "clientip"
    }

    useragent {
      source => "agent"
      target => "user_agent"
    }
  }

  if [type] == "nginx-access" {
    grok {
      match => { "message" => '%{IPORHOST:clientip} - %{USER:ident} \[%{HTTPDATE:timestamp}\] "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})" %{NUMBER:response} (?:%{NUMBER:bytes}|-) "(?:%{DATA:referrer}|-)" "(?:%{DATA:agent}|-)"' }
    }

    date {
      match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
    }

    geoip {
      source => "clientip"
    }
  }
}

output {
  if [type] == "apache-access" {
    elasticsearch {
      hosts => ["localhost:9200"]
      index => "apache-access-%{+YYYY.MM.dd}"
    }
  }

  if [type] == "nginx-access" {
    elasticsearch {
      hosts => ["localhost:9200"]
      index => "nginx-access-%{+YYYY.MM.dd}"
    }
  }
}

Pipeline de Log de Aplicación (JSON)

sudo nano /etc/logstash/conf.d/app-json.conf
input {
  file {
    path => "/var/log/myapp/app.json"
    codec => "json"
    type => "app-json"
  }
}

filter {
  # Parsear campos JSON
  json {
    source => "message"
  }

  # Agregar campos personalizados
  mutate {
    add_field => {
      "application" => "myapp"
      "environment" => "production"
    }
  }

  # Convertir nivel de log a minúsculas
  mutate {
    lowercase => ["level"]
  }

  # Parsear timestamp si está presente
  date {
    match => ["timestamp", "ISO8601"]
  }
}

output {
  elasticsearch {
    hosts => ["localhost:9200"]
    index => "app-%{application}-%{+YYYY.MM.dd}"
  }
}

Configuración Multi-Pipeline

sudo nano /etc/logstash/pipelines.yml
- pipeline.id: syslog-pipeline
  path.config: "/etc/logstash/conf.d/syslog-pipeline.conf"
  pipeline.workers: 2

- pipeline.id: apache-pipeline
  path.config: "/etc/logstash/conf.d/apache-access.conf"
  pipeline.workers: 1

- pipeline.id: app-pipeline
  path.config: "/etc/logstash/conf.d/app-json.conf"
  pipeline.workers: 1
# Reiniciar Logstash para aplicar
sudo systemctl restart logstash

Ajuste de Rendimiento

Rendimiento de Elasticsearch

Optimizar configuración JVM:

sudo nano /etc/elasticsearch/jvm.options
# Tamaño de heap (50% de RAM, máx 32GB)
-Xms16g
-Xmx16g

# Configuración GC
-XX:+UseG1GC
-XX:G1ReservePercent=25
-XX:InitiatingHeapOccupancyPercent=30

Optimizar configuración de Elasticsearch:

sudo nano /etc/elasticsearch/elasticsearch.yml
# Thread pools
thread_pool.write.queue_size: 1000
thread_pool.search.queue_size: 1000

# Configuración de indexación
indices.memory.index_buffer_size: 30%

# Caché de consultas
indices.queries.cache.size: 15%

# Caché de fielddata
indices.fielddata.cache.size: 40%

# Intervalo de refresco (aumentar para mejor rendimiento de indexación)
indices.refresh_interval: 30s

Rendimiento de Logstash

Optimizar workers del pipeline:

sudo nano /etc/logstash/logstash.yml
# Aumentar workers (uno por núcleo CPU)
pipeline.workers: 4

# Aumentar tamaño de lote
pipeline.batch.size: 250

# Ajustar retraso de lote
pipeline.batch.delay: 50

# Workers de salida
pipeline.output.workers: 2

Ajuste específico del pipeline:

output {
  elasticsearch {
    hosts => ["localhost:9200"]
    index => "logs-%{+YYYY.MM.dd}"
    # Configuración de bulk
    flush_size => 500
    idle_flush_time => 5
  }
}

Configuración de Seguridad

Habilitar Seguridad de Elasticsearch

# Editar configuración de Elasticsearch
sudo nano /etc/elasticsearch/elasticsearch.yml
# Habilitar seguridad X-Pack
xpack.security.enabled: true
xpack.security.enrollment.enabled: true

# TLS para HTTP
xpack.security.http.ssl:
  enabled: true
  keystore.path: certs/http.p12

# TLS para capa de transporte
xpack.security.transport.ssl:
  enabled: true
  verification_mode: certificate
  keystore.path: certs/transport.p12
  truststore.path: certs/transport.p12

Configurar contraseñas:

# Auto-generar contraseñas
sudo /usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto

# O establecer contraseñas interactivamente
sudo /usr/share/elasticsearch/bin/elasticsearch-setup-passwords interactive

Guardar las contraseñas generadas:

  • elastic (superusuario)
  • kibana_system
  • logstash_system
  • beats_system

Configurar Logstash con Seguridad

sudo nano /etc/logstash/conf.d/secure-output.conf
output {
  elasticsearch {
    hosts => ["https://localhost:9200"]
    user => "logstash_system"
    password => "YOUR_PASSWORD_HERE"
    cacert => "/etc/elasticsearch/certs/http_ca.crt"
    index => "logs-%{+YYYY.MM.dd}"
  }
}

Configuración de Firewall

# UFW (Ubuntu/Debian)
sudo ufw allow 9200/tcp  # Elasticsearch HTTP
sudo ufw allow 5000/tcp  # Entrada Logstash
sudo ufw allow 5000/udp  # Logstash syslog UDP

# firewalld (CentOS/Rocky)
sudo firewall-cmd --permanent --add-port=9200/tcp
sudo firewall-cmd --permanent --add-port=5000/tcp
sudo firewall-cmd --permanent --add-port=5000/udp
sudo firewall-cmd --reload

Monitoreo y Mantenimiento

Gestión de Índices

Ver índices:

# Listar todos los índices
curl -X GET "localhost:9200/_cat/indices?v"

# Verificar tamaño de índice
curl -X GET "localhost:9200/_cat/indices?v&s=store.size:desc"

# Obtener información de índice específico
curl -X GET "localhost:9200/syslog-2024.01.11/_stats?pretty"

Eliminar índices antiguos:

# Eliminar índices mayores de 30 días
curl -X DELETE "localhost:9200/syslog-2023.*"

# O usar curator (recomendado para automatización)
sudo pip3 install elasticsearch-curator

Crear configuración de curator:

sudo nano /etc/curator/curator.yml
client:
  hosts:
    - localhost
  port: 9200
  timeout: 30

logging:
  loglevel: INFO
  logfile: /var/log/curator.log

Archivo de acción de Curator:

sudo nano /etc/curator/delete-old-logs.yml
actions:
  1:
    action: delete_indices
    description: Delete indices older than 30 days
    options:
      ignore_empty_list: True
    filters:
    - filtertype: pattern
      kind: prefix
      value: syslog-
    - filtertype: age
      source: name
      direction: older
      timestring: '%Y.%m.%d'
      unit: days
      unit_count: 30

Ejecutar curator:

curator --config /etc/curator/curator.yml /etc/curator/delete-old-logs.yml

Monitorear Logstash

Verificar estadísticas de Logstash:

# Estadísticas del nodo
curl -X GET "localhost:9600/_node/stats?pretty"

# Estadísticas del pipeline
curl -X GET "localhost:9600/_node/stats/pipelines?pretty"

# Hilos activos
curl -X GET "localhost:9600/_node/hot_threads?pretty"

Solución de Problemas

Problemas Comunes de Elasticsearch

Verificar logs de Elasticsearch:

sudo journalctl -u elasticsearch -f

# O ver archivos de log
sudo tail -f /var/log/elasticsearch/my-logging-cluster.log

Verificar salud del cluster:

curl -X GET "localhost:9200/_cluster/health?pretty"
curl -X GET "localhost:9200/_cluster/stats?pretty"

Limpiar caché si es necesario:

curl -X POST "localhost:9200/_cache/clear?pretty"

Problemas Comunes de Logstash

Probar configuración del pipeline:

sudo /usr/share/logstash/bin/logstash -t -f /etc/logstash/conf.d/

Ejecutar Logstash en modo debug:

sudo /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/ --log.level=debug

Verificar errores de parseo:

sudo journalctl -u logstash | grep -i "error\|exception"

Conclusión

Elasticsearch y Logstash forman una combinación poderosa para el registro centralizado, proporcionando capacidades escalables de búsqueda, análisis y procesamiento de datos. Siguiendo esta guía, has instalado y configurado una infraestructura de registro lista para producción capaz de manejar logs de múltiples fuentes.

Conclusiones clave:

  1. Arquitectura escalable - Elasticsearch proporciona almacenamiento y búsqueda distribuidos
  2. Procesamiento flexible de datos - Logstash transforma y enriquece datos de log
  3. Múltiples fuentes de entrada - Ingerir logs de archivos, syslog, aplicaciones y más
  4. Ajuste de rendimiento - Optimizar JVM, workers del pipeline y tamaños de lote
  5. Seguridad - Habilitar autenticación, encriptación y controles de acceso

Mejores prácticas para producción:

  • Asignar recursos apropiados basados en el volumen de logs
  • Implementar gestión del ciclo de vida de índices
  • Habilitar características de seguridad y autenticación
  • Monitorear salud y rendimiento del cluster
  • Respaldos regulares de datos de Elasticsearch
  • Usar nodos dedicados para diferentes roles en despliegues más grandes
  • Implementar políticas apropiadas de retención de logs
  • Documentar configuraciones de pipeline

El ELK stack continúa evolucionando con nuevas características y mejoras. Considera integrar Kibana para visualización y Beats para envío ligero de logs para completar tu infraestructura de registro y maximizar las perspectivas operacionales.