id: cratedb-shard-allocation-and-reroute-sentinel
namespace: company.data
inputs:
- id: cratedb_host
type: STRING
displayName: CrateDB Host
defaults: "cratedb.internal"
description: Hostname or IP address of the CrateDB node exposing the PostgreSQL
wire protocol port.
- id: cratedb_port
type: INT
displayName: CrateDB PostgreSQL Port
defaults: 5432
description: Port number for the PostgreSQL wire compatibility interface on
CrateDB (default 5432).
- id: cratedb_database
type: STRING
displayName: Database Name
defaults: "doc"
description: Target database or schema name to establish the JDBC session
against (default doc).
- id: slack_channel
type: STRING
displayName: Slack Channel
defaults: "#data-platform-alerts"
description: Slack channel destination for operational shard health incident cards.
- id: auto_reroute
type: BOOL
displayName: Auto Reroute Failed Allocations
defaults: true
description: Automatically dispatch ALTER CLUSTER REROUTE RETRY FAILED when
unassigned shards are detected.
- id: dry_run
type: BOOL
displayName: Dry Run Mode
defaults: false
description: When true, audits cluster shard states and dispatches notifications
but skips remediation commands.
triggers:
- id: every_fifteen_minutes
type: io.kestra.plugin.core.trigger.Schedule
cron: "*/15 * * * *"
tasks:
- id: probe_unassigned_shards
type: io.kestra.plugin.jdbc.postgresql.Query
url: "jdbc:postgresql://{{ inputs.cratedb_host }}:{{ inputs.cratedb_port }}/{{
inputs.cratedb_database }}"
username: "{{ secret('CRATEDB_USERNAME') }}"
password: "{{ secret('CRATEDB_PASSWORD') }}"
fetchType: FETCH
allowFailure: true
sql: |
SELECT
COALESCE(schema_name, 'doc') AS schema_name,
COALESCE(table_name, 'unknown') AS table_name,
COALESCE(id, 0) AS shard_id,
COALESCE("primary", false) AS is_primary,
COALESCE(routing_state, 'UNKNOWN') AS routing_state,
COALESCE(state, 'UNKNOWN') AS shard_state
FROM sys.shards
WHERE routing_state != 'STARTED'
ORDER BY "primary" DESC, table_name ASC;
- id: route_by_health
type: io.kestra.plugin.core.flow.Switch
value: >-
{% if outputs.probe_unassigned_shards.rows is null %} PROBE_FAILED {% else
%}
{% set unassigned_primaries = 0 %}
{% set unassigned_replicas = 0 %}
{% for row in outputs.probe_unassigned_shards.rows %}
{% if row.is_primary == true %}
{% set unassigned_primaries = unassigned_primaries + 1 %}
{% else %}
{% set unassigned_replicas = unassigned_replicas + 1 %}
{% endif %}
{% endfor %}
{% if unassigned_primaries > 0 %}
CRITICAL
{% elseif unassigned_replicas > 0 %}
WARNING
{% else %}
HEALTHY
{% endif %}
{% endif %}
cases:
CRITICAL:
- id: alert_critical_slack
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
url: "{{ secret('SLACK_WEBHOOK_URL') }}"
payload: |
{
"channel": "{{ inputs.slack_channel }}",
"text": "[CRITICAL] CrateDB Unassigned Primary Shards Detected - Immediate Cluster Intervention Required",
"attachments": [
{
"color": "#D32F2F",
"title": "CrateDB Unassigned Primary Shards Incident",
"fields": [
{
"title": "Cluster Host",
"value": "{{ inputs.cratedb_host }}:{{ inputs.cratedb_port }}",
"short": true
},
{
"title": "Impacted Shards Count",
"value": "{{ outputs.probe_unassigned_shards.size }}",
"short": true
},
{
"title": "Severity",
"value": "CRITICAL - Primary Shard Offline",
"short": true
},
{
"title": "Remediation Status",
"value": "{{ (inputs.auto_reroute and not inputs.dry_run) ? 'Triggering ALTER CLUSTER REROUTE RETRY FAILED' : 'Remediation Skipped (Dry Run or Disabled)' }}",
"short": true
}
],
"footer": "Kestra CrateDB Shard Sentinel | Execution ID: {{ execution.id }}"
}
]
}
- id: check_remediation
type: io.kestra.plugin.core.flow.If
condition: "{{ inputs.auto_reroute == true and inputs.dry_run == false }}"
then:
- id: execute_reroute_retry
type: io.kestra.plugin.jdbc.postgresql.Query
url: "jdbc:postgresql://{{ inputs.cratedb_host }}:{{ inputs.cratedb_port }}/{{
inputs.cratedb_database }}"
username: "{{ secret('CRATEDB_USERNAME') }}"
password: "{{ secret('CRATEDB_PASSWORD') }}"
sql: "ALTER CLUSTER REROUTE RETRY FAILED;"
- id: notify_remediation_slack
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
url: "{{ secret('SLACK_WEBHOOK_URL') }}"
payload: |
{
"channel": "{{ inputs.slack_channel }}",
"text": "[REMEDIATION] CrateDB cluster reroute command ALTER CLUSTER REROUTE RETRY FAILED executed successfully."
}
WARNING:
- id: alert_warning_slack
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
url: "{{ secret('SLACK_WEBHOOK_URL') }}"
payload: |
{
"channel": "{{ inputs.slack_channel }}",
"text": "[WARNING] CrateDB Unassigned Replica Shards Detected - Cluster Under-Replicated",
"attachments": [
{
"color": "#F57C00",
"title": "CrateDB Under-Replication Warning",
"fields": [
{
"title": "Cluster Host",
"value": "{{ inputs.cratedb_host }}:{{ inputs.cratedb_port }}",
"short": true
},
{
"title": "Unassigned Replicas Count",
"value": "{{ outputs.probe_unassigned_shards.size }}",
"short": true
},
{
"title": "Severity",
"value": "WARNING - Reduced Fault Tolerance",
"short": true
},
{
"title": "Auto Reroute",
"value": "{{ inputs.auto_reroute ? 'Enabled' : 'Disabled' }}",
"short": true
}
],
"footer": "Kestra CrateDB Shard Sentinel | Execution ID: {{ execution.id }}"
}
]
}
- id: check_warning_remediation
type: io.kestra.plugin.core.flow.If
condition: "{{ inputs.auto_reroute == true and inputs.dry_run == false }}"
then:
- id: execute_warning_reroute
type: io.kestra.plugin.jdbc.postgresql.Query
url: "jdbc:postgresql://{{ inputs.cratedb_host }}:{{ inputs.cratedb_port }}/{{
inputs.cratedb_database }}"
username: "{{ secret('CRATEDB_USERNAME') }}"
password: "{{ secret('CRATEDB_PASSWORD') }}"
sql: "ALTER CLUSTER REROUTE RETRY FAILED;"
PROBE_FAILED:
- id: alert_probe_failure
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
url: "{{ secret('SLACK_WEBHOOK_URL') }}"
payload: |
{
"channel": "{{ inputs.slack_channel }}",
"text": "[CRITICAL] CrateDB Shard Sentinel Probe Failed - Unable to query sys.shards. Verify network routing and credentials."
}
HEALTHY:
- id: log_cluster_healthy
type: io.kestra.plugin.core.log.Log
message: "CrateDB cluster shard routing is healthy. All evaluated shards are in
STARTED state."
- id: log_audit_summary
type: io.kestra.plugin.core.log.Log
message: "CrateDB shard health audit finished. Status: {{
outputs.route_by_health.value ?? 'PROCESSED' }}. Evaluated shards count:
{{ outputs.probe_unassigned_shards.size ?? 0 }}."
errors:
- id: on_flow_failure
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
url: "{{ secret('SLACK_WEBHOOK_URL') }}"
payload: |
{
"channel": "{{ inputs.slack_channel }}",
"text": "[ERROR] CrateDB Shard Allocation Sentinel flow execution failed unexpectedly. Execution ID: {{ execution.id }}."
}