Skip to content

Generate your first blueprint

By the end of this tutorial you will have compiled the solver, run it against a small bundled cluster, and read the blueprint it produces. It takes about ten minutes, most of which is Rust compiling.

You do not need a Kubernetes cluster. Nothing here touches one.

You need:

  • Rust (stable) with cargo
  • make
  • A clone of the repository
Terminal window
git clone https://github.com/AlexanderSlokov/kuberina.git
cd kuberina
Terminal window
make solver-build

The first build downloads and compiles dependencies, so expect a few minutes. Subsequent builds are fast.

Step 2: Run it against the homelab dataset

Section titled “Step 2: Run it against the homelab dataset”

The repository ships two datasets. Start with the small one — it solves almost instantly, which makes it a much better first read than the hyperscale benchmark.

Terminal window
make solver-homelab

That target expands to a direct invocation of the solver:

Terminal window
cd solver && cargo run --release -- plan \
--infra testdata/homelab_infra.yaml \
--workloads testdata/homelab_workloads.yaml

Two inputs go in:

  1. --infra — the cluster topology: node capacity, taints, labels.
  2. --workloads — the pods to place, with their resource requirements.

The solver prints a stowage plan to the console and writes solver/kuberina_solution.yaml.

Open solver/kuberina_solution.yaml. This is the artifact the whole tool exists to produce — a concrete placement for every pod, with the constraints needed to pin it there.

This is the file you would review with your team, argue about, regenerate, and eventually apply. It is the point of the exercise. Do not skim past it.

Now run the dataset the paper reports on — 186 nodes and 2,714 pods, named irina after the container ship.

Terminal window
make solver-irina

This is where the genetic algorithm earns its keep. The solver auto-scales its parameters by problem size: above 500 pods it switches to a population of 1,024 running up to 1,000 generations, and prints a line telling you so.

Datacenter-scale detected (2714 pods) — cranking GA to maximum

Expect this to take meaningfully longer than the homelab run.

Real clusters should not be packed to 100% of nominal capacity. The --pareto flag scales node capacity by a percentage, leaving headroom:

Terminal window
make solver-irina-pareto-80

This solves against 80% of each node’s capacity while still reporting the plan against true capacities.

The Python tooling under research/ validates the solution independently and renders a cluster heatmap.

Terminal window
make research-inspect

This writes kuberina_dashboard.html. Open it in a browser to explore utilisation node by node.

Once the individual pieces make sense, one target chains them together: generate test data, solve, inspect, and run the formal mathematical proof.

Terminal window
make research-full-pipeline

This target uses uv to manage the Python environment, so you need uv installed for the research steps.

You have compiled the optimiser, produced a blueprint for a small cluster and a hyperscale one, applied a capacity safety margin, and independently validated the result.