Skip to content

Conversation

@B-Yan
Copy link

@B-Yan B-Yan commented Nov 20, 2025

Description

This is a fairly straightforward but important feature to make Karpenter more cost-aware for anyone with existing AWS commitments.

The problem is simple: Karpenter has been blind to Reserved Instances (RIs) unless they are explicitly tied to a Capacity Reservation. This means that if you've bought Standard or Convertible RIs to save money, Karpenter would happily ignore them and go off to launch new, more expensive On-Demand or Spot instances. This is just leaving money on the table and makes Karpenter less effective for anyone trying to optimize their AWS bill.

This change fixes that by making Karpenter RI-aware.

The core of the change is a new, dedicated ReservedInstanceProvider. I've put this in its own pkg/providers/reservedinstance package because RIs are a distinct concept from Capacity Reservations, and mixing the two would have been a mess. The new provider is responsible for one thing: figuring out which RIs are actually available for use right now.

Getting this right is non-trivial. You can't just use the billing or Cost Explorer APIs (GetReservationUtilization, etc.) because that data can be up to 24 hours stale. A scheduler can't work with stale data. The only reliable way to get a real-time view is to:

  1. Fetch all active Reserved Instances (DescribeReservedInstances).
  2. Fetch all running instances that could be consuming those RIs (DescribeInstances).
  3. Do the math. Subtract the running instances from the purchased RIs to get the true available count.

This is exactly what the new provider does. It's the only sane approach for real-time accuracy. To avoid hammering the EC2 API on every single provisioning loop, the results are cached for 10 minutes, which is a reasonable trade-off between data freshness and API load.

With the new provider in place, the rest is simple:

  • It's plumbed through the main operator startup in pkg/operator/operator.go.
  • It's injected into the offering.Provider in pkg/providers/instancetype/offering/offering.go.
  • The offering.Provider now uses this data to create new reserved offerings.

These new RI-based offerings are priced using the same trick we already use for Capacity Reservations: the on-demand price is divided by a ridiculously large number. This makes them effectively "free" in the eyes of the scheduler, ensuring they are always picked first if they match the requirements.

This closes a significant gap in Karpenter's cost-optimization strategy and makes it behave the way users would expect.

How was this change tested?

Ran make ci-test without issues.

End-to-end testing of Reservation features on AWS isn’t practical here, the costs are prohibitive. If you know a sane way to do real-world testing without racking up a giant bill, let me know.

Does this change impact docs?

  • Yes, PR includes docs updates
  • Yes, issue opened: #
  • No

@B-Yan B-Yan requested a review from a team as a code owner November 20, 2025 23:26
@netlify
Copy link

netlify bot commented Nov 20, 2025

Deploy Preview for karpenter-docs-prod canceled.

Name Link
🔨 Latest commit 8887628
🔍 Latest deploy log https://app.netlify.com/projects/karpenter-docs-prod/deploys/691fa3bdf1e9470008abc083

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant