Skip to main content

Install

Octane ships five artifacts. Install only what you need — they are independent apart from one ordering rule.

Two of them install nothing. The advisor and the controller are processes you run beside a cluster, not plugins: unzip and go, no restart, no version pin. The advisor also needs no license, so it is the one you can run before deciding anything.

Check Compatibility before you pick a node version. All three plugins declare the same range — [3.3.0,3.9.0), meaning 3.3.0 through 3.8.x. A node refuses to start when a plugin's range does not match its version, so this is a decision to make before you install rather than a problem to find afterwards.

Order matters​

The license plugin must be installed first. The accelerator and content plugins declare it as an extended plugin, which puts its classes on their classloader and makes the dependency explicit: a node without it refuses to start rather than running a product that could never be licensed.

  1. octane-license        ← always first
2. octane-accelerator ┐ either, both, or neither
3. octane-content ┘
4. octane-autoscale ← outside the cluster; no ordering relationship

Install the plugins​

On every node, using OpenSearch's own plugin tool:

bin/opensearch-plugin install file:///path/to/octane-license-1.1.0.0.zip
bin/opensearch-plugin install file:///path/to/octane-content-1.1.0.0.zip
bin/opensearch-plugin install file:///path/to/octane-accelerator-1.1.0.0.zip

A plugin takes effect on node restart. Roll the fleet one node at a time — or let the autoscale controller do it, which clamps shard allocation for the duration so a restart does not trigger a rebalance.

In a container image​

Bake the plugins into the image rather than installing at runtime, so a node that comes up is already correct and a pod restart cannot lose them:

FROM opensearchproject/opensearch:3.8.0
COPY --chown=opensearch:opensearch octane-*.zip /tmp/
RUN bin/opensearch-plugin install --batch file:///tmp/octane-license-1.1.0.0.zip \
&& bin/opensearch-plugin install --batch file:///tmp/octane-content-1.1.0.0.zip \
&& bin/opensearch-plugin install --batch file:///tmp/octane-accelerator-1.1.0.0.zip \
&& rm /tmp/octane-*.zip
# Prove they are present here rather than discovering it at rollout.
RUN bin/opensearch-plugin list | grep -q octane-license \
&& bin/opensearch-plugin list | grep -q octane-content \
&& bin/opensearch-plugin list | grep -q octane-accelerator

--chown is not decoration. This image runs as the non-root opensearch user, so files copied in as root cannot be deleted by the RUN that follows: the build fails on rm: cannot remove '/tmp/octane-license-1.1.0.0.zip': Operation not permitted, after the plugins have installed successfully — which makes it read like a plugin problem when it is a file-ownership one.

--batch accepts the plugin's declared permissions without prompting, which is required for a non-interactive build.

Then build it, push it, and point the cluster at it​

Building an image changes nothing on its own. These three steps are what turn it into a running cluster, and skipping the third is the usual reason a rollout appears to do nothing at all.

# 1. Build for the architecture your NODES run, not the one your laptop runs. An arm64 image on
# amd64 nodes fails at pod start with "exec format error", after the rollout has begun.
docker buildx build --platform linux/amd64 \
-t registry.example.com/opensearch:3.8.0-octane-1.1.0.0 --push .

Tagging with the Octane version as well as the OpenSearch one makes "which plugin build is this node running" a property of the image name, rather than something you exec into a pod to find out.

# 2. Point the cluster at it.
# If an OPERATOR owns your cluster, patch the custom resource - NOT the StatefulSet. An operator
# reconciles its resources back to spec, so a StatefulSet edit is reverted seconds later and the
# rollout silently never happens.
kubectl patch opensearchcluster prod -n opensearch --type=merge \
-p '{"spec":{"general":{"image":"registry.example.com/opensearch:3.8.0-octane-1.1.0.0"}}}'

# With Helm:
helm upgrade prod opensearch/opensearch -n opensearch \
--set image.repository=registry.example.com/opensearch --set image.tag=3.8.0-octane-1.1.0.0

# With a plain StatefulSet that nothing owns:
kubectl set image statefulset/prod-hot \
opensearch=registry.example.com/opensearch:3.8.0-octane-1.1.0.0 -n opensearch

Nobody installs a plugin node by node. The image carries it; the fleet is rolled onto the image. Updating the image does not restart running nodes, so something has to do the roll — and that is what the Octane controller is for. Ask it:

curl -XPOST "$CLUSTER/.octane-restart-requests/_doc?refresh=true" \
-H 'Content-Type: application/json' \
-d '{"tier":"hot","roles":["data"],"reason":"install octane-accelerator 1.1.0.0",
"requested_at_millis":'"$(date +%s000)"'}'

It plans a roll over that tier and works through it one node at a time — clamping allocation so the cluster does not rebuild replicas for a node coming back in ninety seconds, checking the cluster is whole before each node, restarting cluster-manager-eligible nodes last, and restoring the allocation setting it found however the roll ends.

roles selects the nodes and is not optional in practice: a tier named with no roles matches nothing and the roll is refused. The full path, including what to read while it runs, is in installing across a fleet.

Verify​

curl -s localhost:9200/_cat/plugins?v

Every node should list the plugins you installed. A node missing one is a node that will behave differently from its peers — which, for the accelerator, means segments written in different formats across the same index.

During a roll, check the image as well:

kubectl get pods -n opensearch -o custom-columns='POD:.metadata.name,IMAGE:.spec.containers[0].image'

A partially rolled tier answers _cat/plugins from whichever node handled the request, so the plugin can look present while half the fleet is still on the old image.

Install the controller​

The controller is a standalone JVM process. It does not go on a node.

tar xf octane-autoscale-1.1.0.0.tar -C /opt
/opt/octane-autoscale/bin/octane-autoscale /etc/octane/autoscale.yml

It reads its configuration from, in order:

  1. the first command-line argument
  2. the OCTANE_CONFIG environment variable
  3. /etc/octane/autoscale.yml

It starts in recommend mode unless told otherwise, so a controller that is running but misconfigured logs what it would have done instead of doing it. See Configuration.

As a container​

FROM eclipse-temurin:21-jre
COPY octane-autoscale /opt/octane-autoscale
ENV OCTANE_CONFIG=/etc/octane/autoscale.yml
ENTRYPOINT ["/opt/octane-autoscale/bin/octane-autoscale"]

Mount the configuration and the license file as read-only. The controller needs network access to the cluster's REST endpoint and, in Kubernetes modes, to the API server.

Start a trial​

Nothing is gated until you try to use it, and the trial is one request:

curl -XPOST localhost:9200/_lucenia/license/_start_trial?issued_to=acme

Thirty days, once per cluster. See Licensing.

Uninstall​

bin/opensearch-plugin remove octane-accelerator
bin/opensearch-plugin remove octane-content
bin/opensearch-plugin remove octane-license # last: the others extend it

Removing the accelerator from a node that holds accelerated indices makes those indices unreadable — the codec is recorded in every segment, and without the plugin nothing can decode them. Reindex first, or keep the plugin installed and turn the feature off per index with index.lucenia.accelerator.enabled: false on new indices.