Schedule icon
Request icon
If icon
Fail icon
Log icon
SlackIncomingWebhook icon

Detect and Recover Disabled OpenSearch Shard Allocation

Detect OpenSearch shard allocation stuck at none or primaries, re-enable it, retry failed shards, then re-read health and fail if still red.

Categories
Infrastructure

After a rolling restart an operator often sets cluster.routing.allocation.enable to none or primaries so shards do not thrash while nodes bounce. If that setting is left behind, replicas and new shards never allocate: the cluster sits yellow or red, ingest for new indices stalls and nobody notices until an alert fires hours later. This blueprint reads cluster health and the live setting, re-enables allocation with a PUT _cluster/settings, retries shards stuck behind the failed-allocation limit with POST _cluster/reroute?retry_failed=true, then re-reads health and the setting and fails if the cluster is still red or allocation did not return to all. It alerts Slack the moment a problem is detected, before any remediation decision.

Findings

  • io.kestra.plugin.opensearch.Request fails the task on any non-2xx HTTP status. The gates here also read outputs.<id>.status or re-read the cluster.
  • cluster.routing.allocation.enable lives under transient or persistent in GET _cluster/settings. A value that was never set is absent, which means the built-in default all, so the flow treats an absent value as all.
  • Re-enabling allocation is set with the value all. The flow re-reads the setting and cluster health after the change, because the write returning a 200 does not prove the shards actually allocated.

How it works

  1. detect_health (io.kestra.plugin.opensearch.Request) reads GET _cluster/health for the status color and the unassigned shard count. detect_settings reads GET _cluster/settings for the live cluster.routing.allocation.enable value.
  2. check_reads fails the run if either read did not return HTTP 200. The Request task already fails on non-2xx.
  3. report logs the allocation value, the status, the unassigned count and the mode. alert_detected then posts a Slack findings alert whenever allocation is not all or shards are unassigned, before and apart from the remediation gate, so a plain detect run or a dry_run run both alert.
  4. route (io.kestra.plugin.core.flow.If) acts only when a problem is present, auto_remediate is true and dry_run is false. Otherwise report_only records a no-change outcome.
  5. enable_allocation sends PUT _cluster/settings with transient cluster.routing.allocation.enable set to all. reroute sends POST _cluster/reroute?retry_failed=true to retry shards stuck behind the failed-allocation limit.
  6. reverify_health and reverify_settings re-read the system. landed fails the run through fail_not_landed if the cluster is still red or allocation did not return to all.
  7. The errors block posts a Slack alert on any failure.
  8. A disabled Schedule trigger runs the scan every morning in report-only mode.

What you get

  • A one-command recovery for allocation left disabled after a rolling restart, driven through the plugin and logged as one execution.
  • A findings alert the moment allocation is disabled or shards are unassigned, independent of whether a change will run.
  • Proof the fix landed, from a re-read of health and the setting, not from a write that returned 200.
  • A read-only default: nothing changes unless auto_remediate is true and dry_run is false.
  • A Slack failure alert whenever the cluster stays red or allocation does not return to all.

Who it's for

  • Platform and SRE teams who run rolling restarts and need the allocation toggle flipped back without a manual curl.
  • Teams whose new indices silently stop allocating because enable was left at none or primaries.
  • Anyone who has re-enabled allocation by hand during an incident and wants it gated, logged and alertable instead.

Why orchestrate this with Kestra

Re-enabling allocation is a cluster-wide change that should be observed. Running it as a flow records what the allocation setting and health were, whether a change was allowed and whether the cluster actually recovered, all against one execution id. The read-only default stops a careless change. The re-read plus the red-cluster gate mean a green run really means allocation is back on and the cluster is not red.

Tested end to end

Verified on Kestra 2.0.5 against OpenSearch 2.19 (single node, security disabled). Allocation was disabled with PUT _cluster/settings transient cluster.routing.allocation.enable: none and a fresh index was created so its primary could not allocate, which took the cluster to red with unassigned shards. The clean, detect, dry-run, remediate and failure paths were all run. The remediate path moved the cluster from red with unassigned shards and enable: none to green with zero unassigned shards and enable: all, confirmed with a direct GET _cluster/health and GET _cluster/settings, not only the Kestra log. A separate index pinned to a non-existent node kept the cluster red after allocation was re-enabled. The flow failed that run through the re-read gate instead of reporting success.

Prerequisites

  • A reachable OpenSearch cluster. For a secured cluster, credentials allowed to read cluster health and settings and to update cluster settings.
  • A Slack incoming webhook for alerts.

Secrets

  • OPENSEARCH_USERNAME: username for basic auth, when the cluster has security enabled.
  • OPENSEARCH_PASSWORD: password for basic auth, when the cluster has security enabled.
  • SLACK_WEBHOOK_URL: Slack incoming webhook URL for alerts.

Inputs

  • opensearch_url: base URL of the cluster.
  • dry_run and auto_remediate: the two safety gates. A change runs only when auto_remediate is true and dry_run is false.

Quick start

  1. Add the Slack webhook secret plus the OpenSearch credentials if your cluster is secured.
  2. Set opensearch_url to your cluster. Run once with the defaults (dry_run true) to see the current allocation value, the status and the unassigned shard count.
  3. When you want the toggle flipped back, run with auto_remediate true and dry_run false. The flow re-enables allocation, reroutes failed shards and fails if the cluster is still red.
  4. Set disabled: false on the daily trigger to scan every morning in report-only mode.

How to extend

  • Add a Pause before enable_allocation if your change policy needs a human approval on every write.
  • Add a branch that pages a different channel when the cluster stays red after allocation is re-enabled, which points at a shard problem a reroute cannot fix.
  • Chain a downstream flow off this flow's FAILED state to open a ticket when the cluster cannot be recovered.
  • Narrow the reroute to specific shards by posting allocation commands in the reroute body.

Links

This blueprint was created by zkasuran.

See How

New to Kestra?

Use blueprints to kickstart your first workflows.