A command-line bootstrapping and management tool for k0s zero friction kubernetes clusters.
Example output of k0sctl deploying a k0s cluster:
INFO ==> Running phase: Connect to hosts
INFO ==> Running phase: Detect host operating systems
INFO [ssh] 10.0.0.1:22: is running Ubuntu 20.10
INFO [ssh] 10.0.0.2:22: is running Ubuntu 20.10
INFO ==> Running phase: Prepare hosts
INFO ==> Running phase: Gather host facts
INFO [ssh] 10.0.0.1:22: discovered 10.12.18.133 as private address
INFO ==> Running phase: Validate hosts
INFO ==> Running phase: Gather k0s facts
INFO ==> Running phase: Download k0s binaries on hosts
INFO ==> Running phase: Configure k0s
INFO ==> Running phase: Initialize the k0s cluster
INFO [ssh] 10.0.0.1:22: installing k0s controller
INFO ==> Running phase: Install workers
INFO [ssh] 10.0.0.1:22: generating token
INFO [ssh] 10.0.0.2:22: installing k0s worker
INFO [ssh] 10.0.0.2:22: waiting for node to become ready
INFO ==> Running phase: Disconnect from hosts
INFO ==> Finished in 2m2s
INFO k0s cluster version 1.22.3+k0s.0 is now installed
INFO Tip: To access the cluster you can now fetch the admin kubeconfig using:
INFO k0sctl kubeconfig
You can find example Terraform and bootloose configurations in the examples/ directory.
Download the desired version for your operating system and processor architecture from the k0sctl releases page. Make the file executable and place it in a directory available in your $PATH.
As the released binaries aren't signed yet, on macOS and Windows, you must first run the executable via "Open" in the context menu and allow running it.
If you have a working Go toolchain, you can use go install to install k0sctl to your $GOPATH/bin.
go install github.com/k0sproject/k0sctl@latestHomebrew (macOS, Linux)
brew install k0sproject/tap/k0sctlChocolatey (Windows)
Note: The chocolatey package is community maintained, any issues should be reported to the maintainer of the package.
choco install k0sctlIt is possible to use k0sctl as a docker/OCI container:
# pull the image
docker pull ghcr.io/k0sprojects/k0sctl:latest
# create a backup
docker run -it --workdir /backup \
-v ./backup:/backup \
-v ./k0sctl.yaml:/etc/k0s/k0sctl.yaml \
ghcr.io/k0sprojects/k0sctl:latest k0sctl backup --config /etc/k0s/k0sctl.yamlk0sctl completion > /etc/bash_completion.d/k0sctlk0sctl completion > /usr/local/share/zsh/site-functions/_k0sctl
# For oh my zsh
k0sctl completion > $ZSH_CACHE_DIR/completions/_k0sctlk0sctl completion > ~/.config/fish/completions/k0sctl.fishK0sctl is ready for use and in continuous development.
For repository layout, development, and testing guidelines (including notes for AI assistants), see AGENTS.md.
The main function of k0sctl is the k0sctl apply subcommand. Provided a configuration file describing the desired cluster state, k0sctl will connect to the listed hosts, determines the current state of the hosts and configures them as needed to form a k0s cluster.
The default location for the configuration file is k0sctl.yaml in the current working directory. To load a configuration from a different location, use:
k0sctl apply --config path/to/k0sctl.yamlIf the configuration cluster version spec.k0s.version is greater than the version detected on the cluster, a cluster upgrade will be performed. If the configuration lists hosts that are not part of the cluster, they will be configured to run k0s and will be joined to the cluster.
Generate a configuration template. Use --k0s to include an example spec.k0s.config k0s configuration block. You can also supply a list of host addresses via arguments or stdin.
Output a minimal configuration template:
k0sctl init > k0sctl.yamlOutput an example configuration with a default k0s config:
k0sctl init --k0s > k0sctl.yamlCreate a configuration from a list of host addresses and pipe it to k0sctl apply:
k0sctl init 10.0.0.1 10.0.0.2 [email protected]:8022 | k0sctl apply --config -Takes a backup of the cluster control plane state into the current working directory.
The files are currently named with a running (unix epoch) timestamp, e.g. k0s_backup_1623220591.tar.gz.
Restoring a backup can be done as part of the k0sctl apply command using --restore-from k0s_backup_1623220591.tar.gz flag.
Restoring the cluster state is a full restoration of the cluster control plane state, including:
- Etcd datastore content
- Certificates
- Keys
In general restore is intended to be used as a disaster recovery mechanism and thus it expects that no k0s components actually exist on the controllers.
Known limitations in the current restore process:
- The control plane address (
externalAddress) needs to remain the same between backup and restore. This is caused by the fact that all worker node components connect to this address and cannot currently be re-configured.
Uninstall k0s from the hosts listed in the configuration.
Connects to the cluster and outputs a kubeconfig file that can be used with kubectl or kubeadm to manage the kubernetes cluster.
Example:
$ k0sctl kubeconfig --config path/to/k0sctl.yaml > k0s.config
$ kubectl get node --kubeconfig k0s.config
NAME STATUS ROLES AGE VERSION
worker0 NotReady <none> 10s v1.20.2-k0s1The configuration file is in YAML format and loosely resembles the syntax used in Kubernetes. YAML anchors and aliases can be used.
To generate a simple skeleton configuration file, you can use the k0sctl init subcommand.
Configuration example:
apiVersion: k0sctl.k0sproject.io/v1beta1
kind: Cluster
metadata:
name: my-k0s-cluster
user: admin
spec:
hosts:
- role: controller
installFlags:
- --debug
ssh:
address: 10.0.0.1
user: root
port: 22
keyPath: ~/.ssh/id_rsa
- role: worker
installFlags:
- --debug
ssh:
address: 10.0.0.2
k0s:
version: 0.10.0
config:
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
name: my-k0s-cluster
spec:
images:
calico:
cni:
image: calico/cni
version: v3.16.2
options:
wait:
enabled: true
drain:
enabled: true
evictTaint:
enabled: false
taint: k0sctl.k0sproject.io/evict=true
effect: NoExecute
concurrency:
limit: 30
uploads: 5Simple bash-like expressions are supported in the configuration for environment variable substition.
$VARor${VAR}value ofVARenvironment variable${var:-DEFAULT_VALUE}will useVARif non-empty, otherwiseDEFAULT_VALUE$$var- escape, result will be$var.- And several other expressions
The configuration file syntax version. Currently the only supported version is k0sctl.k0sproject.io/v1beta1.
In the future, some of the configuration APIs can support multiple types of objects. For now, the only supported kind is Cluster.
The main object definition, see below
Information that can be used to uniquely identify the object.
Example:
metadata:
name: k0s-cluster-name
user: kubernetes-adminA list of cluster hosts. Host requirements:
- Currently only linux targets are supported
- The user must either be root or have passwordless
sudoaccess. - The host must fulfill the k0s system requirements
See host object documentation below.
Settings related to the k0s cluster.
See k0s object documentation below.
One of:
controller- a controller hostcontroller+worker- a controller host that will also run workloadssingle- a single-node cluster host, the configuration can only contain one hostworker- a worker host
When true and used in conjuction with the controller+worker role, the default taints are disabled making regular workloads schedulable on the node. By default, k0s sets a node-role.kubernetes.io/master:NoSchedule taint on controller+worker nodes and only workloads with toleration for it will be scheduled.
When true, the k0s binaries for target host will be downloaded and cached on the local host and uploaded to the target.
When false, the k0s binary downloading is performed on the target host itself
A path to a file on the local host that contains a k0s binary to be uploaded to the host. Can be used to test drive a custom development build of k0s.
A path on the node where to install the k0s binary.
A URL to download the k0s binary from. The default is to download from the k0s repository. The URL can contain '%'-prefixed tokens that will be replaced with the host's information, see tokens.
Override host's hostname. When not set, the hostname reported by the operating system is used.
Set host's k0s data-dir.
Set host's k0s kubelet-root-dir.
Extra flags passed to the k0s install command on the target host. See k0s install --help for a list of options.
List of key-value pairs to set to the target host's environment variables.
Example:
environment:
HTTP_PROXY: 10.0.0.1:443List of files to be uploaded to the host.
Example:
- name: image-bundle
src: airgap-images.tgz
dstDir: /var/lib/k0s/images/
perm: 0600Inline data example:
- name: motd
data: |
Powered by k0s
dst: /etc/motd
perm: 0644name: name of the file "bundle", used only for logging purposes (optional)src: File path, an URL or Glob pattern to match files to be uploaded. URL sources will be directly downloaded using the target host. If the value is a URL, '%'-prefixed tokens can be used, see tokens. (required whendatais not set)data: Inline file data to write to the destination. Use together withdstordst+dstDir. (required whensrcis not set)dstDir: Destination directory for the file(s).k0sctlwill create full directory structure if it does not already exist on the host (default: user home)dst: Destination filename for the file. Only usable for single file uploads (default: basename of file)perm: File permission mode for uploaded file(s) (default: same as local)dirPerm: Directory permission mode for created directories (default: 0755)user: User name of file/directory owner, must exist on the host (optional)group: Group name of file/directory owner, must exist on the host (optional)
Run a set of commands on the remote host during k0sctl operations.
Example:
hooks:
connect:
after:
- echo "connected and detected" >> k0sctl-connect.log
upgrade:
before:
- echo "about to upgrade" >> k0sctl-upgrade.log
after:
- echo "upgraded" >> k0sctl-upgrade.log
apply:
before:
- date >> k0sctl-apply.log
after:
- echo "apply success" >> k0sctl-apply.logThe currently available "hook points" are:
connect:after: Runs immediately after OS detection completes
apply: Runs duringk0sctl applybefore: Runs after configuration and host validation, right before configuring k0s on the hostafter: Runs before disconnecting from the host after a successful apply operation
upgrade: Runs duringk0sctl applybefore: Runs for each host that is going to be upgraded, before the upgrade beginsafter: Runs for each host that was upgraded, after the upgrade completes
install: Runs duringk0sctl applybefore: Runs on each host just before installing its k0s components. This includes the first controller (Initialize the k0s cluster), additional controllers, and workers.after: Runs on each host immediately after installing its k0s components (service started and ready checks done).
backup: Runs duringk0s backupbefore: Runs before k0sctl runs thek0s backupcommandafter: Runs before disconnecting from the host after successfully taking a backup
reset: Runs duringk0sctl resetor whenk0sctl applyresets a host.before: Runs after gathering information about the cluster, right before starting to remove the k0s installation.after: Runs before disconnecting from the host after a successful reset operation
Notes:
- Hooks run on each host that defines them, using the same remote user as the connection. If elevated privileges are required, prefix commands with
sudo. - In dry-run mode, hooks are not executed; k0sctl prints what would run on each host.
- Hooks execute only on hosts targeted by the related phase. For example,
upgradehooks run only for hosts that need upgrade.
Override OS distribution auto-detection. By default k0sctl detects the OS by reading /etc/os-release or /usr/lib/os-release files. In case your system is based on e.g. Debian but the OS release info has something else configured you can override k0sctl to use Debian based functionality for the node with:
- role: worker
os: debian
ssh:
address: 10.0.0.2Override private network interface selected by host fact gathering. Useful in case fact gathering picks the wrong private network interface.
- role: worker
os: debian
privateInterface: eth1Override private IP address selected by host fact gathering. Useful in case fact gathering picks the wrong IPAddress.
- role: worker
os: debian
privateAddress: 10.0.0.2SSH connection options.
Example:
spec:
hosts:
- role: controller
ssh:
address: 10.0.0.2
user: ubuntu
keyPath: ~/.ssh/id_rsaIt's also possible to tunnel connections through a bastion host. The bastion configuration has all the same fields as any SSH connection:
spec:
hosts:
- role: controller
ssh:
address: 10.0.0.2
user: ubuntu
keyPath: ~/.ssh/id_rsa
bastion:
address: 10.0.0.1
user: root
keyPath: ~/.ssh/id_rsa2SSH agent and auth forwarding are also supported, a host without a keyfile:
spec:
hosts:
- role: controller
ssh:
address: 10.0.0.2
user: ubuntu$ ssh-add ~/.ssh/aws.pem
$ ssh -A user@jumphost
user@jumphost ~ $ k0sctl applyPageant or openssh-agent can be used on Windows.
IP address of the host
Username to log in as.
TCP port of the SSH service on the host.
spec.hosts[*].ssh.keyPath <string> (optional) (default: ~/.ssh/identity ~/.ssh/id_rsa ~/.ssh/id_dsa)
Path to an SSH key file. If a public key is used, ssh-agent is required. When left empty, the default value will first be looked for from the ssh configuration (default ~/.ssh/config) IdentityFile parameter.
Localhost connection options. Can be used to use the local host running k0sctl as a node in the cluster.
This must be set true to enable the localhost connection.
An alternative SSH client protocol that uses the system's openssh client for connections.
Example:
spec:
hosts:
- role: controller
openSSH:
address: 10.0.0.2The only required field is the address and it can also be a hostname that is found in the ssh config. All other options such as user, port and keypath will use the same defaults as if running ssh from the command-line or will use values found from the ssh config.
An example SSH config:
Host controller1
Hostname 10.0.0.1
Port 2222
IdentityFile ~/.ssh/id_cluster_esa
If this is in your ~/.ssh/config, you can simply use the host alias as the address in your k0sctl config:
spec:
hosts:
- role: controller
openSSH:
address: controller1
# if the ssh configuration is in a different file, you can use:
# configPath: /path/to/configIP address, hostname or ssh config host alias of the host
Username to connect as.
Remote port.
Path to private key.
Path to ssh config, defaults to ~/.ssh/config with fallback to /etc/ssh/ssh_config.
The default mode of operation is to use connection multiplexing where a ControlMaster connection is opened and the subsequent connections to the same host use the master connection over a socket to communicate to the host.
If this is disabled by setting disableMultiplexing: true, running every remote command will require reconnecting and reauthenticating to the host.
Additional options as key/value pairs to use when running the ssh client.
Example:
openSSH:
address: host
options:
ForwardAgent: true # -o ForwardAgent=yes
StrictHostkeyChecking: false # -o StrictHostkeyChecking: noIf set to true k0sctl will remove the node from kubernetes and reset k0s on the host.
The version of k0s to deploy. When left out, k0sctl will default to using the latest released version of k0s or the version already running on the cluster.
Possible values are stable and latest.
When spec.k0s.version is left undefined, this setting can be set to latest to allow k0sctl to include k0s pre-releases when looking for the latest version. The default is to only look for stable releases.
Enable k0s dynamic config. The setting will be automatically set to true if:
- Any controller node has
--enable-dynamic-configininstallFlags - Any existing controller node has
--enable-dynamic-configin run arguments (k0s status -o json)
Note: When running k0s in dynamic config mode, k0sctl will ONLY configure the cluster-wide configuration during the first time initialization, after that the configuration has to be managed via k0s config edit or k0sctl config edit. The node specific configuration will be updated on each apply.
See also:
Embedded k0s cluster configuration. See k0s configuration documentation for details.
When left out, the output of k0s config create will be used.
You can also host the configuration in a separate file or as a separate YAML document in the same file in the standard k0s configuration format.
apiVersion: k0sctl.k0sproject.io/v1beta1
kind: Cluster
spec:
hosts:
- role: single
ssh:
address: 10.0.0.1
---
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
name: my-k0s-cluster
spec:
api:
externalAddress: 10.0.0.2The spec.options field contains options that can be used to modify the behavior of k0sctl.
Example:
spec:
options:
wait:
enabled: true
drain:
enabled: true
evictTaint:
enabled: false
taint: k0sctl.k0sproject.io/evict=true
effect: NoExecute
concurrency:
limit: 30
workerDisruptionPercent: 10
uploads: 5If set to false, k0sctl will not wait for k0s to become ready after restarting the service. By default, k0sctl waits for nodes to become ready before continuing to the next operation. This is functionally the same as using --no-wait on the command line.
If set to false, k0sctl will skip draining nodes before performing disruptive operations like upgrade or reset. By default, nodes are drained to allow for graceful pod eviction. This is functionally the same as using --no-drain on the command line.
The duration to wait for pods to be evicted from the node before proceeding with the operation.
The duration to wait for the drain operation to complete before timing out.
Use --force in kubectl when draining the node.
Ignore DaemonSets when draining the node.
Continue even if there are pods using emptyDir (local data that will be deleted when the node is drained).
If pod DeletionTimestamp older than N seconds, skip waiting for the pod. Seconds must be greater than 0 to skip.
Label selector to filter pods on the node
When enabled, k0sctl will apply a taint to nodes before service-affecting operations such as upgrade or reset. This is used to signal workloads to be evicted in advance of node disruption. You can also use the --evict-taint=k0sctl.k0sproject.io/evic=true:NoExecute command line option to enable this feature.
The taint to apply when evictTaint.enabled is true. Must be in the format key=value.
The taint effect to apply. Must be one of:
NoExecuteNoSchedulePreferNoSchedule
Whether to also apply the taint to nodes with the controller+worker dual role. By default, taints are only applied to worker-only nodes.
The maximum number of hosts to operate on concurrently during cluster operations. Same as the --concurrency command line option.
The maximum percentage of worker nodes that can be disrupted at the same time during operations such as upgrade. This is used to ensure that a minimum number of worker nodes remain available during the operation. The value must be between 0 and 100.
The maximum number of concurrent file uploads to perform. Same as the --concurrent-uploads command line option.
The following tokens can be used in the k0sDownloadURL and files.[*].src fields:
%%- literal%%p- host architecture (arm, arm64, amd64)%v- k0s version (v1.21.0+k0s.0)%x- k0s binary extension (.exe on Windows, empty elsewhere)
Any other tokens will be output as-is including the % character.
Example:
- role: controller
k0sDownloadURL: https://files.example.com/k0s%20files/k0s-%v-%p%x
# Expands to https://files.example.com/k0s%20files/k0s-v1.21.0+k0s.0-amd64