¿Estás visitando desde Argentina?
Ingresá a Linware Argentina ⯈
Continuar en Linware Argentina ⯈
×
¿Qué estás buscando?
BUSCAR!
BLOG
Precargue Elasticsearch con su conjunto de datos
Publicada el 03/10/2023

Sinceramente, esto no es lo ideal porque habría que modificar la forma en que se inicia el servicio Elasticsearch proporcionando una versión bifurcada del archivo entrypoint.sh. Desafortunadamente, esto le hará la vida más difícil en lo que respecta al mantenimiento y las actualizaciones. En cambio, descubrí que sería mejor utilizar otras soluciones para lograr el mismo objetivo.

Configurando el problema

Para comenzar con esta idea, consideraremos que estamos usando la imagen de Elasticsearch Docker y siguiendo la documentación:

 
docker pull docker.elastic.co/elasticsearch/elasticsearch:8.7.0ndocker network create elasticndocker run --name es01 --net elastic -p 9200:9200 -it docker.elastic.co/elasticsearch/elasticsearch:8.7.0
 

Tenga en cuenta que no vamos a montar el directorio de datos aquí, por lo que el directorio datapara este clúster será efímero y desaparecerá una vez que el nodo se haya cerrado. Una vez iniciado, podemos comprobar con la contraseña generada que está funcionando bien:

 
curl -s -k -u elastic:CHANGEME https://localhost:9200 | jq
 

Esto da:

 
{n  "name": "697bf734a5d5",n  "cluster_name": "docker-cluster",n  "cluster_uuid": "cMISiT__RSWkoKDYql1g4g",n  "version": {n    "number": "8.7.0",n    "build_flavor": "default",n    "build_type": "docker",n    "build_hash": "09520b59b6bc1057340b55750186466ea715e30e",n    "build_date": "2023-03-27T16:31:09.816451435Z",n    "build_snapshot": false,n    "lucene_version": "9.5.0",n    "minimum_wire_compatibility_version": "7.17.0",n    "minimum_index_compatibility_version": "7.0.0"n  },n  "tagline": "You Know, for Search"n}
 
 

Entonces, queremos tener un conjunto de datos ya disponible. Tomemos el conjunto de datos de muestra que uso a menudo al hacer una demostración de Elasticsearch: el conjunto de datos de personas. Creé un generador para crear algunos datos falsos.

Primero, descarguemos el inyector:

 
wget https://repo1.maven.org/maven2/fr/pilato/elasticsearch/injector/injector/8.7/injector-8.7.jar
 

Luego, generaremos nuestro conjunto de datos en el disco usando las siguientes opciones:

 
mkdir datanjava -jar injector-8.7.jar --console --silent > data/persons.json
 

Tenemos 1000000documentos JSON y el conjunto de datos debería verse así:

 
head -2 data/persons.jsonnn{"name":"Charlene Mickael","dateofbirth":"2000-11-01","gender":"female","children":3,"marketing":{"cars":1236,"shoes":null,"toys":null,"fashion":null,"music":null,"garden":null,"electronic":null,"hifi":1775,"food":null},"address":{"country":"Italy","zipcode":"80100","city":"Ischia","countrycode":"IT","location":{"lon":13.935138341699972,"lat":40.71842684204817}}}n{"name":"Kim Hania","dateofbirth":"1998-05-18","gender":"male","children":4,"marketing":{"cars":null,"shoes":null,"toys":132,"fashion":null,"music":null,"garden":null,"electronic":null,"hifi":null,"food":null},"address":{"country":"Germany","zipcode":"9998","city":"Berlin","countrycode":"DE","location":{"lon":13.164834451298645,"lat":52.604673827377155}}}
 

Usando un script de Shell

Aquí tenemos 1 millón de documentos, por lo que no podemos enviarlos tal cual mediante una solicitud masiva. En cambio, necesitamos:

  • Dividir en 10000 o menos operaciones de índice
  • Para cada documento, agregue el encabezado masivo que falta
  • Envíe los documentos usando la _bulkAPI. Terminé escribiendo este script que requiere que tenga curl y jq instalados:
 
#!/bin/bashnELASTIC_PASSWORD=CHANGEMEnmkdir tmpnecho "Split the source in 10000 items"nsplit -d -l10000 ../data/persons.json tmp/partnBULK_REQUEST_FILE="tmp/bulk_request.ndjson"nFILES="tmp/part*"nfor f in $FILESndon  rm $BULK_REQUEST_FILEn  echo "Preparing $f file..."n  while read p; don    echo -e '{"index":{}}' >> $BULK_REQUEST_FILEn    echo -e "$p" >> $BULK_REQUEST_FILEn  done <$fn  echo "Calling Elasticsearch Bulk API"n  curl -XPOST -s -k -u elastic:$ELASTIC_PASSWORD https://localhost:9200/person/_bulk -H 'Content-Type: application/json' --data-binary "@$BULK_REQUEST_FILE" | jq '"Bulk executed in \(.took) ms with errors=\(.errors)"'ndone
> $BULK_REQUEST_FILEn echo -e "$p" >> $BULK_REQUEST_FILEn done <$fn echo "Calling Elasticsearch Bulk API"n curl -XPOST -s -k -u elastic:$ELASTIC_PASSWORD https://localhost:9200/person/_bulk -H 'Content-Type: application/json' --data-binary "@$BULK_REQUEST_FILE" | jq '"Bulk executed in \(.took) ms with errors=\(.errors)"'ndone">
 

Esto básicamente imprime:

 
Preparing tmp/part00 file...nCalling Elasticsearch Bulk APIn"Bulk executed in 1673 ms with errors=false"nPreparing tmp/part01 file...nCalling Elasticsearch Bulk APIn"Bulk executed in 712 ms with errors=false"n...nPreparing tmp/part99 file...nCalling Elasticsearch Bulk APIn"Bulk executed in 366 ms with errors=false"
 

Probablemente haya mucho margen de mejora, pero debo confesar que no soy tan bueno escribiendo scripts de shell. Ja. Ya lo has adivinado, ¿eh?

Usando Logstash

Logstash® puede hacer un trabajo similar al que hemos hecho manualmente, pero también puede proporcionar muchas más funciones, como manejo y monitoreo de errores. Además, ni siquiera necesitamos escribir el código. Usaremos Docker nuevamente aquí:

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

Escribamos un trabajo para esto:

 
input {n  file {n    path => "/usr/share/logstash/persons/persons.json"n    mode => "read"n    codec => json { }n    exit_after_read => truen  }n}nfilter {n  mutate {n    remove_field => [ "log", "@timestamp", "event", "@version" ]n  }n}noutput {n  elasticsearch {n    hosts => "${ELASTICSEARCH_URL}"n    index => "person"n    user => "elastic"n    password => "${ELASTIC_PASSWORD}"n    ssl_certificate_verification => falsen  }n}
"/usr/share/logstash/persons/persons.json"n mode => "read"n codec => json { }n exit_after_read => truen }n}nfilter {n mutate {n remove_field => [ "log", "@timestamp", "event", "@version" ]n }n}noutput {n elasticsearch {n hosts => "${ELASTICSEARCH_URL}"n index => "person"n user => "elastic"n password => "${ELASTIC_PASSWORD}"n ssl_certificate_verification => falsen }n}">
 

Ahora podemos ejecutar el trabajo:

 
docker run --rm -it --name ls01 --net elastic \n  -v $(pwd)/../data/:/usr/share/logstash/persons/:ro \n  -v $(pwd)/pipeline/:/usr/share/logstash/pipeline/:ro \n  -e XPACK_MONITORING_ENABLED=false \n  -e ELASTICSEARCH_URL="https://es01:9200" \n  -e ELASTIC_PASSWORD="CHANGEME" \n  docker.elastic.co/logstash/logstash:8.7.0
 

 

Usando la ventana acoplable componer

En lugar de ejecutar todo manualmente, puede usar fácilmente el docker composecomando para ejecutar todo según sea necesario y proporcionar a sus usuarios un clúster listo para usar. Aquí hay un .envarchivo simple:

 
ELASTIC_PASSWORD=CHANGEMEnSTACK_VERSION=8.7.0nES_PORT=9200
 

Y el docker-compose.yml:

 
version: "2.2"nservices:n  es01:n    image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}n    ports:n      - ${ES_PORT}:9200n    environment:n      - node.name=es01n      - cluster.initial_master_nodes=es01n      - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}n      - bootstrap.memory_lock=truen    ulimits:n      memlock:n        soft: -1n        hard: -1n    healthcheck:n      test:n        [n          "CMD-SHELL",n          "curl -s -k https://localhost:9200 | grep -q 'missing authentication credentials'",n        ]n      interval: 10sn      timeout: 10sn      retries: 120n  logstash:n    depends_on:n      es01:n        condition: service_healthyn    image: docker.elastic.co/logstash/logstash:${STACK_VERSION}n    volumes:n      - type: bindn        source: ../datan        target: /usr/share/logstash/personsn        read_only: truen      - type: bindn        source: pipelinen        target: /usr/share/logstash/pipelinen        read_only: truen    environment:n      - ELASTICSEARCH_URL=https://es01:9200n      - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}n      - XPACK_MONITORING_ENABLED=false
 

Todavía tenemos nuestro persons.jsonarchivo en el ../datadirectorio. Se monta como /usr/share/logstash/persons/persons.jsontambién en el ejemplo anterior. Entonces, estamos usando el mismo pipeline/persons.confarchivo que vimos antes. Para ejecutar esto, ahora podemos simplemente escribir:

 
docker compose up
 

Y espere a with-compose-logstash-1que salga el contenedor:

 
with-compose-logstash-1  | [2023-04-21T15:17:55,335][INFO ][logstash.runner          ] Logstash shut down.nwith-compose-logstash-1 exited with code 0
 

Esto indica que nuestro servicio ahora está listo para ejecutarse y completamente cargado con nuestro conjunto de datos de muestra.

Usar instantánea y restaurar

También puede usar la API Create Snapshot para hacer una copia de seguridad de un conjunto de datos existente que se encuentra en Elasticsearch en un sistema de archivos compartido o en S3, por ejemplo, y luego restaurarlo en su nuevo clúster usando la API Restore . Digamos que ya ha registrado un repositorio llamado sample. Puedes crear la instantánea con:

 
# We force merge the segments firstnPOST /person/_forcemerge?max_num_segments=1n# Snapshot the datanPUT /_snapshot/sample/personsn{n  "indices": "person",n  "include_global_state": falsen}
 

Entonces, cada vez que inicie un nuevo clúster, puede restaurar la instantánea con:

 
POST /_snapshot/sample/persons/_restore
 

Sólo debe tener cuidado con este método, ya que la instantánea que tiene aún se puede restaurar en su clúster cuando lo actualiza a una nueva versión principal. Por ejemplo, si creó una instantánea con la versión 6.3, no podrá restaurarla en la 8.2. Consulte Compatibilidad del índice de instantáneas para obtener más detalles. Pero ¡buenas noticias! Con Archive Indices , Elasticsearch ahora tiene la capacidad de acceder a repositorios de instantáneas más antiguos (volviendo a la versión 5). Sólo necesitas tener en cuenta algunas de las restricciones.. Para garantizar que su instantánea siempre sea totalmente compatible, es posible que desee volver a tomar una instantánea de su índice con la versión más reciente utilizando el mismo script. Tenga en cuenta que la llamada a la API Force Merge es importante en ese caso, ya que reescribirá todos los segmentos utilizando las últimas versiones de Elasticsearch y Lucene.

Usando un directorio montado

¿Recuerdas cuando iniciamos el clúster?

 
docker run --name es01 --net elastic -p 9200:9200 -it docker.elastic.co/elasticsearch/elasticsearch:8.7.0
 

No utilizamos un montaje de enlace para los directorios dataconfig. Pero en realidad podemos hacer esto con:

 
docker run --name es01 --net elastic -p 9200:9200 -it -v persons-data:/usr/share/elasticsearch/data -v persons-config:/usr/share/elasticsearch/config docker.elastic.co/elasticsearch/elasticsearch:8.7.0
 

Podemos inspeccionar los volúmenes de Docker que se acaban de crear:

 
docker volume inspect persons-data persons-confign[n    {n        "CreatedAt": "2023-05-09T10:20:14Z",n        "Driver": "local",n        "Labels": null,n        "Mountpoint": "/var/lib/docker/volumes/persons-data/_data",n        "Name": "persons-data",n        "Options": null,n        "Scope": "local"n    },n    {n        "CreatedAt": "2023-05-09T10:19:51Z",n        "Driver": "local",n        "Labels": null,n        "Mountpoint": "/var/lib/docker/volumes/persons-config/_data",n        "Name":</
Ir al Blog