Ansible Elasticsearch: Automatiza tu Stack ELK Completo 2025

Ansible Elasticsearch stack ELK automatización DevOps

Ansible Elasticsearch es la solución ideal para automatizar el despliegue y configuración del stack ELK (Elasticsearch, Logstash, Kibana) en tu infraestructura. Con Ansible puedes gestionar clusters de búsqueda y análisis de logs de forma declarativa, reduciendo errores manuales y acelerando despliegues en entornos de producción.

El stack ELK se ha convertido en el estándar de facto para la gestión centralizada de logs y análisis de datos en tiempo real. Elasticsearch proporciona búsqueda y análisis distribuido, Logstash procesa y transforma datos, mientras que Kibana ofrece visualización interactiva. Automatizar este stack con Ansible garantiza configuraciones consistentes y repetibles.

¿Por Qué Usar Ansible Elasticsearch para Automatización?

La automatización del stack ELK con Ansible Elasticsearch ofrece ventajas significativas sobre configuraciones manuales. Las organizaciones que implementan infraestructura como código reportan un 668% de retorno de inversión según estudios de IDC sobre plataformas de automatización.

Los roles de Ansible para Elasticsearch permiten desplegar clusters completos en minutos. La comunidad de Ansible Galaxy proporciona roles probados como geerlingguy.elasticsearch que simplifican enormemente el proceso de instalación y configuración.

Al combinar Ansible Docker Deployment con Elasticsearch, puedes crear entornos de monitorización completamente containerizados. Esta arquitectura facilita la portabilidad y escalabilidad de tus sistemas de observabilidad.

Requisitos Previos para Ansible Elasticsearch

Antes de implementar Ansible Elasticsearch, necesitas cumplir ciertos requisitos técnicos. Tu servidor de control Ansible debe tener Python 3.8 o superior instalado, junto con el paquete ansible-core versión 2.12 o más reciente.

Los nodos donde desplegarás Elasticsearch requieren al menos 4GB de RAM, aunque se recomiendan 8GB o más para entornos productivos. Java JDK 11 o superior es obligatorio, ya que Elasticsearch está construido sobre la JVM.

  • Ansible 2.12 o superior instalado en servidor de control
  • Python 3.8+ en todos los nodos
  • Mínimo 4GB RAM por nodo (8GB recomendado)
  • Java JDK 11 o superior
  • Conectividad SSH entre control y nodos gestionados
  • Puertos 9200 (HTTP) y 9300 (transporte) disponibles

La configuración de acceso SSH sin contraseña mediante claves públicas agiliza enormemente las ejecuciones de playbooks. Asegúrate de configurar tu archivo de inventario con las IPs o nombres DNS correctos de tus servidores objetivo.

Instalación de Roles desde Ansible Galaxy

Ansible Galaxy alberga roles comunitarios de alta calidad para Ansible Elasticsearch. El rol geerlingguy.elasticsearch es ampliamente utilizado y mantenido activamente, con soporte para las versiones más recientes de Elasticsearch 8.x.

# Instalar rol de Elasticsearch desde Galaxy
ansible-galaxy install geerlingguy.elasticsearch

# Instalar rol de Kibana
ansible-galaxy install geerlingguy.kibana

# Instalar rol de Logstash
ansible-galaxy install geerlingguy.logstash

# Instalar rol de Java (dependencia)
ansible-galaxy install geerlingguy.java

Estos roles se descargan automáticamente a tu directorio de roles de Ansible, típicamente ubicado en ~/.ansible/roles/. Puedes verificar la instalación listando el contenido de este directorio.

Alternativamente, puedes definir las dependencias en un archivo requirements.yml para gestionar versiones específicas y facilitar la reproducibilidad en diferentes entornos.

# requirements.yml
---
roles:
  - name: geerlingguy.java
    version: 1.10.0
  - name: geerlingguy.elasticsearch
    version: 4.1.0
  - name: geerlingguy.kibana
    version: 4.1.0
  - name: geerlingguy.logstash
    version: 5.0.0

Luego ejecuta ansible-galaxy install -r requirements.yml para instalar todas las dependencias con las versiones exactas especificadas. Este enfoque es ideal para entornos de integración continua.

Playbook Completo de Ansible Elasticsearch

Este playbook de Ansible Elasticsearch despliega un cluster completo de tres nodos con configuración de alta disponibilidad. Incluye instalación de Java, configuración de memoria heap, y parámetros de seguridad básicos.

---
- name: Desplegar Stack ELK con Ansible Elasticsearch
  hosts: elk_nodes
  become: yes
  vars:
    elasticsearch_version: '8.11'
    elasticsearch_heap_size: '4g'
    elasticsearch_cluster_name: 'produccion-logs'
    elasticsearch_network_host: '0.0.0.0'
    elasticsearch_http_port: 9200
    elasticsearch_discovery_seed_hosts:
      - 'elk-node1:9300'
      - 'elk-node2:9300'
      - 'elk-node3:9300'
    elasticsearch_cluster_initial_master_nodes:
      - 'elk-node1'
      - 'elk-node2'
      - 'elk-node3'

  roles:
    - role: geerlingguy.java
      java_packages:
        - openjdk-11-jdk

    - role: geerlingguy.elasticsearch
      elasticsearch_config:
        cluster.name: "{{ elasticsearch_cluster_name }}"
        node.name: "{{ inventory_hostname }}"
        network.host: "{{ elasticsearch_network_host }}"
        http.port: "{{ elasticsearch_http_port }}"
        discovery.seed_hosts: "{{ elasticsearch_discovery_seed_hosts }}"
        cluster.initial_master_nodes: "{{ elasticsearch_cluster_initial_master_nodes }}"
        bootstrap.memory_lock: true
        xpack.security.enabled: false

  tasks:
    - name: Configurar límites de memoria para Elasticsearch
      lineinfile:
        path: /etc/security/limits.conf
        line: "{{ item }}"
        create: yes
      loop:
        - 'elasticsearch soft memlock unlimited'
        - 'elasticsearch hard memlock unlimited'

    - name: Ajustar vm.max_map_count para Elasticsearch
      sysctl:
        name: vm.max_map_count
        value: '262144'
        state: present
        reload: yes

    - name: Verificar estado del servicio Elasticsearch
      systemd:
        name: elasticsearch
        state: started
        enabled: yes

    - name: Esperar a que Elasticsearch esté disponible
      wait_for:
        host: localhost
        port: 9200
        delay: 10
        timeout: 300

    - name: Verificar salud del cluster
      uri:
        url: "http://localhost:9200/_cluster/health"
        method: GET
        return_content: yes
      register: cluster_health

    - name: Mostrar estado del cluster
      debug:
        msg: "Cluster status: {{ cluster_health.json.status }}, Nodes: {{ cluster_health.json.number_of_nodes }}"

Este playbook configura parámetros críticos como vm.max_map_count que Elasticsearch requiere para manejar grandes cantidades de archivos mapeados en memoria. El ajuste de heap size a 4GB es apropiado para servidores con 8GB de RAM.

Si trabajas con Ansible Kubernetes, puedes integrar esta configuración para desplegar Elasticsearch dentro de clusters de contenedores, aprovechando StatefulSets para persistencia de datos.

Configuración Avanzada de Ansible Elasticsearch

La configuración avanzada de Ansible Elasticsearch incluye parámetros de seguridad, optimización de rendimiento y gestión de índices. Elasticsearch 8.x incorpora seguridad habilitada por defecto, requiriendo configuración de TLS y autenticación.

---
- name: Configuración Avanzada Ansible Elasticsearch
  hosts: elk_master
  become: yes
  vars:
    elasticsearch_security_enabled: true
    elasticsearch_xpack_security_transport_ssl_enabled: true

  tasks:
    - name: Generar certificados SSL para Elasticsearch
      command: >
        /usr/share/elasticsearch/bin/elasticsearch-certutil cert
        --silent --pem --in /tmp/instances.yml
        --out /etc/elasticsearch/certs/certs.zip
      args:
        creates: /etc/elasticsearch/certs/certs.zip

    - name: Configurar contraseña para usuario elastic
      command: >
        /usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto -b
      register: elastic_passwords
      changed_when: false

    - name: Crear política de gestión de índices (ILM)
      uri:
        url: "http://localhost:9200/_ilm/policy/logs-policy"
        method: PUT
        user: elastic
        password: "{{ elasticsearch_password }}"
        body_format: json
        body:
          policy:
            phases:
              hot:
                min_age: "0ms"
                actions:
                  rollover:
                    max_age: "7d"
                    max_size: "50gb"
              warm:
                min_age: "7d"
                actions:
                  allocate:
                    number_of_replicas: 1
              delete:
                min_age: "30d"
                actions:
                  delete: {}

    - name: Configurar template de índice para logs
      uri:
        url: "http://localhost:9200/_index_template/logs-template"
        method: PUT
        user: elastic
        password: "{{ elasticsearch_password }}"
        body_format: json
        body:
          index_patterns: ["logs-*"]
          template:
            settings:
              number_of_shards: 3
              number_of_replicas: 2
              index.lifecycle.name: "logs-policy"
            mappings:
              properties:
                timestamp:
                  type: date
                message:
                  type: text
                level:
                  type: keyword

Las políticas de gestión del ciclo de vida de índices (ILM) automatizan la rotación, compactación y eliminación de datos antiguos. Esto previene el crecimiento descontrolado del cluster y optimiza costos de almacenamiento.

Similar a cómo gestionas Ansible PostgreSQL para backups automatizados, puedes implementar snapshots programados de Elasticsearch para recuperación ante desastres.

Integración de Kibana con Ansible Elasticsearch

Kibana es la interfaz de visualización para Ansible Elasticsearch que permite crear dashboards interactivos y explorar logs en tiempo real. La integración con Ansible garantiza configuración consistente del frontend de análisis.

---
- name: Desplegar Kibana con Ansible
  hosts: kibana_server
  become: yes
  vars:
    kibana_version: '8.11'
    kibana_server_port: 5601
    kibana_server_host: '0.0.0.0'
    kibana_elasticsearch_hosts:
      - 'http://elk-node1:9200'
      - 'http://elk-node2:9200'
      - 'http://elk-node3:9200'

  roles:
    - role: geerlingguy.kibana
      kibana_config:
        server.port: "{{ kibana_server_port }}"
        server.host: "{{ kibana_server_host }}"
        elasticsearch.hosts: "{{ kibana_elasticsearch_hosts }}"
        elasticsearch.username: 'kibana_system'
        elasticsearch.password: "{{ kibana_elasticsearch_password }}"

  tasks:
    - name: Instalar Nginx como reverse proxy
      apt:
        name: nginx
        state: present

    - name: Configurar Nginx para Kibana
      template:
        src: templates/kibana-nginx.conf.j2
        dest: /etc/nginx/sites-available/kibana

    - name: Habilitar configuración de Nginx
      file:
        src: /etc/nginx/sites-available/kibana
        dest: /etc/nginx/sites-enabled/kibana
        state: link

    - name: Reiniciar Nginx
      systemd:
        name: nginx
        state: restarted

Utilizar Nginx como reverse proxy delante de Kibana añade una capa adicional de seguridad y permite implementar autenticación básica HTTP. Para configuraciones más avanzadas, consulta el artículo sobre Ansible Nginx.

Despliegue de Logstash para Procesamiento de Datos

Logstash complementa Ansible Elasticsearch procesando, transformando y enriqueciendo datos antes de indexarlos. Su arquitectura basada en pipelines permite filtrar logs, parsear formatos complejos y agregar campos calculados.

---
- name: Configurar Logstash con Ansible
  hosts: logstash_nodes
  become: yes
  vars:
    logstash_version: '8.11'

  roles:
    - role: geerlingguy.java
    - role: geerlingguy.logstash

  tasks:
    - name: Crear configuración de pipeline de Logstash
      copy:
        dest: /etc/logstash/conf.d/logstash-pipeline.conf
        content: |
          input {
            beats {
              port => 5044
            }
            tcp {
              port => 5000
              codec => json
            }
          }

          filter {
            if [type] == "syslog" {
              grok {
                match => { "message" => "%{SYSLOGLINE}" }
              }
              date {
                match => [ "timestamp", "MMM  d HH:mm:ss", "MMM dd HH:mm:ss" ]
              }
            }

            if [type] == "nginx" {
              grok {
                match => { "message" => "%{COMBINEDAPACHELOG}" }
              }
              geoip {
                source => "clientip"
              }
            }
          }

          output {
            elasticsearch {
              hosts => ["http://elk-node1:9200", "http://elk-node2:9200"]
              index => "logs-%{[type]}-%{+YYYY.MM.dd}"
              user => "logstash_writer"
              password => "{{ logstash_es_password }}"
            }
          }

    - name: Reiniciar Logstash para aplicar cambios
      systemd:
        name: logstash
        state: restarted
        enabled: yes

Los filtros Grok permiten parsear logs no estructurados en campos indexables. La integración de GeoIP enriquece direcciones IP con datos de geolocalización, útil para análisis de tráfico web y detección de amenazas.

Monitorización y Mantenimiento del Cluster

El monitoreo continuo de tu implementación Ansible Elasticsearch es crucial para garantizar disponibilidad y rendimiento. Las APIs de Elasticsearch proporcionan métricas detalladas sobre salud del cluster, uso de recursos y rendimiento de índices.

---
- name: Tareas de Mantenimiento Elasticsearch
  hosts: elk_master
  become: yes

  tasks:
    - name: Verificar salud del cluster
      uri:
        url: "http://localhost:9200/_cluster/health?pretty"
        method: GET
      register: health_check

    - name: Alertar si cluster no está en verde
      fail:
        msg: "Cluster health is {{ health_check.json.status }}"
      when: health_check.json.status != "green"

    - name: Verificar uso de disco en nodos
      uri:
        url: "http://localhost:9200/_cat/allocation?v"
        method: GET
      register: disk_usage

    - name: Listar índices grandes
      uri:
        url: "http://localhost:9200/_cat/indices?v&s=store.size:desc"
        method: GET
      register: large_indices

    - name: Forzar merge de segmentos en índices viejos
      uri:
        url: "http://localhost:9200/logs-{{ item }}/_forcemerge?max_num_segments=1"
        method: POST
      loop:
        - "2024.01"
        - "2024.02"
        - "2024.03"
      when: optimize_old_indices | default(false)

    - name: Configurar snapshot repository
      uri:
        url: "http://localhost:9200/_snapshot/backup_repo"
        method: PUT
        body_format: json
        body:
          type: "fs"
          settings:
            location: "/mnt/elasticsearch_backups"
            compress: true

Los snapshots incrementales permiten backups eficientes sin detener el servicio. Programa ejecuciones diarias mediante cron o integra con herramientas como ArgoCD Kubernetes para orquestación avanzada.

Optimización de Rendimiento para Producción

La optimización de Ansible Elasticsearch en producción requiere ajustes específicos de JVM, configuración de discos y tuning de índices. El rendimiento depende críticamente de la arquitectura de hardware y patrones de uso.

  • Heap Size JVM: Configura 50% de RAM disponible, máximo 31GB debido a compressed oops
  • Almacenamiento: Usa SSD para data directories, especialmente en workloads de escritura intensiva
  • Sharding: Calcula 20-50GB por shard, evita over-sharding que impacta rendimiento
  • Replicas: Mínimo 1 réplica por índice crítico para alta disponibilidad
  • Refresh Interval: Aumenta de 1s a 30s para ingestión masiva de datos
  • Merge Policy: Ajusta para reducir I/O en horarios de bajo tráfico

Monitorea constantemente las métricas de threadpool, especialmente search y write queues. Si observas rechazos frecuentes, considera escalar horizontalmente añadiendo más nodos data al cluster.

Seguridad en Ansible Elasticsearch 8.x

Elasticsearch 8.x introdujo seguridad habilitada por defecto, requiriendo TLS y autenticación para todas las comunicaciones. Ansible Elasticsearch debe configurar certificados, usuarios y roles apropiadamente.

---
- name: Configuración de Seguridad Elasticsearch 8.x
  hosts: elk_nodes
  become: yes

  tasks:
    - name: Crear directorio para certificados
      file:
        path: /etc/elasticsearch/certs
        state: directory
        owner: elasticsearch
        group: elasticsearch
        mode: '0750'

    - name: Generar CA certificate
      command: >
        /usr/share/elasticsearch/bin/elasticsearch-certutil ca
        --out /etc/elasticsearch/certs/elastic-stack-ca.p12
        --pass ""
      args:
        creates: /etc/elasticsearch/certs/elastic-stack-ca.p12

    - name: Generar certificados de nodo
      command: >
        /usr/share/elasticsearch/bin/elasticsearch-certutil cert
        --ca /etc/elasticsearch/certs/elastic-stack-ca.p12
        --out /etc/elasticsearch/certs/{{ inventory_hostname }}.p12
        --pass ""
      args:
        creates: /etc/elasticsearch/certs/{{ inventory_hostname }}.p12

    - name: Configurar TLS en elasticsearch.yml
      blockinfile:
        path: /etc/elasticsearch/elasticsearch.yml
        block: |
          xpack.security.enabled: true
          xpack.security.transport.ssl.enabled: true
          xpack.security.transport.ssl.verification_mode: certificate
          xpack.security.transport.ssl.keystore.path: certs/{{ inventory_hostname }}.p12
          xpack.security.transport.ssl.truststore.path: certs/{{ inventory_hostname }}.p12
          xpack.security.http.ssl.enabled: true
          xpack.security.http.ssl.keystore.path: certs/{{ inventory_hostname }}.p12

    - name: Configurar roles personalizados
      uri:
        url: "https://localhost:9200/_security/role/logs_writer"
        method: PUT
        user: elastic
        password: "{{ elasticsearch_password }}"
        validate_certs: no
        body_format: json
        body:
          cluster: ["monitor", "manage_ilm"]
          indices:
            - names: ["logs-*"]
              privileges: ["create_index", "write", "create"]

Implementa el principio de mínimo privilegio creando usuarios específicos para cada aplicación. Nunca uses el usuario elastic en aplicaciones; resérvalo exclusivamente para administración.

Troubleshooting Común en Ansible Elasticsearch

Los problemas más frecuentes en implementaciones de Ansible Elasticsearch incluyen errores de memoria, fallos de conectividad entre nodos y problemas de permisos de archivos.

Error: memory locking requested for elasticsearch process but memory is not locked – Verifica que vm.max_map_count esté configurado correctamente y que los límites en /etc/security/limits.conf estén aplicados. Requiere reinicio del servicio.

Cluster stuck in yellow status – Generalmente indica réplicas no asignadas. Verifica que tengas suficientes nodos data para satisfacer el número configurado de réplicas. Usa la API _cluster/allocation/explain para diagnóstico detallado.

High CPU usage on master nodes – Masters no deben gestionar datos ni queries. Configura nodos dedicados con node.roles específicos: master, data, ingest, ml separadamente según carga de trabajo.

# Comandos útiles de troubleshooting
curl -X GET "localhost:9200/_cluster/health?pretty"
curl -X GET "localhost:9200/_cat/nodes?v"
curl -X GET "localhost:9200/_cat/shards?v&s=state"
curl -X GET "localhost:9200/_cluster/allocation/explain?pretty"
curl -X GET "localhost:9200/_nodes/stats?pretty"

Preguntas Frecuentes sobre Ansible Elasticsearch

¿Cuántos nodos necesito para un cluster Elasticsearch en producción?

Un cluster productivo de Ansible Elasticsearch requiere mínimo 3 nodos master-eligible para evitar split-brain. Para alta disponibilidad, se recomienda arquitectura de 3 masters dedicados más 2+ nodos data. Clusters pequeños pueden usar 3 nodos multi-rol.

¿Puedo ejecutar Ansible Elasticsearch en contenedores Docker?

Sí, Elasticsearch funciona perfectamente en Docker. Combina roles de Ansible con módulos docker_container o usa docker-compose. Asegúrate de configurar vm.max_map_count en el host y montar volúmenes persistentes para /usr/share/elasticsearch/data.

¿Qué diferencia hay entre Elasticsearch 7.x y 8.x?

Elasticsearch 8.x habilita seguridad por defecto (TLS y autenticación obligatorios), elimina tipos de mapeo completamente, y mejora rendimiento de búsquedas vector. Migrar desde 7.x requiere planificación cuidadosa de certificados y credenciales.

¿Cómo escalo horizontalmente mi cluster Elasticsearch?

Añade nodos data al inventario de Ansible y ejecuta el playbook. Elasticsearch redistribuye shards automáticamente. Para control preciso, ajusta cluster.routing.allocation settings. Monitorea el rebalanceo con _cat/recovery para evitar saturar la red.

¿Necesito Logstash o puedo enviar datos directamente a Elasticsearch?

Para logs simples, herramientas como Filebeat pueden enviar directamente a Ansible Elasticsearch. Logstash añade valor cuando necesitas transformaciones complejas, múltiples fuentes de datos, o enriquecimiento con lookups externos y filtros avanzados de parsing.

Avatar

Por Mid

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x