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

AWS EBS Unattached Volume FinOps Auditor

Scans AWS EC2 EBS volumes in unattached status exceeding retention thresholds, calculating monthly cost waste and alerting FinOps on Slack.

Categories
CloudInfrastructure

When Amazon EC2 instances are terminated or recreated, root block devices and secondary EBS data volumes are frequently left behind in the available (unattached) state unless explicitly configured with DeleteOnTermination=true.

Because Amazon EBS bills based on provisioned gigabytes per month (regardless of whether the volume is mounted to a running compute instance), orphaned volumes silently accumulate in cloud accounts. Over months of developer deployments and auto-scaling events, hundreds of detached volumes generate substantial monthly storage fees with zero operational utility.

This blueprint implements an automated Cloud FinOps sentinel that connects to the AWS EC2 API, discovers all EBS volumes in the available status older than your retention threshold (default: 14 days), aggregates wasted gigabytes and monthly dollar costs, and dispatches an actionable advisory to your Slack channel with exact create-snapshot and delete-volume remediation instructions.

How it works

  1. Weekly Scheduled Scan: The weekly_ebs_audit trigger (io.kestra.plugin.core.trigger.Schedule) executes every Monday morning at 08:00 UTC.
  2. Boto3 Volume Query: The scan_unattached_volumes task (io.kestra.plugin.scripts.python.Script) calls AWS EC2 describe_volumes with a status filter of available, calculates volume ages in days, and outputs ebs_audit_report.json.
  3. Condition Branching: The evaluate_unattached_volumes flowable task (io.kestra.plugin.core.flow.If) branches based on whether any volumes breached the detached age threshold.
  4. Slack Alert Dispatch: When detached volumes are found, notify_slack_storage_team (io.kestra.plugin.slack.notifications.SlackIncomingWebhook) delivers an actionable triage card detailing volume IDs, gigabytes, and estimated monthly cost waste.
  5. Compliant Logging: When all storage volumes are actively attached, log_clean_ebs_status records nominal status in execution logs.
  6. Audit Manifest: The export_ebs_manifest task records execution metadata for cloud budget accounting.

What you get

  • Automated discovery of orphaned Amazon EBS volumes across regions.
  • Exact calculation of reclaimable storage gigabytes and monthly cost estimates.
  • Safety-first remediation guidance recommending snapshots before deletion.
  • Non-intrusive read-only execution preventing accidental data deletion.

Who it is for

  • Cloud FinOps practitioners optimizing multi-account AWS spending.
  • DevOps Engineers managing EC2 instances and auto-scaling groups.
  • Storage Administrators maintaining cloud data retention policies.

Why orchestrate this with Kestra

Building ad-hoc Lambda functions for cloud governance requires managing serverless deployments, IAM permissions, and external webhook libraries. Kestra provides declarative, observable orchestration: it securely executes containerized Python tasks, calculates financial metrics, branches conditionally, and dispatches structured alerts with full execution history.

Inputs

Name Type Default Description
aws_region STRING us-east-1 AWS region to inspect for detached EBS storage volumes.
unattached_days_threshold INT 14 Minimum days detached before triggering an advisory alert.
ebs_gp3_price_per_gb_month FLOAT 0.08 Estimated monthly dollar cost per gigabyte for EBS gp3.
slack_channel STRING #finops-alerts Slack channel destination for alerts.

Expected outputs

  • {{ outputs.scan_unattached_volumes.vars.has_unattached }}: Boolean flag indicating if unattached volumes were detected.
  • {{ outputs.scan_unattached_volumes.vars.flagged_count }}: Number of detached volumes breaching threshold.
  • {{ outputs.scan_unattached_volumes.vars.total_wasted_gb }}: Total gigabytes of unattached storage capacity.
  • {{ outputs.scan_unattached_volumes.outputFiles['ebs_audit_report.json'] }}: Complete JSON diagnostic report.

Prerequisites

  • An AWS IAM user or role with permissions: ec2:DescribeVolumes.
  • AWS credentials configured in Kestra secrets.
  • Slack Incoming Webhook configured for your FinOps alerting channel.

Secrets

  • AWS_ACCESS_KEY_ID: AWS IAM access key ID.
  • AWS_SECRET_ACCESS_KEY: AWS IAM secret access key.
  • SLACK_WEBHOOK_URL: Slack Incoming Webhook endpoint URL.

Quick start

  1. Configure AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and SLACK_WEBHOOK_URL in your Kestra namespace secrets.
  2. Import this flow YAML into your Kestra instance.
  3. Click Execute in the UI to run an initial regional scan.
  4. Review execution outputs to inspect unattached EBS volumes and monthly cost estimates.

Common pitfalls and troubleshooting

  • Snapshot Precedence: Always ensure a final safety snapshot is created before calling delete_volume on orphaned volumes to protect against accidental data loss.
  • Encrypted Volumes with KMS: When auditing encrypted EBS volumes, verify that the caller role possesses appropriate kms:DescribeKey permissions if inspecting encryption keys.
  • Multi-Region Coverage: EBS volumes are bound to specific Availability Zones; duplicate or parameterize this flow to audit all active AWS regions.

How to extend

  • Add an automated remediation task using boto3 to automatically create snapshots and delete volumes if tagged with AutoCleanup:True.
  • Scan across multiple AWS accounts using AWS Organizations cross-account IAM assume-role policies.
  • Correlate unattached volumes with historical CloudTrail events to identify the engineer who originally detached the volume.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.