Skip to main content

Personal project

Volta: a Kubernetes platform built from scratch on OpenStack

The problem

Cloud infrastructure hides its physical cost. A pod drawing 40 W looks exactly like a pod drawing 4 W: same dashboard, same green checkmark, same invoice line buried in an aggregate. Capacity ends up sized by intuition, and “we should optimize this” stays an opinion, because the thing being optimized is never measured.

Volta closes that gap on a small scale. It builds a complete platform from nothing, then adds the signal most platforms lack: watts and grams of CO2eq attributed to each workload, shown next to what that workload actually costs.

Two constraints

  • Everything is destroyed and rebuilt. A step that cannot survive a full destroy and rebuild cycle is not finished.
  • Every measurement states its own margin of error. Energy figures taken inside a virtual machine are estimates, and the repository says so wherever it reports one.
Infomaniak Public Cloud · dc3-ak3s cluster3 nodes · 3 zonesInternetHTTPS trafficOperatorSSHGit repositorydesired stateOpenTofuprovisionsOctaviafloating IPBastiononly SSH way inSwiftencrypted stateTraefikcert-managerDemowhoamiArgo CDapp of appsPrometheusGrafanaKeplerplannedVelerobackupsInfomaniak Public Cloud · dc3-ak3s cluster3 nodes · 3 zonesInternetHTTPS trafficOperatorSSHGit repositorydesired stateOpenTofuprovisionsOctaviafloating IPBastiononly SSH way inSwiftencrypted stateTraefikcert-managerDemowhoamiArgo CDapp of appsPrometheusGrafanaKeplerplannedVelerobackups

Hover over or select a block to read the details.

Where the project stands

The first phase is done. The platform is built with make up and destroyed with make down: a private network and encrypted state, three nodes in three availability zones reached through a bastion, a k3s cluster bootstrapped in a single apply, HTTPS ingress through an Octavia load balancer, Traefik and cert-manager, Argo CD delivering the whole cluster from the repository, Prometheus and Grafana. The CI checks every change and holds no secret.

Backups are proven, and their scope is stated: Velero backs up the monitoring namespace, with Prometheus’s history, and its restore was played on 28 October, in about three minutes.

The second phase remains: the power draw of each pod, a carbon model, dashboards as code, and one optimization measured before and after. Measured inside a virtual machine, without access to the processor’s counters, power will be an estimate, with its margin of error.

The decisions

Five decisions shape the platform, each recorded as an ADR with the options rejected and why.

  • Self-managed k3s rather than managed Kubernetes: Infomaniak’s managed service is cheaper and better for production, but the cluster bootstrap is part of what the repository demonstrates. One server per zone, embedded etcd: a lost zone costs one member, not the quorum.
  • State in Swift, without a lock: the platform’s S3 layer refuses the conditional write a lock needs; one operator and saved plans stand in.
  • A bastion as the only way in: no node has a public address, and the exposed machine is not a member of the cluster.
  • OpenTofu outside the cluster, Argo CD inside: every resource has one owner.
  • Build from the workstation, check in CI: make up and make down run on the workstation; the CI checks every change, holds no secret, and pins every action to a commit.

What broke

The repository keeps a list of its failures: how a platform fails and recovers says more about it than what it does on a good day. Three examples.

A state lock the platform cannot take. With state locking enabled, planning failed before doing anything. OpenTofu takes that lock with a conditional write, and Swift 2.30.1, which serves the S3 API here, answers every conditional write with 501 NotImplemented. Swift accepts it from version 2.36.0; until the platform runs it, the state has no lock.

A rule on main that let a red pull request through. The rule protecting main had been saved without its required checks. A test pull request with a duplicated key in Traefik’s values failed its checks and merged anyway: Argo CD turned Traefik into a one-replica Deployment for six minutes, until a revert. The checks are now required.

A destroy that forgot half the platform. make down timed out on the router’s interface. Two servers, the bastion and the load balancer were still running, without a delete request, but no longer in the state: it had shrunk from 91 to 43 KB at the destroy’s first write. They were deleted by hand. The cause is not found; what is left is now listed after every destroy.

Code on GitHub

  • OpenStack
  • OpenTofu
  • k3s
  • Argo CD
  • Helm
  • Traefik
  • cert-manager
  • Prometheus
  • Grafana
  • Velero

← Back to projects