Schedule icon
Status icon
Return icon
Switch icon
Log icon
SlackIncomingWebhook icon

Helm Release Health Sentinel

Check a Helm release's status via helm status on a schedule, change nothing on the cluster, and alert Slack on a stuck or failed release.

Categories
CloudInfrastructure

A Helm release can get stuck mid-upgrade or land in a failed state long after the person who ran helm upgrade has moved on, and nothing in Helm itself pages anyone about it. This blueprint turns a scheduled, read-only helm status call into a Day 2 health gate: io.kestra.plugin.helm.Status reports the release's current revision and status without changing anything on the cluster, a single Pebble expression classifies that status, and the result routes to a quiet log, an informational Slack note, or a Slack page depending on severity.

How it works

  1. check_release_status (io.kestra.plugin.helm.Status) runs helm status and helm get manifest for release_name in release_namespace, using the same cluster connection model as the Kubernetes plugin. It returns status, revision, chart, chartVersion, firstDeployed, lastDeployed, and the release's managed resources, without installing, upgrading, or rolling anything back. allowFailure: true keeps a cluster or release lookup failure from aborting the flow outright.
  2. classify_release_health (io.kestra.plugin.core.debug.Return) evaluates a single Pebble expression against the reported status: missing entirely becomes UNREACHABLE, deployed becomes HEALTHY, any of Helm's transitional states (pending-install, pending-upgrade, pending-rollback, uninstalling) becomes WARNING, and anything else (failed, unknown, or any other value) becomes CRITICAL.
  3. route_by_release_health (io.kestra.plugin.core.flow.Switch) branches on that classification: HEALTHY logs a quiet confirmation; WARNING posts an informational Slack note; CRITICAL and UNREACHABLE each page Slack with the reported status and revision; a defaults fallback logs the raw value for any classification outside the four known cases.
  4. log_audit_result (io.kestra.plugin.core.log.Log) writes one audit line per run, independent of which Switch branch fired, including the chart name and revision, so the check's own history stays queryable even if Slack delivery fails.
  5. The flow-level errors block pages Slack separately if the flow fails outright, so a broken sentinel is never mistaken for a healthy release.
  6. The release_health_schedule trigger checks every 15 minutes and ships disabled: true, with explicit inputs: overrides for release_namespace and environment so the scheduled run's target is pinned regardless of this flow's own defaults.

What you get

  • A scheduled, read-only health check for any Helm release with zero custom helm CLI scripting.
  • A single status output (HEALTHY / WARNING / CRITICAL / UNREACHABLE) other flows can gate on.
  • Three distinct Slack messages, one per severity, each carrying the release's reported Helm status and revision.
  • An audit log line on every run, separate from Slack, carrying the chart and revision, so the check's own history survives a webhook outage.

Who it's for

  • Platform teams running Helm-deployed services who have no orchestrator-side check for a release stuck between deploys.
  • On-call engineers who want a signal that an upgrade or rollback never finished, before the next deploy collides with it.
  • Teams standardizing Day 2 release health monitoring across multiple clusters inside Kestra without writing a bespoke helm status cron script.

Why orchestrate this with Kestra

A cron job that shells out to helm status and greps the output is invisible the moment it succeeds and brittle the moment Helm's text output changes format. Kestra's Status task parses the release state into typed fields, so the check, the classification, and the Slack call are all one auditable execution history, with the Switch branch ready to grow into real remediation (triggering the existing rollback pattern, opening a ticket) without rewriting the check itself.

Prerequisites

  • A Kubernetes cluster reachable via connection (the same model as the Kubernetes plugin) with an existing Helm release named release_name in release_namespace.
  • A Slack incoming webhook for the WARNING, CRITICAL, UNREACHABLE, and flow-failure alerts.

Secrets

  • K8S_MASTER_URL, K8S_CA_CERT, K8S_TOKEN: cluster connection details for the connection block (same secrets already used by the existing helm-gated-release-with-rollback blueprint).
  • SLACK_WEBHOOK_URL: Slack incoming webhook used for every alert branch and the flow-failure alert.

In Kestra OSS (no Enterprise secrets backend), secrets are supplied as environment variables prefixed SECRET_, base64-encoded, and read back in flows with {{ secret('NAME') }}, for example SECRET_SLACK_WEBHOOK_URL=$(echo -n 'https://hooks.slack.com/services/<placeholder>' | base64). This keeps credentials out of the flow YAML but, per Kestra's own documentation, offers no encryption at rest or access control beyond the host environment; use the Enterprise secrets backend for stronger guarantees.

Quick start

  1. Start a local single-node Kubernetes cluster in Docker, on its own API server port well away from Kestra's own UI: docker run -d --name k3s-server --privileged -p 6443:6443 rancher/k3s:latest server --tls-san=localhost
  2. If Kestra is also running in Docker, attach the cluster to Kestra's network so the worker can reach it by container name: docker network connect YOUR_KESTRA_NETWORK k3s-server
  3. Pull the cluster's kubeconfig and install a sample release to check: docker exec k3s-server cat /etc/rancher/k3s/k3s.yaml helm install my-app oci://registry-1.docker.io/bitnamicharts/nginx --namespace default --kubeconfig <path-from-previous-step>
  4. Derive K8S_MASTER_URL, K8S_CA_CERT, and K8S_TOKEN from that kubeconfig, add them along with SLACK_WEBHOOK_URL as secrets, and run the flow once manually to confirm status reads HEALTHY.
  5. Enable release_health_schedule once pointed at a real cluster and release.

How to extend

  • Chain a CRITICAL branch into the existing rollback pattern (io.kestra.plugin.helm.Rollback) for automatic remediation instead of a Slack page alone.
  • Loop this flow's release_name/release_namespace inputs over every release a team owns using io.kestra.plugin.core.flow.Loop, instead of checking one release per execution.
  • Add a staleness check on lastDeployed if your team also wants to know when a release has not been touched in a long time, as a separate signal from its current status.
  • Push status into a KV store and alert only on state transitions instead of every run.

Inputs

  • release_name: the Helm release to check.
  • release_namespace: the namespace holding the release.
  • environment: recorded as Asset metadata on the Status task; not used in the classification itself.

Outputs

  • status: one of HEALTHY, WARNING, CRITICAL, UNREACHABLE.

Links

Pitfalls

  • Status reports the release's state as of the moment the call runs; a brief pending-upgrade window during a fast, healthy deploy can be caught by an unlucky poll and reported as WARNING even though the upgrade finishes seconds later. Treat a single WARNING as a prompt to check again before escalating, not as a confirmed incident.
  • This flow only ever calls helm status/helm get manifest; it never calls helm upgrade, helm rollback, or helm uninstall, so there is nothing destructive to default to dry-run for.
  • A release that was intentionally uninstalled will typically make helm status report nothing at all (not a status value of uninstalled), which this flow treats as UNREACHABLE; do not point this at a release you expect to be gone.
  • connection and kubeconfig are mutually exclusive on this task; this blueprint uses connection to match the existing helm-gated-release-with-rollback blueprint's convention.
See How

New to Kestra?

Use blueprints to kickstart your first workflows.