OpenShift · FinOps · capacity planning
What does this cluster actually need, and what should we therefore buy?
corepair measures real demand, converts it into a subscription count using the rules that actually apply, and produces a cost case that shows its working — including which part of a multi-year saving is a contract term and which part is just a forecast.
Why
The count is wrong. Core-pair rounding happens per node, so ten 6-vCPU nodes cost twenty core-pairs rather than fifteen. Infra nodes are exempt only if they are tainted, not merely labelled. Meanwhile most estates reserve several times the CPU they use — and requests, not usage, are what force nodes to exist at all.
The savings case is mostly assumptions. A three-year lock gets justified with one number that quietly combines a discount differential you can hold a vendor to with assumed price growth and an assumed worse renewal discount, which you cannot.
The headline, itemised
32 units over three years, on the figures from a real quote. The headline saving is €15,110. Here is what it is made of.
Which is not an argument against the longer term — it is an argument for converting those forecasts into terms. A written commitment to hold the renewal discount turns an assumption into an obligation. If the vendor won't commit to it, the case is weaker than the headline suggested, and now you know by exactly how much.
Sizing
| Through wave | Apps | vCPU | GiB | Nodes (CPU) | Nodes (RAM) | Binding | Core-pairs |
|---|---|---|---|---|---|---|---|
| wave-1 · pilot | 2 | 3.5 | 14 | 1 | 1 | memory | 4 |
| wave-2 · core systems | 4 | 13.5 | 54 | 3 | 3 | memory | 8 |
| wave-3 · remainder | 5 | 17.5 | 86 | 4 | 4 | memory | 10 |
Each row is cumulative: it is the capacity you need in place by that wave — which is also when you should be buying it, not three years early.
Memory saturates before CPU on this shape. Adding vCPU to the node template would raise the licence count without relieving the actual constraint; adding RAM raises capacity without raising it.
Halving the quantity beats any plausible term discount. Quantity is the larger lever, and right-sizing is the thing that moves it — which is why the measuring comes before the negotiating.
The rules it encodes
| Rule | Why it matters |
|---|---|
| Core-pair = 2 cores = 4 vCPU, rounded up per node | Node shape drives cost independently of workload |
| Control-plane nodes are exempt | Unless the cluster is compact and they are schedulable |
| Infra nodes need the label and the taint | An untainted infra node can still run application pods |
| Bare-metal is per node, with an optional core cap | Break-even against core-pairs depends entirely on density |
| Sizing follows the binding resource | Memory-bound estates pay for CPU-rich nodes and get nothing |
| Headroom and HA spares are licensed too | The N+1 node is not free |
The test file doubles as the readable specification. Disagree with a rule? The useful contribution is a failing test plus a citation — a rule with no citation is folklore, and folklore is what this replaces.
Four commands
corepair measure --prometheus …What do we run, versus what did we reserve?corepair auditWhat are we subscribing that we needn't be?corepair plan --plan plan.yamlWhat will the waves need, and when?corepair cost --pricing pricing.yamlWhat should we buy, and what is the saving made of?Vendor pricing is confidential and contract-specific. A figure copied from someone else's repository is worse than none, because it looks authoritative. The example file carries placeholders, and the tool refuses to run until you have replaced them with your own quote.
The same goes for your plan and your snapshots. Publish the schema, never the estate.
$ corepair cost --pricing pricing.yaml error: pricing.yaml still contains placeholder prices. Replace them with figures from your own quote before relying on any output.
Reproducibility
--snapshot-out freezes a measurement so it can be replayed, reviewed, and committed next to the proposal. The workbook it exports is built from live formulas rather than pasted results: shaded input cells, everything else recalculating from them.
That last part matters more than it sounds. A reader who disagrees with an assumption can change the cell and watch the answer move, instead of asking you to run it again and waiting a day to find out whether it mattered.