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 data
para 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 1000000
documentos 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:
#!/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
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}
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 compose
comando para ejecutar todo según sea necesario y proporcionar a sus usuarios un clúster listo para usar. Aquí hay un .env
archivo 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.json
archivo en el ../data
directorio. Se monta como /usr/share/logstash/persons/persons.json
también en el ejemplo anterior. Entonces, estamos usando el mismo pipeline/persons.conf
archivo que vimos antes. Para ejecutar esto, ahora podemos simplemente escribir:
docker compose up
Y espere a with-compose-logstash-1
que 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 data
y config
. 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":</