Schedule icon
Script icon
If icon
SlackIncomingWebhook icon
Log icon
Return icon

Consul Service Deregistration Sentinel

Audits HashiCorp Consul catalog for services failing health checks past thresholds, calculating dead nodes and alerting SREs on Slack.

Categories
CloudInfrastructure

In dynamic cloud environments utilizing HashiCorp Consul for service discovery and mesh networking, microservice containers and virtual machines frequently terminate abruptly without invoking graceful catalog deregistration hooks.

When an ephemeral service instance crashes or gets rescheduled by Kubernetes or Nomad, its corresponding health check transitions to critical. Unless DeregisterCriticalServiceAfter is explicitly defined on each individual service registration payload, the dead service endpoint remains registered in Consul DNS and HTTP lookup catalogs indefinitely. Downstream load balancers (such as Envoy, NGINX, or Traefik) and upstream consumers continue routing live user requests to unreachable endpoints, causing cascading HTTP 502/503 outages.

This blueprint acts as an automated service mesh hygiene sentinel. Executing every fifteen minutes, it queries the Consul Health API for services stuck in critical status, identifies unmanaged dead nodes, and delivers actionable Slack alerts with exact CLI deregistration commands to on-call platform engineers.

How it works

  1. Recurrent Pulse Trigger: The audit_failing_consul_services trigger (io.kestra.plugin.core.trigger.Schedule) initiates catalog health queries every fifteen minutes.
  2. Consul Health API Scan: The scan_critical_service_checks task (io.kestra.plugin.scripts.python.Script) invokes the Consul /v1/health/state/critical endpoint for the target datacenter, parsing check outputs and service identifiers.
  3. Threshold Gate: The evaluate_failing_services flowable task (io.kestra.plugin.core.flow.If) evaluates whether any critical services exceed healthy cluster SLAs.
  4. Slack Incident Alert: When unmanaged dead services are detected, notify_slack_consul_deregistration (io.kestra.plugin.slack.notifications.SlackIncomingWebhook) dispatches a triage card detailing the primary offending service, node, and copy-paste remediation commands (consul services deregister -id=...).
  5. Healthy Confirmation: When zero failing checks are discovered, log_healthy_consul_catalog logs healthy catalog status.
  6. Manifest Export: The export_consul_audit_manifest task records an execution summary for SRE telemetry pipelines.

Architecture diagram

flowchart TD
    A[Schedule: Every 15 Minutes] --> B[scan_critical_service_checks: Consul Health API]
    B --> C{Critically Failing Services Found?}
    C -- Yes --> D[notify_slack_consul_deregistration: Slack Webhook]
    C -- No --> E[log_healthy_consul_catalog: Log]
    D --> F[export_consul_audit_manifest: Return JSON]
    E --> F

Use cases

  • Ephemeral Cloud Auto-Scaling Hygiene: Automatically catch phantom EC2 or GCE instances left behind after spot instance terminations.
  • Service Mesh Upstream Protection: Prevent Envoy and Consul Connect sidecars from attempting connection establishment to dead upstream instances.
  • Platform Engineering Policy Audits: Identify developer service manifests lacking DeregisterCriticalServiceAfter definitions.

Inputs

Name Type Default Description
consul_http_addr STRING "http://localhost:8500" Base URL of the HashiCorp Consul agent or cluster API endpoint.
critical_failing_threshold_minutes INT 30 Duration a service health check must remain in critical status before alerting.
datacenter STRING "dc1" Target Consul datacenter namespace to query.
slack_channel STRING "#sre-service-discovery" Slack channel destination for service discovery notifications.

Expected outputs

  • {{ outputs.scan_critical_service_checks.vars.has_stale_services }}: Boolean flag indicating if critical service checks were discovered.
  • {{ outputs.scan_critical_service_checks.vars.stale_count }}: Total number of service instances currently stuck in critical status.
  • {{ outputs.scan_critical_service_checks.vars.top_service }}: Service name of the most prominent failing registration.
  • {{ outputs.scan_critical_service_checks.vars.top_node }}: Node hosting the offending failing check.
  • {{ outputs.scan_critical_service_checks.outputFiles['consul_health_audit.json'] }}: Structured JSON audit report.

Prerequisites

  • Reachable HashiCorp Consul agent or server endpoint with HTTP API enabled.
  • Incoming Webhook URL configured in your team's Slack workspace.

Secrets

  • SLACK_WEBHOOK_URL: Slack Incoming Webhook endpoint URL with permissions to post messages.

Quick start

  1. Configure SLACK_WEBHOOK_URL in your Kestra namespace secrets.
  2. Import this flow YAML into your Kestra workspace.
  3. Update consul_http_addr to point to your internal Consul server or agent URL.
  4. Click Execute in the UI to run an initial discovery catalog health scan.

Common pitfalls and troubleshooting

  • Consul ACL Token Requirements: If Consul operates with ACLs enabled (acl.enabled = true), pass the management or operator token via the X-Consul-Token HTTP header in requests.
  • Node vs Service Level Checks: Consul distinguishes between node-level health checks (e.g., host disk/memory) and service-level checks; deregistering a service does not resolve a failing host-level agent check.

How to extend

  • Add an automated deregistration task invoking PUT /v1/catalog/deregister directly after manager approval via io.kestra.plugin.core.flow.Pause.
  • Loop across all federated datacenters using /v1/catalog/datacenters to enforce multi-region catalog hygiene.
  • Export dead service metrics directly to Prometheus Pushgateway or Datadog custom metrics.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.