Testing more advanced APIs in OpenSearch requires a setup that also imports data. For example, OpenSearch has a concept of so-called dangling indexes. After a node joins a cluster, dangling indexes occur if any shards exist in the node’s local directory that do not already exist in the cluster. To fabricate a dangling index one must create a cluster that loses quorum. Fortunately, we have available to us an excellent talk by Amitai Stern that goes into great depth into data migrations between clusters and talks about a method called “node toss” at around 17:50 that puts node indexes into a dangling state. Amitai has also authored a cookbook for re-creating a dangling index in a Docker container.
Here’s how it works.
We begin by creating a single-node cluster without security that uses a local directory (opensearch-data1) to store data. Note the --entrypoint /bin/bash which opens a shell instead of starting the cluster.
We manually start it with ./opensearch-docker-entrypoint.sh, then insert some data from another shell.
Remove the index replicas.
Detach the cluster from the Docker shell.
Exit the container with exit and start a new 2-node cluster on top of this data with this docker-compose.yml that mounts our previously detached data.
After about 30 seconds the cluster figures out what to do, and creates the desired dangling indexes out of the existing data in node1.
Trying to recover this data will not work because the cluster is in a quorum loss and there’s no elected cluster manager.
Deleting the dangling index will also hang waiting for a cluster manager.
We can turn our 2-node quorum loss cluster into a healthy single-node cluster with these dangling indexes. Attempting to switch the cluster discovery.type=single-node will not work because the node is part of a 2-node cluster that lost quorum.
We need to properly detach one of the nodes. This is done by setting the number of replicas to zero, and removing node2 from voting.
A single node cluster can now start on top of this data.
However, while we can mount it directly via docker-compose, we don’t want to update the local copy of our data files, and instead copy them into the Docker container every time in order to have a stable initial state. Copying files causes OpenSearch to think that they were tampered with externally.
The solution is to get rid of lock files with find . -name *.lock | xargs rm. Now our local data is usable in a single-node cluster and this is what we add to git. Finally, copied files also have to be writable. We add COPY --chown=1000:1000 .data/opensearch-data1 /usr/share/opensearch/data to Dockerfile and end up with a single-node cluster with dangling indexes that can be deleted or recovered.
Note that DELETE and POST _dangling return 202 Accepted and not 200 or 201.