Schedule icon
Webhook icon
Request icon
Script icon
SlackIncomingWebhook icon
If icon
Pause icon
Loop icon
Apply icon
Log icon

Kubecost Namespace Rightsizing with Approval and Chargeback

Pull Kubecost allocations, build a budget-vs-actual chargeback report, hold a human approval, then enforce right-sized Kubernetes LimitRange defaults.

Categories
BusinessCloud

Diagram unavailable

We could not build the topology for this blueprint. The flow itself is valid, use the YAML on the left to run it.

How it works

  1. A weekly Schedule trigger (shipped disabled) or the on-demand Webhook starts the run.
  2. fetch_allocations (core.http.Request) calls the Kubecost /model/allocation API grouped by namespace with a Bearer token.
  3. analyze_rightsizing (scripts.python.Script, Process runner) joins allocations with the budgets input and builds three things: a chargeback table (cost vs budget per owning team, with over-budget flags and an unassigned bucket for namespaces missing from the budget map), rightsizing proposals for namespaces whose CPU/RAM utilization sits below util_threshold (savings scaled to a 30-day month, filtered by min_monthly_savings_usd), and a headline savings total. Results come back through Kestra's ::json:: outputs protocol.
  4. publish_chargeback (Slack) always posts the report — the chargeback half of the blueprint is useful even when nothing needs resizing.
  5. rightsizing_gate (core.flow.If) branches only when proposals exist: a second Slack message lists them, then approval (core.flow.Pause with structured onResume fields) holds the execution for a human decision for up to approval_timeout.
  6. On approval, enforce_defaults (core.flow.Loop) applies one kubernetes.kubectl.Apply LimitRange per namespace so future pods get the recommended default requests; on rejection the cluster is untouched. Either verdict is announced to Slack with the approver's reason.
  7. Flow outputs expose the chargeback rows, over-budget list, proposals, savings total and the decision; errors posts any failure to Slack.

What you get

  • A per-team chargeback report (actual spend vs budget, over-budget alerts) delivered on a schedule.
  • Data-driven rightsizing proposals with projected monthly savings per namespace.
  • A durable, auditable human approval gate before anything touches the cluster.
  • Enforcement via LimitRange defaults rather than mutating running workloads.

Who it's for

Platform and FinOps engineers who own showback/chargeback reporting and want a governed path from "here is the waste" to "here is the enforced change."

Why orchestrate

The analysis, the report, the approval and the enforcement live in different tools today — a Kubecost dashboard, a spreadsheet, a ticket, a kubectl session. Kestra joins them into one execution graph: the Pause holds state durably while an approver decides, the structured resume fields become branch conditions downstream, and every sweep leaves a single auditable record of what was proposed, approved and applied.

Prerequisites

  • A reachable Kubecost installation with an API token.
  • Kubernetes service account credentials able to read namespaces and apply LimitRange objects.
  • A Slack incoming webhook for notifications.
  • The budgets input populated with your namespace-to-team mapping.

Secrets

  • KUBECOST_API_TOKEN - Bearer token for the Kubecost /model API.
  • K8S_MASTER_URL - Kubernetes API server URL.
  • K8S_TOKEN - Service account token with namespace and LimitRange apply permissions.
  • SLACK_WEBHOOK_URL - Slack incoming webhook for report and approval messages.

Quick start

  1. Set the four secrets above in Kestra.
  2. Replace the budgets input defaults with your namespaces, owner teams and monthly budgets.
  3. Run the flow with the on_demand webhook (or enable weekly_rightsizing), then inspect namespace_report and total_monthly_savings_usd in the outputs.
  4. When proposals exist, open the paused execution, review the Slack thread, and resume with the approved decision plus notes.
  5. Confirm the LimitRanges landed and watch the next report reflect smaller requests.

How to extend

  • Tighten util_threshold or min_monthly_savings_usd to cut noise, or set window to 7d for a tighter signal.
  • Swap the LimitRange Apply for a kubectl.Patch of Deployment resources if you prefer to resize workloads directly.
  • Fan the chargeback rows out to a Subflow per owning team, or write them to a database for a finance-facing dashboard.
  • Add a second approval step for namespaces over budget rather than over-provisioned.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.