Documentation

kubesoloctl CLI

One binary for the whole lifecycle, on Linux hosts or in a container on macOS and WSL2.

What kubesoloctl is

kubesoloctl is a single, dependency-free binary that manages the whole KubeSolo lifecycle: pre-flight checks, download, service setup, kubeconfig wiring, configuration, upgrades, reset and uninstall. It runs KubeSolo in one of two ways:

  • On the host (Linux): installs the KubeSolo binary and runs it as a system service. This is the production path for edge devices and gateways.
  • In a container: runs KubeSolo inside a container on Docker. This is for development and CI on macOS, Windows (WSL2) or any Linux machine with Docker. On macOS it is the only mode, because KubeSolo is Linux-only.

It complements the install script, which remains the quickest way to install on a Linux host.

Getting kubesoloctl

Download the binary for your platform from the release and put it on your PATH:

bash
1$ curl -fL -o kubesoloctl https://github.com/portainer/kubesolo/releases/download/v1.2.1/kubesoloctl-linux-amd64
2$ chmod +x kubesoloctl
3$ sudo mv kubesoloctl /usr/local/bin/

Assets are named kubesoloctl-<os>-<arch>. Published targets: linux-amd64, linux-arm64, linux-arm (ARMv7; ARMv6 boards such as the Pi 1 and original Pi Zero are not supported), linux-riscv64, darwin-amd64 and darwin-arm64. On Windows, use the Linux binary inside WSL2. kubesoloctl is a pure-Go binary, so the same file works on glibc and musl.

Run modes

ModeFlagWhere KubeSolo runsTypical use
service(default on Linux)Binary under the host init systemProduction, edge
container--run-mode=containerInside a Docker containerDevelopment and CI on macOS, WSL2 or Linux
daemon--run-mode=daemonBackground process with a PID fileHosts without a supported init system
foreground--run-mode=foregroundThe current terminalDebugging

On macOS the mode is always container; asking for another mode is an error.

Installing on a Linux host

bash
1$ sudo kubesoloctl install
2$ kubectl get nodes --watch

install runs the pre-flight checks (root, RFC 1123 hostname, no Docker, iptables xt_comment, nftables and iptables on Alpine, cgroup controllers, free ports 2379, 6443 and 10443), installs /usr/local/bin/kubesolo, writes /etc/kubesolo/config.yaml, starts the service and merges the admin kubeconfig into ~/.kube/config.

install flags

FlagEnv varDefaultDescription
--versionKUBESOLO_VERSIONv1.2.1KubeSolo release to install (defaults to the version kubesoloctl was built for).
--pathKUBESOLO_PATH/var/lib/kubesoloData directory.
--run-modeKUBESOLO_RUN_MODEserviceservice, daemon, foreground or container.
--nameKUBESOLO_NAMEkubesoloInstance name: container name and kubeconfig context in container mode.
--node-ipKUBESOLO_NODE_IPauto-detectPin the node IP on multi-NIC hosts.
--mtuKUBESOLO_MTUauto-detectMTU for the CNI bridge. In container mode it also sizes the Docker network the container runs on.
--apiserver-extra-sansKUBESOLO_APISERVER_EXTRA_SANS(none)Extra SANs for the API server certificate.
--d2kKUBESOLO_D2KfalseDocker-compatible API translator on port 2376.
--d2k-namespaceKUBESOLO_D2K_NAMESPACEd2kNamespace d2k uses.
--portainer-edge-idKUBESOLO_PORTAINER_EDGE_ID(none)Portainer Edge ID.
--portainer-edge-keyKUBESOLO_PORTAINER_EDGE_KEY(none)Portainer Edge key.
--portainer-edge-asyncKUBESOLO_PORTAINER_EDGE_ASYNCfalseEdge async mode.
--portainer-edge-imageKUBESOLO_PORTAINER_EDGE_IMAGEdocker.io/portainer/agent:ltsEdge Agent image.
--cpu-manager-policyKUBESOLO_CPU_MANAGER_POLICYnonestatic gives Guaranteed pods exclusive cores. Not in container mode.
--cpu-manager-policy-optionsKUBESOLO_CPU_MANAGER_POLICY_OPTIONS(none)Options for the static policy.
--reserved-cpusKUBESOLO_RESERVED_CPUS0 under staticCpuset reserved for the host.
--system-reservedKUBESOLO_SYSTEM_RESERVED(none)Resources withheld from allocatable.
--debugKUBESOLO_DEBUGfalseDebug logging.
--pprof-serverKUBESOLO_PPROF_SERVERfalsepprof server on port 6060.
--proxyKUBESOLO_PROXY(none)HTTP/HTTPS proxy injected into the service environment.
--offline-installKUBESOLO_OFFLINE_INSTALL(none)Install from a local .tar.gz or binary.
--install-prereqsKUBESOLO_INSTALL_PREREQSfalseInstall missing OS prerequisites, such as nftables on Alpine.
--imageKUBESOLO_IMAGEportainer/kubesolo:<version>Container image for container mode.
--container-portsKUBESOLO_CONTAINER_PORTS(none)Host ports to publish in container mode. Ignored, with a warning, on host installs.

CPU pinning options are validated before anything is installed, so a bad cpuset fails immediately instead of crash-looping the service.

Local storage is on by default. To turn it off, set storage.localPath.enabled: false in /etc/kubesolo/config.yaml and restart. That only stops KubeSolo deploying it on later starts. If it is already running, also remove it with kubectl delete namespace local-path-storage and kubectl delete storageclass local-path. Settings without an install flag, such as the metrics endpoint, are changed the same way with kubesoloctl config set.

Container mode (macOS, WSL2, Linux dev)

Container mode needs a reachable Docker engine (Docker Engine or Docker Desktop). kubesoloctl honours DOCKER_HOST.

bash
1# implied on macOS; elsewhere ask for it
2$ kubesoloctl install --run-mode=container
3$ kubectl get nodes --watch

kubesoloctl starts the portainer/kubesolo:<version> image, publishes the API server on a random localhost port, and merges a kubeconfig that points at it. Inside the container, KubeSolo switches to container mode, which adjusts cgroups, mounts, DNS and eviction thresholds so the node starts cleanly in a container.

The host port can change after an upgrade or reset. Refresh the kubeconfig when it does:

bash
1$ kubesoloctl kubeconfig fetch
Development, not production. Container mode is for laptops and CI. It does not support the static CPU manager policy, and the production path for edge hardware is a host install.

Publishing workload ports

In container mode KubeSolo has its own network namespace, so NodePort and LoadBalancer services and hostPort pods are reachable only on ports published when the container is created. This is the same model as Kind's extraPortMappings:

bash
1$ kubesoloctl install --run-mode=container --container-ports=9001,8080:80,9000-9100,53/udp
EntryMeaning
9001Host 9001 to container 9001.
9000-9100A range, host port equal to container port.
8080:80Host 8080 to container 80.
127.0.0.1:80:80Bind on one host IP only.
53/udpUDP. TCP is assumed otherwise.

Bare ports and ranges bind on all interfaces, so other machines can reach them. Scope a port to localhost with the 127.0.0.1:host:container form. Published ports are kept across upgrade and reset.

Running several instances

--name runs independent instances side by side in container mode. Each gets its own container (kubesolo-<name>), data volume and kubeconfig context, plus its own Docker context with d2k. Pass the same --name to upgrade, reset, uninstall and d2k fetch. For kubeconfig fetch, set KUBESOLO_NAME or pass --container=kubesolo-<name>:

bash
1$ kubesoloctl install --run-mode=container --name=dev
2$ kubesoloctl install --run-mode=container --name=ci --container-ports=8081:80
3$ kubectl config use-context kubernetes-admin@dev
4$ kubesoloctl uninstall --name=ci --purge

Command reference

CommandPurpose
installInstall KubeSolo and start the service or container.
checkRun the pre-flight checks only. Flags: --install-prereqs, --pprof-server (also check port 6060).
upgrade --version=<v>Upgrade to a newer release, keeping data and configuration.
resetWipe all cluster state and start a fresh cluster, keeping the install.
uninstallStop and remove KubeSolo and its service files; optionally its data.
kubeconfigPrint, write, view or merge the admin kubeconfig.
configRead, change, edit and validate /etc/kubesolo/config.yaml.
d2k fetchCreate a Docker context for the d2k endpoint of a container-mode instance.
downloadBuild an offline bundle for an air-gapped machine.
completionGenerate shell completion for bash, zsh, fish or PowerShell.
versionPrint kubesoloctl version information.

Each command detects whether the instance runs as a container or a host service and acts on it.

upgrade, reset and uninstall

bash
1$ sudo kubesoloctl upgrade --version=v1.2.1
2$ sudo kubesoloctl upgrade --version=v1.2.1 --offline-install=./kubesolo-v1.2.1-linux-amd64.tar.gz
3$ sudo kubesoloctl reset # asks for confirmation; --force skips it
4$ sudo kubesoloctl uninstall --purge
CommandFlags
upgrade--version (required), --offline-install, --name. On a host install it stops the service, replaces the binary, moves a flag-based service definition into the configuration file, and restarts.
reset--force, --path, --name. Deletes the database, certificates and CNI configuration, keeps the binary and service, and restarts into a fresh cluster.
uninstall--purge (also delete /var/lib/kubesolo), --remove-kubeconfig, --keep-config (keep /etc/kubesolo/config.yaml, which is removed by default), --name.

kubeconfig

bash
1$ sudo kubesoloctl kubeconfig # print the admin kubeconfig
2$ sudo kubesoloctl kubeconfig -o ./admin.kubeconfig # write it to a file
3$ kubesoloctl kubeconfig view # print it, from the container in container mode
4$ kubesoloctl kubeconfig fetch # merge it into ~/.kube/config

fetch reads from the container when one is running and from the local data directory otherwise. fetch and view accept --container, --socket (Docker socket) and --path.

config

bash
1$ sudo kubesoloctl config get # the whole file
2$ sudo kubesoloctl config get network.nodeIP # one setting
3$ sudo kubesoloctl config set network.nodeIP 10.0.0.5 # change one setting
4$ sudo kubesoloctl config edit # open in $EDITOR, validated on save
5$ kubesoloctl config validate -f ./candidate.yaml # check a file without installing it
6$ kubesoloctl config schema # every setting, type, default and flag

Nothing is written until validation passes. When the configuration API is enabled, config goes through it instead of editing the file under the running process. Changes take effect on the next restart; kubesoloctl prints which settings need one. The --config flag points at a file other than /etc/kubesolo/config.yaml.

d2k fetch

For a container-mode instance installed with --d2k, d2k fetch copies the CA and client certificate out of the container into ~/.docker/d2k/<name>/ and creates a Docker context named after the instance:

bash
1$ kubesoloctl d2k fetch
2$ docker --context kubesolo ps

The published d2k port is random, so run d2k fetch again after each upgrade or reset. For a host install, see connecting to d2k.

download

bash
1$ kubesoloctl download --version=v1.2.1 --path=./bundle
2$ kubesoloctl download --version=v1.2.1 --path=./bundle --arch=arm64
3$ kubesoloctl download --version=v1.2.1 --path=./bundle --arch=amd64-musl

The bundle holds the KubeSolo release archive and the kubesoloctl binary. On macOS --arch is required, since there is no macOS KubeSolo binary. See air-gapped installation.