Schedule icon
AwsCLI icon
If icon
SlackIncomingWebhook icon
Log icon

AWS Compute Optimizer Underprovisioned Instance Risk Sentinel

Audit AWS Compute Optimizer for underprovisioned EC2 instances and alert Slack with the exact instance and recommended fix.

Categories
CloudInfrastructure

Compute Optimizer continuously analyzes CloudWatch utilization data and classifies every EC2 instance as Optimized, Overprovisioned, or Underprovisioned - but it has no built-in way to say "notify this Slack channel the moment a running instance becomes genuinely under-specced for its workload" without wiring an EventBridge rule and a notification target per account. Overprovisioned findings are a cost story; Underprovisioned findings are a reliability risk story - this blueprint focuses on the latter and alerts Slack with the exact instance and Compute Optimizer's own recommended fix.

How it works

  1. periodic_rightsizing_check (io.kestra.plugin.core.trigger.Schedule) runs every 12 hours, explicitly passing aws_region through its own inputs: block so the flow is self-contained when the trigger fires. Shipped disabled so a manual run can be verified first.
  2. probe_underprovisioned_instances (io.kestra.plugin.aws.cli.AwsCLI) runs aws compute-optimizer get-ec2-instance-recommendations with a --filters JSON for Finding = Underprovisioned, capturing the result's instanceRecommendations list as a named task output.
  3. evaluate_underprovisioned_presence (io.kestra.plugin.core.flow.If) branches on whether that list has any entries at all.
    • then (UNDERPROVISIONED_INSTANCES_DETECTED): alert_underprovisioned_instances reports each instance's ARN, current type, Compute Optimizer's top recommended type, and the specific finding reason codes (CPU, memory, EBS, network) to Slack.
    • else (HEALTHY): log_all_instances_healthy records a clean sweep.
  4. log_audit_complete always runs last, printing the underprovisioned count regardless of which branch fired.
  5. The errors block alerts Slack separately if the flow itself fails outright - the account not having opted in to Compute Optimizer yet, or bad credentials, must not read as HEALTHY.

What you get

  • A HEALTHY/UNDERPROVISIONED_INSTANCES_DETECTED answer computed by Compute Optimizer's own server-side finding filter, not by paging through every instance (Optimized and Overprovisioned included) and filtering client-side.
  • The exact instance ARN, current instance type, Compute Optimizer's own top-ranked recommended type, and the specific resource dimension that is underprovisioned (CPU, memory, EBS throughput/IOPS, network bandwidth/PPS, or disk) in the Slack alert itself.
  • A focus on reliability risk (Underprovisioned), not cost waste (Overprovisioned) - the two findings call for different urgency and different remediation, and this sentinel is scoped to the one that can actually cause an incident.
  • A worked example of io.kestra.plugin.aws.cli.AwsCLI driving a read-only, finding-filtered Compute Optimizer audit, reusing the same corrected output-capture convention (newlines only, not spaces, stripped before the marker) as this repository's CloudFormation, AWS Config, AWS Backup, GuardDuty, and Security Hub sentinel blueprints.

Who it's for

  • Platform and SRE teams who want an early signal when a production instance is genuinely under-specced for its workload, before it becomes a performance incident.
  • On-call engineers who want one Slack alert with the exact instance and Compute Optimizer's own recommended instance type instead of opening the console to check manually.
  • Anyone evaluating the AWS plugin who wants a worked example of AwsCLI driving a Compute Optimizer finding filter, with the nuance between Finding values (Underprovisioned, Overprovisioned, Optimized) and FindingReasonCodes (the specific CPU/memory/EBS/network dimension) made explicit.

Why orchestrate this with Kestra

Compute Optimizer itself has no cross-account "notify me the moment an instance becomes Underprovisioned" primitive beyond what you wire up separately in EventBridge and SNS, configuration that then has to be kept in sync as instances are launched and terminated. Kestra supplies the schedule, the HEALTHY/UNDERPROVISIONED_INSTANCES_DETECTED classification as a first-class branch, and an execution history that shows exactly when an instance crossed into performance risk and what Compute Optimizer recommended.

Prerequisites

  • An AWS account that has opted in to AWS Compute Optimizer in the target region (a one-time console or API action, separate from any support plan), with at least 14 days of CloudWatch utilization history on at least one running EC2 instance.
  • AWS credentials with compute-optimizer:GetEC2InstanceRecommendations permission - entirely read-only, cannot resize or modify any instance.
  • A Slack incoming webhook for alerts.

This blueprint has no meaningful local testing path. Compute Optimizer's own recommendations are generated from real CloudWatch utilization history accumulated over at least 14 days, so even a perfectly API-compatible local mock could not produce a genuine Underprovisioned finding without that real usage data behind it - this is a limitation of what the service measures, not specific to any particular local AWS emulator's feature coverage.

Secrets

  • AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY: credentials for io.kestra.plugin.aws.cli.AwsCLI.
  • SLACK_WEBHOOK_URL: Slack incoming webhook used by alert_underprovisioned_instances and the errors block.
  • In Kestra OSS (no Enterprise secrets backend), secrets are supplied as environment variables prefixed SECRET_, base64-encoded - for example SECRET_AWS_SECRET_ACCESS_KEY=$(echo -n '<your-secret-key>' | base64) - and read back in flows with {{ secret('NAME') }}.

Inputs

  • aws_region (STRING, default us-east-1): region whose EC2 recommendations are audited.

Outputs

  • outputs.probe_underprovisioned_instances.vars.instanceRecommendations: the list of matching instance recommendations, each with instanceArn, currentInstanceType, finding, findingReasonCodes, recommendationOptions (ranked alternative instance types with performanceRisk and rank), and more (verified fields from Compute Optimizer's own GetEC2InstanceRecommendations API reference).
  • outputs.probe_underprovisioned_instances.vars.errors: per-instance errors Compute Optimizer itself reports (for example, an unsupported instance family) - not raised as a flow failure, since it is a documented part of a normal response.

Quick start

  1. Opt in to Compute Optimizer in a real AWS account with at least one running EC2 instance that has accumulated 14+ days of CloudWatch metrics.
  2. Add the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and SLACK_WEBHOOK_URL secrets.
  3. Run the flow manually and confirm log_all_instances_healthy or alert_underprovisioned_instances fires depending on your actual fleet's utilization history.
  4. If nothing is currently Underprovisioned, temporarily run a CPU or memory stress test against a small test instance for a few days to generate a genuine finding, then re-run to confirm the alert path.
  5. Enable periodic_rightsizing_check once you trust the check against your real account.

How to extend

  • Loop over several aws_region values with io.kestra.plugin.core.flow.Loop to audit every region where Compute Optimizer is opted in, in one run.
  • Add a second, parallel probe filtered to Finding = Overprovisioned for a separate FinOps-focused cost-savings digest, kept distinct from this sentinel's reliability-risk focus.
  • Add a remediation branch that resizes a flagged instance to recommendationOptions[0].instanceType behind an explicit approval gate, since a resize requires a stop/start and brief downtime - deliberately kept out of this sentinel so the monitoring path never changes any instance.

Pitfalls

  • Underprovisioned and Overprovisioned call for different responses and different urgency. This blueprint deliberately filters to Underprovisioned only (a reliability risk - the instance cannot meet its own workload's demands) rather than also alerting on Overprovisioned (a cost-savings opportunity, not a risk) - mixing the two into one alert would bury the more urgent signal.
  • Pagination is not handled. get-ec2-instance-recommendations is itself paginated (nextToken); if more underprovisioned instances exist than fit in one page, this blueprint's single call only sees the first page.
  • OptInRequiredException is the expected failure mode for an account that has never opted in to Compute Optimizer - this surfaces through the errors block, explicitly called out in its own alert text so it is not mistaken for a credentials problem.
  • The output-capture convention (tr -d '\n' | xargs -0 -I {} echo '::{"outputs":{}}::') deliberately does not strip spaces, the same corrected pattern used throughout this repository's AWS CLI-based sentinel blueprints, since finding reason codes and instance names can contain them.
  • This blueprint is UNTESTED against a live AWS account. The CLI syntax, the Filter name/values enum, and the instanceRecommendations / finding / findingReasonCodes / recommendationOptions output fields are taken verbatim from AWS Compute Optimizer's own API reference documentation - but no Kestra engine was run to execute this flow end to end.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.