Update elastic stack test

This commit is contained in:
Manuel Vergara 2024-08-07 19:56:05 +02:00
parent 89959d29ee
commit 4756d756ac
8 changed files with 423 additions and 7 deletions

View File

@ -0,0 +1,191 @@
# Cómo Usar Elasticsearch en Python con Docker
**Índice**
- [Cómo Usar Elasticsearch en Python con Docker](#cómo-usar-elasticsearch-en-python-con-docker)
- [¿Qué es Elasticsearch?](#qué-es-elasticsearch)
- [Requisitos Previos](#requisitos-previos)
- [Crear un Clúster Local del Elastic Stack con Docker Compose](#crear-un-clúster-local-del-elastic-stack-con-docker-compose)
- [Desplegar el Elastic Stack](#desplegar-el-elastic-stack)
- [Dockerizar el Programa Python](#dockerizar-el-programa-python)
- [Programa Python](#programa-python)
- [Conectar a Tu Clúster desde el Contenedor Python](#conectar-a-tu-clúster-desde-el-contenedor-python)
- [Ejecutar los Scripts Python en Docker](#ejecutar-los-scripts-python-en-docker)
- [Construir y Ejecutar el Contenedor Python](#construir-y-ejecutar-el-contenedor-python)
- [Visualización de Datos con Kibana](#visualización-de-datos-con-kibana)
- [Usar Logstash para Ingestión de Datos](#usar-logstash-para-ingestión-de-datos)
- [Recopilar Métricas con Metricbeat](#recopilar-métricas-con-metricbeat)
- [Eliminar Documentos del Índice](#eliminar-documentos-del-índice)
- [Eliminar un Índice](#eliminar-un-índice)
- [Conclusión](#conclusión)
[Elasticsearch](https://www.elastic.co/elasticsearch/) (ES) es una tecnología utilizada por muchas empresas, incluyendo GitHub, Uber y Facebook. Aunque no se enseña con frecuencia en cursos de Ciencia de Datos, es probable que te encuentres con ella en tu carrera profesional.
Muchos científicos de datos enfrentan dificultades al configurar un entorno local o al intentar interactuar con Elasticsearch en Python. Además, no hay muchos recursos actualizados disponibles.
Por eso, decidí crear este tutorial. Te enseñará lo básico y podrás configurar un clúster de Elasticsearch en tu máquina para el desarrollo local rápidamente. También aprenderás a crear un índice, almacenar datos en él y usarlo para buscar información.
¡Vamos a empezar!
## ¿Qué es Elasticsearch?
Elasticsearch es un motor de búsqueda distribuido, rápido y fácil de escalar, capaz de manejar datos textuales, numéricos, geoespaciales, estructurados y no estructurados. Es un motor de búsqueda popular para aplicaciones, sitios web y análisis de registros. También es un componente clave del Elastic Stack (también conocido como ELK Stack), que incluye Logstash y Kibana, junto con Beats para la recolección de datos.
Para entender el funcionamiento interno de Elasticsearch, piensa en él como dos procesos distintos. Uno es la ingestión, que normaliza y enriquece los datos brutos antes de indexarlos usando un [índice invertido](https://www.elastic.co/guide/en/elasticsearch/reference/current/documents-indices.html). El segundo es la recuperación, que permite a los usuarios recuperar datos escribiendo consultas que se ejecutan contra el índice.
Eso es todo lo que necesitas saber por ahora. A continuación, prepararás tu entorno local para ejecutar un clúster del Elastic Stack.
## Requisitos Previos
Debes configurar algunas cosas antes de comenzar. Asegúrate de tener lo siguiente listo:
1. Instala Docker y Docker Compose.
2. Descarga los datos necesarios.
## Crear un Clúster Local del Elastic Stack con Docker Compose
Para desplegar el Elastic Stack (Elasticsearch, Kibana, Logstash y Beats) en tu máquina local, utilizaremos Docker Compose. Este enfoque simplifica el despliegue y la administración de múltiples servicios.
Mediante el fichero [docker-compose.yaml](docker-compose.yaml) vamos a configurar los servicios para Elasticsearch, Kibana, Logstash, Metricbeat, y la aplicación Python, todos conectados a una red llamada `elastic`.
### Desplegar el Elastic Stack
Para iniciar los servicios, abre una terminal en el directorio donde se encuentra `docker-compose.yml` y ejecuta el siguiente comando:
```bash
docker compose up -d
```
Este comando iniciará Elasticsearch, Kibana, Logstash, Metricbeat y la aplicación Python en contenedores separados. Aquí tienes un desglose de los servicios:
- **Elasticsearch**: El motor de búsqueda que almacena y analiza los datos.
- **Kibana**: Una interfaz de usuario para visualizar y explorar datos en Elasticsearch.
- **Logstash**: Una herramienta de procesamiento de datos que ingiere datos desde múltiples fuentes, los transforma y los envía a un destino como Elasticsearch.
- **Metricbeat**: Un agente de monitoreo que recopila métricas del sistema y las envía a Elasticsearch.
- **Python App**: Un contenedor que ejecutará tus scripts de Python para interactuar con Elasticsearch. (Hasta que no construyamos el contenedor, este servicio fallará).
## Dockerizar el Programa Python
Para dockerizar la aplicación Python, utilizaremos el archivo [Dockerfile](./app/Dockerfile) del directorio `app`. El directorio `app` también debe contener el programa Python y un archivo [requirements.txt](./app/requirements.txt) para manejar las dependencias.
### Programa Python
El archivo [main.py](./app/main.py) en el directorio `app` manejará la conexión a Elasticsearch, la creación de índices y la carga de datos.
Este programa realiza las siguientes acciones:
1. **Crea un índice** en Elasticsearch con las configuraciones de mapeo necesarias.
2. **Carga datos** desde un archivo CSV (`wiki_movie_plots_deduped.csv`) al índice creado.
## Conectar a Tu Clúster desde el Contenedor Python
Tu aplicación Python se conectará al clúster de Elasticsearch usando el hostname `elasticsearch`, que es el nombre del servicio definido en `docker-compose.yml`.
## Ejecutar los Scripts Python en Docker
Una vez que hayas creado los archivos `Dockerfile`, `requirements.txt` y `main.py`, puedes construir la imagen de Docker para tu aplicación Python y ejecutarla usando Docker Compose.
### Construir y Ejecutar el Contenedor Python
1. Construye la imagen de Docker para tu aplicación Python:
```bash
docker compose build python-app
```
2. Ejecuta el contenedor:
```bash
docker compose up python-app
```
La aplicación Python se ejecutará y cargará los datos en Elasticsearch. Puedes verificar que los datos se hayan indexado correctamente ejecutando una consulta en Elasticsearch o usando Kibana para explorar los datos:
```python
es.search(index="movies", body={"query": {"match_all": {}}})
```
## Visualización de Datos con Kibana
Kibana es una herramienta de visualización que se conecta a Elasticsearch y te permite explorar y visualizar tus datos.
Para acceder a Kibana, abre un navegador web y navega a `http://localhost:5601`. Deberías ver la interfaz de Kibana, donde puedes crear visualizaciones y dashboards.
1. **Crea un índice en Kibana**: Ve a *Management > Index Patterns* y crea un nuevo patrón de índice para el índice `movies`.
2. **Explora tus datos**: Usa la herramienta *Discover* para buscar y explorar los datos que has indexado.
3. **Crea visualizaciones**: En la sección *Visualize*, crea gráficos y tablas que te permitan entender mejor tus datos.
## Usar Logstash para Ingestión de Datos
Logstash es una herramienta para procesar y transformar datos antes de enviarlos a Elasticsearch. Aquí tienes un ejemplo básico de cómo configurar Logstash para que procese y envíe datos a Elasticsearch.
Mediante el archivo de configuración en la carpeta `logstash-config/` llamado [pipeline.conf](./logstash-config/pipeline.conf) realizaremos los siguientes pasos:
- Lee un archivo CSV de entrada.
- Usa el filtro `csv` para descomponer cada línea en campos separados.
- Usa `mutate` para convertir el año de lanzamiento en un número entero.
- Envía los datos procesados a Elasticsearch.
Para usar Logstash con esta configuración, asegúrate de que el archivo `wiki_movie_plots_deduped.csv` esté accesible en tu sistema y modifica la ruta en el archivo de configuración según sea necesario. Luego, reinicia el contenedor de Logstash para aplicar los cambios.
```bash
docker compose restart logstash
```
## Recopilar Métricas con Metricbeat
Metricbeat es un agente ligero que recopila métricas del sistema y las envía a Elasticsearch. Está configurado en el archivo `docker-compose.yml` que has creado anteriormente.
Para ver las métricas en Kibana:
1. **Configura Metricbeat**: Edita el archivo de configuración de Metricbeat si necesitas recopilar métricas específicas.
2. **Importa dashboards preconfigurados**: En Kibana, navega a *Add Data > Metricbeat* y sigue las instrucciones para importar los dashboards preconfigurados.
3. **Explora las métricas**: Usa los dashboards importados para explorar las métricas de tu sistema.
## Eliminar Documentos del Índice
Puedes usar el siguiente código para eliminar documentos del índice:
```python
es.delete(index="movies", id="2500")
```
El código anterior eliminará el documento con ID 2500 del índice `movies`.
## Eliminar un Índice
Finalmente, si por alguna razón deseas eliminar un índice (y todos sus documentos), aquí te mostramos cómo hacerlo:
```python
es.indices.delete(index='movies')
```
## Conclusión
Este tutorial te enseñó los conceptos básicos de Elasticsearch y cómo usarlo junto con el Elastic Stack y Docker. Esto será útil en tu carrera, ya que seguramente te encontrarás con Elasticsearch en algún momento.
En este tutorial, has aprendido:
- Cómo configurar un clúster del Elastic Stack en tu máquina usando Docker Compose.
- Cómo dockerizar una aplicación Python para interactuar con Elasticsearch.
- Cómo crear un índice y almacenar datos en él.
- Cómo buscar tus datos usando Elasticsearch.
- Cómo visualizar datos con Kibana.
- Cómo procesar datos con Logstash.
- Cómo recopilar métricas con Metricbeat.
Explora más funcionalidades de Elasticsearch y el Elastic Stack para sacar el máximo provecho de tus datos.

View File

@ -0,0 +1,15 @@
# Usa la imagen base de Python
FROM python:3.9-slim
# Establece el directorio de trabajo
WORKDIR /app
# Copia el archivo requirements.txt e instala las dependencias
COPY requirements.txt /app/
RUN pip install --no-cache-dir -r requirements.txt
# Copia el código fuente a /app
COPY . /app/
# Comando para ejecutar la aplicación
CMD ["python", "main.py"]

View File

@ -0,0 +1,114 @@
import pandas as pd
from elasticsearch import Elasticsearch
from elasticsearch.helpers import bulk
# Configura la conexión a Elasticsearch
es = Elasticsearch("http://elasticsearch:9200")
def create_index():
"""
Crea un índice en Elasticsearch con el nombre 'movies' si no existe.
Define el mapeo del índice para los campos de los documentos.
"""
# Define el mapeo del índice 'movies'
mappings = {
"properties": {
# Campo para el título de la película
"title": {"type": "text", "analyzer": "english"},
# Campo para la etnicidad
"ethnicity": {"type": "text", "analyzer": "standard"},
# Campo para el director
"director": {"type": "text", "analyzer": "standard"},
# Campo para el elenco
"cast": {"type": "text", "analyzer": "standard"},
# Campo para el género
"genre": {"type": "text", "analyzer": "standard"},
# Campo para el argumento de la película
"plot": {"type": "text", "analyzer": "english"},
# Campo para el año de lanzamiento
"year": {"type": "integer"},
# Campo para la página de Wikipedia
"wiki_page": {"type": "keyword"}
}
}
# Verifica si el índice 'movies' ya existe
if not es.indices.exists(index="movies"):
# Crea el índice 'movies' si no existe
es.indices.create(index="movies", mappings=mappings)
print("\n[+] Índice 'movies' creado.")
else:
print("\n[!] El índice 'movies' ya existe.")
def load_data():
"""
Carga datos desde un archivo CSV a Elasticsearch.
"""
try:
# Lee el archivo CSV
df = pd.read_csv("/app/wiki_movie_plots_deduped.csv", quoting=1)
# Verifica el número de filas en el DataFrame
num_rows = len(df)
sample_size = min(5000, num_rows)
# Elimina filas con valores nulos y toma una muestra
df = df.dropna().sample(sample_size, random_state=42).reset_index(drop=True)
except Exception as e:
print(f"\n[!] Error al leer el archivo CSV: {e}")
return
# Prepara los datos para la carga en Elasticsearch
bulk_data = [
{
"_index": "movies", # Nombre del índice en Elasticsearch
"_id": i, # ID del documento en Elasticsearch
"_source": {
"title": row["Title"], # Título de la película
"ethnicity": row["Origin/Ethnicity"], # Etnicidad
"director": row["Director"], # Director
"cast": row["Cast"], # Elenco
"genre": row["Genre"], # Género
"plot": row["Plot"], # Argumento
"year": row["Release Year"], # Año de lanzamiento
"wiki_page": row["Wiki Page"], # Página de Wikipedia
}
}
for i, row in df.iterrows() # Itera sobre cada fila del DataFrame
]
try:
# Carga los datos en Elasticsearch en bloques
bulk(es, bulk_data)
print("\n[+] Datos cargados en Elasticsearch.")
except Exception as e:
print(f"\n[!] Error al cargar datos en Elasticsearch: {e}")
def main():
"""
Función principal que crea el índice y carga los datos.
"""
create_index() # Crea el índice en Elasticsearch
load_data() # Carga los datos en Elasticsearch
if __name__ == "__main__":
# Ejecuta la función principal si el script se ejecuta directamente
main()

View File

@ -0,0 +1,3 @@
pandas==2.0.1
numpy==1.24.2
elasticsearch==8.8.0

View File

@ -0,0 +1,7 @@
Title,Origin/Ethnicity,Director,Cast,Genre,Plot,Release Year,Wiki Page
The Shawshank Redemption,American,Frank Darabont,"Tim Robbins, Morgan Freeman",Drama,"Two imprisoned men bond over a number of years, finding solace and eventual redemption through acts of common decency.",1994,https://en.wikipedia.org/wiki/The_Shawshank_Redemption
The Godfather,American,Francis Ford Coppola,"Marlon Brando, Al Pacino",Crime,"The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son.",1972,https://en.wikipedia.org/wiki/The_Godfather
The Dark Knight,American,Christopher Nolan,"Christian Bale, Heath Ledger",Action,"When the menace known as the Joker emerges from his mysterious past, he wreaks havoc and chaos on the people of Gotham.",2008,https://en.wikipedia.org/wiki/The_Dark_Knight
Pulp Fiction,American,Quentin Tarantino,"John Travolta, Uma Thurman",Crime,"The lives of two mob hitmen, a boxer, a gangster's wife, and a pair of diner bandits intertwine in four tales of violence and redemption.",1994,https://en.wikipedia.org/wiki/Pulp_Fiction
The Lord of the Rings: The Return of the King,American,Peter Jackson,"Elijah Wood, Viggo Mortensen",Fantasy,"The final battle for Middle-earth begins. The forces of good and evil are drawn into a confrontation and the outcome will determine the fate of the world.",2003,https://en.wikipedia.org/wiki/The_Lord_of_the_Rings:_The_Return_of_the_King
Inception,American,Christopher Nolan,"Leonardo DiCaprio, Joseph Gordon-Levitt",Sci-Fi,"A thief who enters the dreams of others to steal secrets from their subconscious is given the inverse task of planting an idea into the mind of a CEO.",2010,https://en.wikipedia.org/wiki/Inception
1 Title Origin/Ethnicity Director Cast Genre Plot Release Year Wiki Page
2 The Shawshank Redemption American Frank Darabont Tim Robbins, Morgan Freeman Drama Two imprisoned men bond over a number of years, finding solace and eventual redemption through acts of common decency. 1994 https://en.wikipedia.org/wiki/The_Shawshank_Redemption
3 The Godfather American Francis Ford Coppola Marlon Brando, Al Pacino Crime The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son. 1972 https://en.wikipedia.org/wiki/The_Godfather
4 The Dark Knight American Christopher Nolan Christian Bale, Heath Ledger Action When the menace known as the Joker emerges from his mysterious past, he wreaks havoc and chaos on the people of Gotham. 2008 https://en.wikipedia.org/wiki/The_Dark_Knight
5 Pulp Fiction American Quentin Tarantino John Travolta, Uma Thurman Crime The lives of two mob hitmen, a boxer, a gangster's wife, and a pair of diner bandits intertwine in four tales of violence and redemption. 1994 https://en.wikipedia.org/wiki/Pulp_Fiction
6 The Lord of the Rings: The Return of the King American Peter Jackson Elijah Wood, Viggo Mortensen Fantasy The final battle for Middle-earth begins. The forces of good and evil are drawn into a confrontation and the outcome will determine the fate of the world. 2003 https://en.wikipedia.org/wiki/The_Lord_of_the_Rings:_The_Return_of_the_King
7 Inception American Christopher Nolan Leonardo DiCaprio, Joseph Gordon-Levitt Sci-Fi A thief who enters the dreams of others to steal secrets from their subconscious is given the inverse task of planting an idea into the mind of a CEO. 2010 https://en.wikipedia.org/wiki/Inception

View File

@ -0,0 +1,59 @@
version: '3.8'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.15.2
container_name: elasticsearch
environment:
- discovery.type=single-node
- xpack.security.enabled=false
ports:
- "9200:9200"
networks:
- elastic
kibana:
image: docker.elastic.co/kibana/kibana:7.15.2
container_name: kibana
environment:
ELASTICSEARCH_HOSTS: http://elasticsearch:9200
ports:
- "5601:5601"
networks:
- elastic
logstash:
image: docker.elastic.co/logstash/logstash:7.15.2
container_name: logstash
volumes:
- ./logstash-config/:/usr/share/logstash/pipeline/
environment:
LS_JAVA_OPTS: "-Xmx256m -Xms256m"
ports:
- "5000:5000"
- "9600:9600"
networks:
- elastic
metricbeat:
image: docker.elastic.co/beats/metricbeat:7.15.2
container_name: metricbeat
command: metricbeat -e -E output.elasticsearch.hosts=["http://elasticsearch:9200"]
depends_on:
- elasticsearch
networks:
- elastic
python-app:
build:
context: ./app
dockerfile: Dockerfile
container_name: python-app
volumes:
- ./app:/app
networks:
- elastic
networks:
elastic:
driver: bridge

View File

@ -0,0 +1,26 @@
input {
file {
path => "/path/to/your/data/wiki_movie_plots_deduped.csv"
start_position => "beginning"
sincedb_path => "/dev/null"
}
}
filter {
csv {
separator => ","
columns => ["Release Year", "Title", "Origin/Ethnicity", "Director", "Cast", "Genre", "Wiki Page", "Plot"]
}
mutate {
convert => { "Release Year" => "integer" }
}
}
output {
elasticsearch {
hosts => ["http://elasticsearch:9200"]
index => "movies"
}
stdout { codec => rubydebug }
}

View File

@ -6,10 +6,11 @@
</div>
| Nombre | Descripción | Nivel |
| --------------------------------- | --------------------------------------------------- | ---------- |
| [redis](./01_redis_flask_docker/) | Despliegue de un contenedor de redis y flask | Básico |
| [rabbit](./02_rabbitmq/README.md) | Despliegue de distintas arquitecturas para rabbitmq | Intermedio |
| Apache Kafka (proximamente) | Despliegue de un contenedor de Apache Kafka | Básico |
| Prometheus Grafana (proximamente) | Despliegue de un contenedor de Prometheus Grafana | Básico |
| SonarQube (proximamente) | Despliegue de un contenedor de SonarQube | Básico |
| Nombre | Descripción | Nivel |
| -------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | ---------- |
| [redis](./01_redis_flask_docker/) | Despliegue de un contenedor de redis y flask | Básico |
| [rabbit](./02_rabbitmq/README.md) | Despliegue de distintas arquitecturas para rabbitmq | Intermedio |
| Apache Kafka (próximamente) <!-- [Apache Kafka](./03_kafka/README.md) --> | Despliegue de Apache Kafka con productor y consumidor | Básico |
| [Elastic stack](./04_elastic_stack/README.md) | Despliegue de Elastic Stack | Básico |
| Prometheus Grafana (proximamente) <!-- [Prometheus Grafana](./05_prometheus_grafana/README.md) --> | Despliegue de un contenedor de Prometheus Grafana | Básico |
| SonarQube (proximamente) <!-- [SonarQube](./06_sonarqube/README.md) --> | Despliegue de un contenedor de SonarQube | Básico |