Documentation

KubeSolo documentation

Architecture, reference guides, FAQ and troubleshooting for KubeSolo v1.2.1.

Architecture

KubeSolo is a single-node Kubernetes distribution with clustering and HA logic removed, ingress simplified, and defaults tuned for resource-limited environments. Everything it needs ships in one binary.

There is no etcd quorum logic, no leader election, no multi-node networking overlay, and no control plane components that assume peer nodes exist. The Kubernetes API server, controller manager, kubelet and kube-proxy all run in a single process, and state is persisted locally in SQLite through Kine. There is no kube-scheduler either: NodeSetter, a lightweight mutating admission webhook built into KubeSolo, sets spec.nodeName on every new pod.

The result is a full Kubernetes control loop that is operationally equivalent to a standard Kubernetes cluster for all workload-facing APIs, but with a fraction of the resource footprint, because none of the clustering machinery is present even in dormant form.

Not a toy: KubeSolo runs the full Kubernetes control loop and exposes the complete Kubernetes API. The difference from upstream Kubernetes is in what has been removed, not in what has been simplified or proxied.

What is inside v1.2.1

ComponentIn KubeSolo v1.2.1
Kubernetes1.35.7: API server, controller manager, kubelet and kube-proxy in one process
DatastoreKine 0.16 over SQLite, in place of etcd
SchedulingNodeSetter mutating admission webhook (no kube-scheduler)
Container runtimeEmbedded containerd 2.2.5 and crun 1.26, or a host runtime
NetworkingBridge CNI (CNI plugins v1.9.0), kube-proxy in iptables or nftables mode, built-in LoadBalancer
DNSCoreDNS 1.14.4 at 10.43.0.10
Storagelocal-path-provisioner v0.0.36 as the default StorageClass
OptionalPortainer Edge Agent, d2k Docker API, Prometheus metrics endpoint, configuration API

Default paths

PathContents
/usr/local/bin/kubesoloThe KubeSolo binary.
/etc/kubesolo/config.yamlThe configuration file.
/var/lib/kubesoloAll cluster state: certificates, the Kine database, containerd and kubelet data. Set with path at install time.
/var/lib/kubesolo/pki/admin/admin.kubeconfigAdmin kubeconfig. Context kubernetes-admin@kubesolo, server https://<node IP>:6443.
/var/lib/kubesolo/kubeletkubelet root directory. Point CSI drivers here.

The ports KubeSolo listens on are listed under Networking.

Documentation

New to KubeSolo? Start with the quick start. The reference is organised by topic:

FAQ

What is KubeSolo actually designed for?

KubeSolo was built explicitly for extremely resource-constrained environments: devices with less than 1 GB of RAM, basic CPUs, and simple SD card storage. If your hardware is a 512 MB RAM, single-core ARM processor, KubeSolo was made for it. Normal operation sits around 200 MB RAM.

If my devices have 1 GB or more RAM, should I still use KubeSolo?

Probably not. With 1 GB or more, standard lightweight distributions like K3s, K0s, or MicroK8s are generally a better fit. They are CNCF-certified and more widely adopted for general-purpose use. That said, K3s and K0s typically need around 400 MB to run comfortably, and MicroK8s around 2 GB. The gauge below illustrates where each distribution sits:

RAM footprint comparison

KubeSolo ~200 MB
K3s / K0s ~400 MB
MicroK8s ~2 GB
0 512 MB 1 GB 1.5 GB 2 GB

Is KubeSolo CNCF-certified?

Not currently. KubeSolo has not been through CNCF certification. It runs upstream Kubernetes 1.35 with its upstream defaults, and a nightly job runs a focused subset of the upstream Kubernetes e2e [Conformance] suite against it with Sonobuoy (test/e2e/conformance.sh), covering ConfigMaps, Secrets, Pods, Services, Deployments, ReplicaSets, DNS, projected and downward API volumes, and EmptyDir. Tests that need more than one node, or that are serial, disruptive or slow, are skipped. That is a regression signal, not a certification.

Why use KubeSolo instead of Docker or Podman?

Docker and Podman remain the lightest way to run containers, ideal if absolute minimal resource use is the only priority. But Kubernetes has become the industry standard, particularly in IoT, Industrial IoT, and Industry 4.0. Many off-the-shelf industrial software packages explicitly require it. KubeSolo is the compromise: Kubernetes within the tightest constraints.

Why does KubeSolo sometimes appear to use more than 200 MB?

Linux aggressively uses available memory for caching to optimize performance. On a device with more than 1 GB RAM, monitoring tools may show KubeSolo using more. That reported figure includes cache that the OS allocated speculatively. When memory contention occurs, KubeSolo releases it and operates within its actual ~200 MB target. The chart below shows the difference between reported and actual working set:

KubeSolo memory breakdown

~200 MB
+variable
actual working set
reported (incl. cache)
KubeSolo working set Linux OS cache (reclaimable)

Why use Kubernetes at the edge at all?

The Kubernetes ecosystem gives you mature tooling for deploying and operating software with real complexity. Operators, Helm charts, and the wider community output remove the need to build and maintain your own automation. A few hundred megabytes of RAM buys access to everything the ecosystem already provides and continues to improve... that is usually a very reasonable trade.

Why not run the device as a worker node with cloud-based control plane nodes?

Worker nodes depend on a remote control plane, which breaks when edge locations experience intermittent or intentional loss of connectivity. When the connection drops, kubelet can restart containers but the rest of the automation stops. A single-node cluster keeps the control plane on the device, so scheduling, updates, and reconciliation continue even when the site is offline.

Does KubeSolo support multi-node or multi-cluster configurations?

Single-node by design. To centrally manage many standalone KubeSolo instances (for example, hundreds of edge devices), you need a multi-cluster management solution. Portainer gives you centralized visibility, configuration, and control over each KubeSolo instance through a single UI. CNCF Open Cluster Management is another option.

How does KubeSolo differ from KubeEdge?

KubeEdge requires edge devices to act as worker nodes in a centrally managed, network-connected Kubernetes cluster. That architecture isn't suitable for environments with unreliable or intentionally offline connectivity. KubeSolo provides fully autonomous, self-contained single-node clusters designed for standalone and offline edge deployments.

How do I manage KubeSolo?

KubeSolo is standard Kubernetes. Any Kubernetes client works: VSCode with the Kubernetes extension, OpenLens, Headlamp, K9s, or Portainer. ArgoCD can also connect remotely via the Kubernetes API. With d2k enabled, the Docker CLI works too. You are not locked into any specific tooling.

What hardware was tested?

The following hardware has been confirmed to run KubeSolo: NVIDIA Jetson with Ubuntu, Atom X5 with Arch Linux, Zimaboard with Ubuntu, Raspberry Pi CS5 with Armbian Bookworm, and Siemens IOT2050 with Siemens Industrial OS. KubeSolo is also well suited to industrial compute hardware from Wago (CC100 series), Bosch, Siemens (SIMATIC IOT2000), Phoenix Contact (PLCnext AXC F 1152), Beckhoff (CX7000), and Advantech compact edge series.

Can I run KubeSolo on macOS or Windows?

For development, yes. KubeSolo itself is a Linux binary, but kubesoloctl container mode runs it in a Docker container on macOS or under Windows WSL2, and merges a kubeconfig for you. Production nodes run Linux.

Is there a kube-scheduler?

No. On a single node there is nothing to choose between, so KubeSolo replaces the scheduler with NodeSetter, a lightweight mutating admission webhook that sets spec.nodeName on every new pod. The kubelet still enforces resources, host ports and node affinity, so a pod that does not fit is rejected rather than left Pending.

Troubleshooting

Node not reaching Ready

Check the service logs. Most startup failures are port conflicts, missing cgroup controllers or insufficient permissions.

bash
1$ journalctl -u kubesolo -f # systemd
2$ tail -f /var/log/kubesolo.log # daemon mode

On slow storage such as SD cards, components can need longer than the default 600 seconds to pass their startup health checks. Raise kubernetes.apiServer.startupTimeoutSeconds.

The installer stops with a pre-flight error

MessageFix
Docker is installed on this systemRemove Docker, or use kubesoloctl container mode on development machines.
Hostname contains uppercase letters / is not RFC 1123 compliantRename the host to lowercase letters, digits, - and ., starting and ending with a letter or digit.
iptables command not found / xt_comment module is not availableInstall iptables and make sure the kernel has xt_comment.
Required cgroups controllers are missingEnable cpuset, cpu, io, memory and pids, for example by adding cgroup_enable=cpuset cgroup_enable=cpu cgroup_enable=io cgroup_memory=1 cgroup_enable=pids to the kernel boot parameters. On Alpine, re-run with --install-prereqs.
nftables (nft) is required on Alpineapk add nftables, or re-run with --install-prereqs.

A configuration change has no effect

Settings apply on restart, and flags or environment variables in the service definition override the file. Check what KubeSolo resolves:

bash
1$ sudo kubesolo --config=/etc/kubesolo/config.yaml --print-config
2$ grep -- '--' /etc/systemd/system/kubesolo.service

kubectl: connection refused or x509 errors

Check that the kubeconfig exists and that its server: address is reachable:

bash
1$ sudo kubectl --kubeconfig /var/lib/kubesolo/pki/admin/admin.kubeconfig get nodes

When the node IP changes, KubeSolo re-signs its certificates and the server: address in a copied kubeconfig goes out of date. Copy it again, or run kubesoloctl kubeconfig fetch. If you connect through a name or address other than the node IP, add it to kubernetes.apiServer.extraSANs. On multi-NIC hosts, pin network.nodeIP.

Pods rejected with NodeAffinity, NodePorts or OutOfcpu

KubeSolo has no scheduler, so a pod that does not fit is bound to the node anyway and then rejected by the kubelet instead of staying Pending. Check nodeSelector and affinity rules, host ports used by more than one replica, and resource requests:

bash
1$ kubectl describe pod <pod-name>
2$ kubectl describe node

Database errors after a power cut

Set storage.dbWALRepair: true and restart. KubeSolo checks the SQLite database at startup and clears corrupt WAL files.