Skip to main content

skrooge

PyPI Changelog Tests License

A quick and dirty kubernetes cost estimator

OIG 0uCanRKKeLq7XwJysZQ3 Ebenezer scrooge standing at the helm of a ship, pencil sketch

Why

Scaling a Kubernetes deployment up or down changes how many nodes it needs, so it changes what you pay. Working that out by hand is grunt work every time: look up the node's machine type, figure out whether the change is CPU-bound or memory-bound, count the extra nodes, and price them. skrooge does that arithmetic for you using bundled GCP machine specs and regional pricing.

For example, doubling a deployment of 2 CPU / 3GiB pods from 16 to 32 replicas on c2-standard-30 nodes (30 cores, 120GiB) adds 32 cores and 48GiB of memory. CPU runs out first, so it needs ceil(32 / 30) = 2 more nodes:

$ uvx skrooge estimate --replicas 16 --cpu 2000 --mem 3072 --instance c2-standard-30
This workload is running on c2-standard-30 instances in us-central1 with 30 cores and 120GiB of memory.
This workload will require 32.0 cores and 48.0 GiB of memory. This workload is cores-constrained.
This workload will require 2 instances, costing $2.51/h (or $1829/m (or $21950/y)) at sud rates.

For a scale-down, pass the size of the reduction: the cost skrooge reports is what you'd save.

It's a quick estimate, not a bill. It assumes pods pack perfectly onto whole nodes, and it ignores the node capacity reserved for the system and DaemonSets, cluster autoscaler behaviour, and storage or network costs. Prices come from a snapshot in skrooge/instances.json, taken whenever that file was last regenerated.

Installation

skrooge requires Python 3.11 or newer. The quickest way to use it is to run it with uvx, which fetches and runs the latest release without installing it:

uvx skrooge --help

To install it as a standalone tool instead, use uv:

uv tool install skrooge

Or with pipx or pip:

pipx install skrooge
pip install skrooge

Usage

Estimate the cost of adding 5.81 cores and 9950MiB of memory to each of 1000 replicas running on n2-highcpu-64 nodes:

$ uvx skrooge estimate --replicas 1000 --cpu 5810 --mem 9950 --instance n2-highcpu-64
This workload is running on n2-highcpu-64 instances in us-central1 with 64 cores and 64GiB of memory.
This workload will require 5810.0 cores and 9716.796875 GiB of memory. This workload is memory-constrained.
This workload will require 152 instances, costing $278.98/h (or $203658/m (or $2443898/y)) at sud rates.

Use --region, --cost-class, and --format json to change the region, pricing tier, and output format:

uvx skrooge estimate --replicas 1000 --cpu 5810 --mem 9950 --instance n2-highcpu-64 --region europe-west1 --cost-class cud-1y --format json

If you installed skrooge, drop the uvx prefix and run skrooge directly (or python -m skrooge).

For help, run:

uvx skrooge --help
uvx skrooge estimate --help

Development

This project uses uv to manage its environment. To contribute, check out the code and install the dependencies:

cd skrooge
uv sync

To run the tests:

uv run pytest

To lint and format:

uv run ruff check .
uv run ruff format .

To run the same checks automatically on each commit, install the pre-commit hooks:

uv tool install pre-commit
pre-commit install

To update the instances.json file:

uv run --group scrape python skrooge/scraper.py > skrooge/instances.json

Releasing

Releases are made with Sentry's Craft and follow Semantic Versioning. Anything that drops support for a Python version needs at least a minor version bump.

  1. Update the changelog. Craft doesn't edit CHANGELOG.md for this project, so in a PR, rename the ## [Unreleased] heading to ## [X.Y.Z] - YYYY-MM-DD, add a new empty ## [Unreleased] heading above it, and merge it to main. Make sure CI on main is green.
  2. Start the release. In GitHub, go to Actions → Release → Run workflow, run it on main, and enter the new version, e.g. 1.1.0. Enter an explicit version: auto and bump keywords like minor need a newer minVersion in .craft.yml than this project sets. Leave force empty unless you need to release despite an open issue labelled release-blocker.
  3. Craft prepares the release. It creates a release/X.Y.Z branch from main, runs scripts/bump-version.sh (which uses uv version to update pyproject.toml and uv.lock), commits that as release: X.Y.Z, and opens a publish: getsentry/skrooge@X.Y.Z issue in getsentry/publish.
  4. CI builds the package. The push to release/X.Y.Z runs the Publish Python Package workflow, which runs the tests and uploads the built sdist and wheel as an artifact for Craft. Wait for it to pass; the publish issue links to the check runs.
  5. Approve the release. Add the accepted label to the publish issue. Craft then uploads the package to PyPI, tags the release and creates a GitHub release, and merges the release branch back into main. Nothing is published until the label is added, so to abandon a release, close the publish issue and delete the release/X.Y.Z branch.
  6. Check it. Once PyPI has the new version, uvx skrooge@X.Y.Z --version should print it.

Metadata

Release files for skrooge 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for skrooge 1.1.0
File Size Uploaded Provenance
skrooge-1.1.0.tar.gz 180.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for skrooge 1.1.0
File Interpreter ABI Platform
skrooge-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 361.3 kB

Release files / skrooge-1.1.0.tar.gz

Download URL skrooge-1.1.0.tar.gz
Size 180.5 kB
Tags Source
SHA-256 checksum
How to use checksums
3d9b0a3ed2e5d4d6b3cf1dbb13c944cc3d9342a559e09053ea8d0e15b02be727
BLAKE2b-256 checksum
How to use checksums
e3d49133a15e76691db4e82a4dd1e660f85b5d3e0628b6a01c589731119808c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.11.2

Release files / skrooge-1.1.0-py3-none-any.whl

Download URL skrooge-1.1.0-py3-none-any.whl
Size 180.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e47ab3434da638222a25f9b11d380b5c6cf4a50b377f8e3ede97ee4d9bab58bd
BLAKE2b-256 checksum
How to use checksums
fd04022bcd55129f063ad86d78cc5f9488b74a153738224942789e72aff4bcae
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.11.2

Security for skrooge 1.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page