skrooge
A quick and dirty kubernetes cost estimator
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.
- Update the changelog. Craft doesn't edit
CHANGELOG.mdfor 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 tomain. Make sure CI onmainis green. - 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:autoand bump keywords likeminorneed a newerminVersionin.craft.ymlthan this project sets. Leave force empty unless you need to release despite an open issue labelledrelease-blocker. - Craft prepares the release. It creates a
release/X.Y.Zbranch frommain, runsscripts/bump-version.sh(which usesuv versionto updatepyproject.tomlanduv.lock), commits that asrelease: X.Y.Z, and opens apublish: getsentry/skrooge@X.Y.Zissue in getsentry/publish. - CI builds the package. The push to
release/X.Y.Zruns 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. - Approve the release. Add the
acceptedlabel 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 intomain. Nothing is published until the label is added, so to abandon a release, close the publish issue and delete therelease/X.Y.Zbranch. - Check it. Once PyPI has the new version,
uvx skrooge@X.Y.Z --versionshould 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)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| skrooge-1.1.0.tar.gz | 180.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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.