10 abr 2024

Logstash, Elastic Search y Kibana en Docker Container para Dev

  En fechas recientes he contado con el tiempo suficiente para realizar alguna prueba de concepto con tecnologías con las que no he estado en contacto. Por ejemplo, he estado "jugado" con Java Spring y Spring Boot. En ese contexto me encontré con el stack ELK, es decir, Logstash, Elastic Search y Kibana.  

  Yo tengo un par de microservicios muy simples que generan logs y la idea es enviar estos logs a Logstash (un pipeline que recoge, parsea y trasforma datos de diferentes fuentes), que este los envíe a Elastic Search para su almacenamiento (documentos NoSQL) y utilizar Kibana como visualizador de la información almacenada. Mi idea es realizar todo este procesamiento en mi máquina local, mi ambiente de desarrollo, sin instalar ningún componente, si no utilizando contenedores de Docker para todo el stack ELK.  

  Voy a realizar este proceso de forma muy manual sin utilizar Docker Compose, Todos los comandos siguientes los ejecute en una consola de powershell. Comencemos:  

  Paso 1: bajar las imágenes docker de todos los componentes:  

  Elastic Search:  

	docker pull docker.elastic.co/elasticsearch/elasticsearch:8.7.0    

  Logstash:  

	docker pull docker.elastic.co/logstash/logstash:8.13.0    

  Kibana:    

	docker pull docker.elastic.co/kibana/kibana:8.7.0    

  Paso 2: Crear una red en docker  

  Para que todos los componentes del stack ELK se puede comunicar entre si de una mejor manera es recomendable crear una red en docker para ellos. Esto se logra con el siguiente comando:  

		docker network create elk    

  Donde elk es el nombre que le di a la red.  

  Si quisiéramos inspeccionar que elementos, contenedores se están ejecutado en la red se puede utilizar el comando  

	docker inspect elk    

  y si quisiéramos eliminar la red utilizaríamos el comando  

	docker network rm elk 

Paso 3: Ejecutar el contenedor de Elastic Search

  Para ejecutar el contenedor de Search ejecuto el siguiente comando:  

	docker run -it --rm --name=elasticsearch --net elk -p 9200:9200 -p 9300:9300 --net-alias=elasticsearch -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:8.7.0
    

  El parámetro -it (interactive) es para poder ver los logs del proceso de arranque de Elastic Search y poder ejecutar Ctrl + C directamente en la consola para detener el contenedor. El parámetro --rm eliminará el contenedor automáticamente una vez se detenga este se detenga. Como alternativa se podría reemplazar ambos parámetros por -d para que el contenedor se ejecute como un Daemon y detenerlo con docker stop y la siguiente vez usar docker start en lugar de docker run.  

  Además podemos constatar que esta usando la misma red (elk) que generamos anteriormente por medio del parámetro --net.    

  Cuando el contenedor de Elastic Search esté listo en la consola veremos algo similar a esto:  


 Aquí podemos ver el password generado automáticamente para el usuario elastic y el enrollment token necesario para Kibana. Si no hubiéramos usado el parámetro -it (usando -d en su lugar) podemos generar ambos datos usando el siguiente procedimiento:  

  Ingresamos al bash de contenedor de Elastic search:  

	docker exec -it elasticsearch /bin/bash    

  una vez dentro del bash podemos ejecutar el siguiente comando para generar los passwords para los diferentes usuarios:  

	./bin/elasticsearch-setup-passwords auto    

  o este otro para obtener el enrollment token para Kibana:  

	./bin/elasticsearch-create-enrollment-token -s kibana    

  Paso 4: Preparar y ejecutar el contenedor docker de Logstash  

  El contenedor de Logstash requiere una preparación previa. Elastic Search por defecto tiene activada la comunicación SSL por lo que debemos comunicarnos usando https y para esto ocupamos el certificado correspondiente, Este lo podemos obtener ejecutando el siguiente comando:  

	docker cp elasticsearch:/usr/share/elasticsearch/config/certs/http_ca.crt 'd:/proyectos foy/docker/logstash/certificates/http_ca.crt'

 Con lo que estamos copiando el certificado http_ca.crt a una carpeta en mi maquina llamada d:/proyectos foy/docker/logstash/  

  El siguiente paso es crear un archivo de configuración para logstash llamado logstash.conf el cual yo lo ubique en la carpeta 'd:/proyectos foy/docker/logstash/’ el contenido de este archivo es el siguiente  

    input {
      http {
        port => 5000
        codec => json_lines
      }
    }

    filter {
      mutate {
        remove_field => ["@timestamp", "@version"]
      }
    }

    output {
      elasticsearch {
        hosts => ["https://elasticsearch:9200"]
        index => "microservices-%{+YYYY.MM.dd}"
        ssl => true
        cacert => "/usr/share/logstash/certificates/http_ca.crt"
        user => "elastic" 
        password => "contraseñagenerada”
        ssl_certificate_verification => false 
      }
      stdout {
        codec => rubydebug
      }
    }

  Esa configuración nos indica que Logstash estará escuchando en el puerto 5000 por elementos de tipo JSON. Eliminará un par de elementos del JSON si estos vienen y los pasara a Elastic Search. Es importante notar que hay que reemplazar la contraseña por la que se generó en el paso anterior y que la ruta en cacert no es la ruta dentro de mi maquina si no la ruta dentro del container. 

  El campo index indica que se creara un índice en Elastic Search por día llamado “microservices-fecha de los logs”  

  Ya con todo esto preparado podemos finalmente ejecutar el comando para levantar el contenedor de Logstash:  

	docker run -it --rm --name logstash --net elk -p 5044:5044 -v 'D:\Proyectos Foy\Docker\Logstash\certificates:/usr/share/logstash/certificates' -v 'D:\Proyectos Foy\Docker\Logstash\logstash.conf:/usr/share/logstash/pipeline/logstash.conf' docker.elastic.co/logstash/logstash:8.13.0    

  En este comando por medio del parámetro para volúmenes -v le asignamos tanto la dirección del certificado como del archivo de configuración.  

  Si una vez iniciado el container recibimos logs de este tipo:  

    Es normal ya que el licensechecker.licensereader trata de leer si el Elastic Search está configurado con una licencia válida y de momento sólo tenemos una licencia gratuita por lo que no nos preocuparemos por esos mensajes.    

  Además, con este contenedor ejecutándose podemos probar con una herramienta como HTTPie si Logstash está recibiendo los mensajes, por ejemplo con la instrucción:  

	http POST localhost:5000 --json '{"message": "Hola Logstash!"}'    

  en los logs de Logstash veremos algo como esto:            


  Paso 5: Ejecutar el Container de Kibana  

  Hemos llegado al paso final que consiste en levantar el container de Kibana y jugar con su UI. Para ejecutar su container corremos el siguiente comando:  

	docker run -it --rm --name kibana --net elk -p 5601:5601 docker.elastic.co/kibana/kibana:8.7.0    

  Al final de su ejecución veremos algo similar a esto:  

   


  Vamos a la ruta http://localhost:5601/?code=el_que_nos_indique y vamos a ver una interfaz a la siguiente donde nos solicita el enrollment token que vimos en el paso 2            


  Una vez ingresemos el token le damos clic en el botón “Configure Elastic”:            


  Aquí nos pedirá el usuario, donde ingresaremos elastic y el password que también lo obtuvimos en el Paso 2 y damos al botón Log in e ingresamos en la interfaz de Kibana donde buscaremos en el menú la opción de Discovery:         


  Si ya contamos con datos en nuestro Elastic Search (como nuestro mensaje de prueba) nos aparecerá una pantalla como esta en la que se nos solicita crear un DataView            


  En este caso vamos a crear uno muy simple:            


  Y damos clic en el botón Save data view to Kibana. Ya con esto vamos a poder ver la información de los logs que se estén enviando a Logstash y que se almacenan en Elastic Search pudiendo usar el lengua KQL para hacer consultas:            


  Ya en este punto lo que queda es configurar los microservicios para que envíen sus logs a Logstash para consultarlos por medio de Kibana. Ya el stack ELK completo esta ejecutándose correctamente de manera local a través de los docker containers.  

   

	
	
	
    

Roy {aka. Foy}

Autor & Editor

Desarrallador y líder técnico, con experiencia en tecnologías Microsoft desde los tiempos del VB6 y el asp clásico hasta el .Net Core, pasando por COM+, javascript, angularjs, Ionic, xaml, cordova, MVC, Web Api, Sql Server, Oracle... . Ávido lector, apasionado programador.