KubeSolo: Kubernetes on the machine that only ever needed one node
Ultra-lightweight Kubernetes
At a glance
- What is it?
- KubeSolo is a single-node Kubernetes distribution that deletes the clustering code rather than disabling it, replacing etcd with SQLite, dropping the scheduler for a mutating webhook, and running the API server, controller manager and kubelet inside one process under 200 MB of RAM.
- Who is it for?
- KubeSolo fits the edge, factory, kiosk and laptop workloads the project describes, where a full cluster was never justified and Docker or Podman was the only realistic option, and it fits anyone who needs the Kubernetes API, Helm charts and CRDs to work unchanged on one host.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The premise: most of the world runs on one node
KubeSolo describes itself as ultra-lightweight, OCI-compliant, single-node Kubernetes under 200 MB of RAM, with no etcd and no clustering overhead, and the argument for it starts from a gap in the standard distribution. Standard Kubernetes is built for multi-node clusters, and a lot of the real world runs on single nodes: edge devices, factory gateways, developer laptops, remote site hardware, IoT controllers, and the millions of machines that have been running Docker or Podman because standing up a full cluster was overhead that could not be justified for a single workload host. That creates a choice you did not want to make. You either run Docker and give up the Kubernetes ecosystem entirely, or you run K3s or MicroK8s and accept carrying clustering machinery you will never use. KubeSolo takes the other route, removing the clustering code rather than disabling it, and the result is full Kubernetes with the complete API, the full control loop and full ecosystem compatibility.
Three deletions, not three disablements
The project is explicit that the footprint is small because the clustering machinery is absent, not dormant, and that most lightweight distributions take the opposite approach by keeping the multi-node code present but inactive. Three specific design decisions produce the smaller footprint. There is no etcd, with SQLite through Kine replacing it as the state store. There is no Kubernetes Scheduler, replaced by NodeSetter, a lightweight mutating admission webhook built into KubeSolo that sets spec.nodeName on every new pod, without the full scheduling machinery. And all components run inside a single process rather than as separate binaries. The practical result is a full Kubernetes control loop that runs comfortably on devices with 512 MB of RAM, on flash storage, and in air-gapped environments. The rest of the stack is bundled as well, with containerd and crun for the container runtime, CoreDNS for name resolution, and Kine for SQLite-based storage, packaged as a single binary with minimal OS dependencies.
Two variants, and the choice is about connectivity
KubeSolo ships in two variants, and the reason is a trade of binary size against offline capability. The online variant is the default, with a smaller binary, and it requires internet access, so it is the one for devices with reliable connectivity where binary size matters more. The offline variant is larger and needs no internet, for air-gapped environments, factory floors and edge devices with intermittent or no connectivity. The offline variant bundles all required container images, CNI plugins and runtime dependencies directly in the binary, so nothing needs to be fetched from the internet at install time or at runtime, while the online variant pulls container images from public registries at startup. The default installer downloads the online variant, and the project says to use the offline one if your devices are air-gapped or have unreliable internet access.
Installing, and the three ways to do it
The install is a one-liner for the online variant, run with sudo, and KubeSolo then starts as a systemd service.
curl -sfL https://get.kubesolo.io | sudo sh -The offline variant uses an environment variable.
curl -sfL https://get.kubesolo.io | KUBESOLO_OFFLINE=true sudo -E sh -For a target with no internet at all, you download the bundle on a connected machine and transfer it.
# On a connected Linux machine with the same architecture and libc as the target, download the offline bundle
curl -sfL https://get.kubesolo.io | sh -s -- --offline --download-only=/tmp/kubesolo-bundle
# Transfer the files to the target machine, then install
sudo sh install.sh --offline-install=<archive.tar.gz>The bundle matches the OS, architecture and libc of the machine that downloaded it, so a bundle fetched on macOS, or on a glibc host for an Alpine target, will not work, and the project points to the releases page for the matching archive in that case. The installer detects the architecture and libc automatically, downloading the standard binary on glibc systems such as Ubuntu, CentOS and Debian, and the musl-compatible binary on Alpine. Settings are written to /etc/kubesolo/config.yaml, every installer flag is listed in the install script flags reference, and unreleased changes from the develop branch are served from a different host that the project says not to use in production.
The pre-flight check that stops the installer
There is a warning before the install steps that is worth understanding rather than working around. You must ensure that no container engine, Docker, Podman or containerd, is installed or active on the target system beforehand, including any background services or residual installations that could interfere with KubeSolo networking, and the installer refuses to continue if Docker is installed or running. The reason is structural. KubeSolo runs its own containerd with its own CNI plugins, and a second container engine on the same host will fight it over network interfaces, mount namespaces and the containerd socket. There is one deliberate exception. KubeSolo can attach to a host-managed containerd or CRI-O instead of running its own, by setting runtime.endpoint, for example to a unix socket path, and the host then provides the runtime, the OCI runtime, the CNI plugin binaries and the sandbox image. The supported platforms are ARM, ARM64, x86_64 and RISC-V 64.
Pointing kubectl at it
After installation you copy the admin kubeconfig out of the cluster's PKI directory to the machine where kubectl lives and set the context.
kubectl config use-context kubernetes-admin@kubesolo
kubectl get nodes
# You should see a single node in Ready stateThe path of the kubeconfig is fixed by the install layout, under /var/lib/kubesolo/pki/admin/admin.kubeconfig, and the context name follows the same pattern. The single node in Ready state is the expected result, and it is the moment where the scheduler decision becomes visible in practice: because there is no scheduler, the node assignment was handled by the admission webhook instead, so the pod lands on the only node that exists without any scheduling decision being made. The container image in the repository documents the same flow for a Docker-based evaluation, where the kubeconfig is read out of the running container and the API server address is rewritten to point at the published port.
Where KubeSolo is the wrong choice
The obvious boundary is that this is a single-node design with the clustering code removed, so it does not grow. A workload that needs a second node for availability, for rolling updates across machines, or for a scheduler to place pods by resource fit is outside what this project is, and the project does not pretend otherwise, since the deleted components are listed as removed rather than disabled. The second boundary is operational, and it is that the whole control loop lives in one process with a SQLite state store, which is a different durability and upgrade story from a cluster with a replicated etcd. The third is that a machine already running Docker or Podman cannot be upgraded in place, because the installer refuses to continue. The dependency list in the project manifest also shows the shape of the compromise, with containerd, Kine, the CRI client and apiserver libraries all compiled into one binary alongside the Docker client library, and SQLite built with the dbstat virtual table enabled so Kine can report database size.
Editorial conclusion
KubeSolo fits the edge, factory, kiosk and laptop workloads the project describes, where a full cluster was never justified and Docker or Podman was the only realistic option, and it fits anyone who needs the Kubernetes API, Helm charts and CRDs to work unchanged on one host. It does not fit a team that expects to add a second node later, because the clustering machinery is removed rather than disabled, and it does not fit a machine that already runs Docker or Podman, since the installer refuses to continue in that case. Before you install, decide between the online and offline variants, and check the install script flags reference for the settings you need, since the installer writes its configuration to /etc/kubesolo/config.yaml and the development branch is served from a different host that the project says not to use in production.
Frequently asked questions
How does KubeSolo stay under 200 MB of RAM?
By removing the clustering code rather than disabling it. There is no etcd, with SQLite through Kine as the state store, no Kubernetes Scheduler, replaced by a NodeSetter mutating admission webhook that sets spec.nodeName on every new pod, and all components run inside a single process instead of as separate binaries.
How do I install KubeSolo on an air-gapped machine?
On a connected machine with the same architecture and libc, run the install script with the --offline and --download-only flags to fetch a bundle, transfer it to the target, and install with sudo sh install.sh and the --offline-install flag. A bundle fetched on the wrong libc or architecture will not work, so the matching archive from the releases page is the fallback.
Can I install KubeSolo on a machine that already runs Docker?
No, the installer refuses to continue if Docker is installed or running, and the same applies to Podman or containerd, because a second container engine would interfere with KubeSolo's networking. The one exception is attaching to a host-managed containerd or CRI-O by setting runtime.endpoint.
What is the difference between the online and offline KubeSolo builds?
The online variant is the default, has a smaller binary and pulls container images from public registries at startup, so it needs internet access. The offline variant is larger and bundles all required container images, CNI plugins and runtime dependencies in the binary, so nothing is fetched at install or runtime, which suits air-gapped and intermittent-connectivity devices.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/portainer-kubesolo)Was this useful?