Kubernetes Provisioner
The Kubernetes Provisioner lets you create a ready-to-use Kubernetes cluster from Cockpit in a few guided steps. Cockpit builds the virtual machines, installs a lightweight, fully compatible Kubernetes distribution (k3s), wires up networking and storage, and hands you a cluster you can connect to with the standard kubectl tool.
You do not need to prepare servers, run installers, or copy join commands by hand. You choose how big the cluster should be, what shape its nodes take, and where it should run, and Cockpit does the rest in the background while you keep working.
Who this guide is for
This guide is for people who want to run a Kubernetes cluster — application teams, platform operators, and administrators. It focuses on what you do in the Cockpit interface and how to use the cluster afterwards.
License
The Kubernetes Provisioner requires the Kubernetes entitlement on your Cockpit license. If it is missing, add it to your subscription and import the updated license before you begin. All of the capabilities in this guide — creating clusters, multiple worker node pools, custom CPU and node configuration, adding and removing pools, scaling and upgrading — are covered by that one entitlement.
Before you start
Two things must be in place before your first cluster. If your administrator has already set up the environment, you can skip straight to Create a cluster.
- A cluster template. Cockpit clones every node from a prepared Ubuntu template image. The template carries the Kubernetes components for the versions it was built with, so nodes install quickly and without needing to download anything at boot. It appears automatically as an option in the wizard.
- A suitable network. Every node must sit on a distributed network — one that spans the physical hosts in your compute cluster — so that nodes placed on different hosts can reach each other. See Choosing a network.
Create a cluster
- In the left-hand inventory tree, right-click your compute Cluster (or the Datacenter it belongs to).
- Choose Kubernetes → New Cluster.
- The Kubernetes Provisioning Wizard opens with five short steps.
Because you launched it from a specific place in the inventory, the wizard already knows which datacenter and compute cluster you mean. All node placement is limited to the hosts of that compute cluster — nodes will never land on a host in another datacenter.
When you finish the wizard, Cockpit starts building the cluster in the background. You can close the wizard and watch progress in the Tasks panel. The cluster appears in the inventory and moves through provisioning to active when it is ready to use.
Step 1 — Basics
| Field | What it does |
|---|---|
| Cluster Name | A friendly name for the cluster. It is used in the inventory, in node names, and in the downloaded config file. |
| Target Network | The distributed network the nodes connect to. Only distributed networks are offered. See Choosing a network. |
| Node IP Addressing | DHCP (default) lets the network hand out addresses. Static lets you reserve a fixed range for the cluster — see Static node addresses. |
| Kubernetes Version | The k3s version to install. Versions baked into the template install fastest; pick the newest unless you have a reason not to. |
| Network Plugin (CNI) | How pods talk to each other. See Network plugins. Leave on Flannel if unsure. |
Step 2 — Control Plane
The control plane is the "brain" of the cluster. Choose how resilient it should be:
- Single (1 node) — Simplest and lightest. Good for development and testing. If that one node is lost, the cluster is unavailable until it recovers.
- High Availability (3 nodes) — Recommended for production. The cluster keeps running even if one control-plane node fails.
You also set the CPU, Memory, Datastore, and Disk size for each control-plane node, and a Placement choice:
- Auto-Distribute (recommended) — Cockpit spreads the three HA nodes across three different physical hosts automatically, so a single host outage cannot take down the whole control plane.
- Manual — You pick exactly which host each node runs on, from the hosts in your compute cluster.
Two advanced sections are collapsed by default and can be left alone for most clusters:
- CPU Mode & Topology — how the virtual CPU is presented to the node. See CPU mode and topology.
- Node Labels & Taints — Kubernetes metadata applied to the control-plane nodes. See Node labels and taints. A common use is to add a
NoScheduletaint here so ordinary application pods stay off the control plane.
Step 3 — Workers
Workers run your actual applications. A cluster can have one or more worker node pools. Each pool is a group of identical nodes with its own name, size, hardware shape, placement, and Kubernetes metadata. See Worker node pools for when you would want more than one.
For each pool you set:
| Field | What it does |
|---|---|
| Pool Name | A short name for the pool. Node names are built from it: cluster prod, pool gpu → nodes prod-gpu-1, prod-gpu-2, and so on. See Naming rules. |
| Node Count | How many nodes to start with. You can change this at any time later. |
| CPU, Memory, Datastore, Disk size | The resources for every node in this pool. |
| Placement | Auto-Distribute balances nodes across the hosts in your compute cluster, or use Manual to pin them to specific hosts (useful when certain hosts have special hardware such as GPUs). |
| CPU Mode & Topology (advanced) | See CPU mode and topology. |
| Node Labels & Taints (advanced) | See Node labels and taints. |
Click Add Node Pool to define another pool with different settings. The first pool is named workers unless you rename it.
Step 4 — Credentials & CSI
- SSH Public Key — Optional. Paste a public key here if you want direct SSH access to the node VMs for troubleshooting. It is not required to use the cluster; Cockpit also generates its own key pair for the cluster, which you can download from the cluster page.
- Storage Tiers (CSI) — Choose how applications get persistent storage. You can enable more than one. See Storage for your applications.
Step 5 — Review
Review the summary — the size of the cluster, each pool and its settings, the resources it will use, and which hosts the nodes will land on. Click Provision to start. The wizard closes and a task begins.
Choosing a network
The network you pick in Step 1 has the biggest impact on whether your cluster forms successfully, so it is worth a moment's thought.
Every node must be able to reach every other node, and reach the internet during setup for anything not already in the template. Because Cockpit spreads nodes across the physical hosts in your compute cluster, the network must span those hosts — which is why the wizard only offers distributed networks. A network that exists on a single host cannot connect nodes on two different hosts, and is not listed.
WARNING
The network's gateway must actually provide internet access for the nodes, not just forward their traffic. A gateway that routes but does not translate addresses lets nodes boot and respond to ping while every download silently fails, and the cluster never finishes provisioning. If you are not sure which network is intended for Kubernetes, ask your administrator.
Static node addresses
By default nodes get their addresses from DHCP. If your network has no DHCP server, or you want the cluster's addresses to be predictable, choose Static in Step 1 and fill in:
| Field | Example |
|---|---|
| Subnet | 192.168.1.0/24 |
| Gateway | 192.168.1.1 |
| Nameservers | 8.8.8.8, 1.1.1.1 |
| IP Range | 192.168.1.100 – 192.168.1.120 |
Cockpit assigns each node the next free address in the range and keeps it for the node's lifetime. The range must have room for every node you plan to have — control plane, every worker pool, and any nodes you add later. If a later scale-up or a new pool would exhaust the range, Cockpit refuses it up front with a clear message rather than leaving half-built nodes behind.
Network plugins (CNI)
The network plugin controls how pods communicate and whether you can enforce network security policies. You choose it once, in Step 1.
| Plugin | Best for | Notes |
|---|---|---|
| Flannel (default) | Most clusters, development, simple setups | Lightweight and reliable. No network policies. |
| Calico | Production with tenant isolation | Adds Kubernetes NetworkPolicy support for controlling pod-to-pod traffic. |
| Cilium | High-performance, advanced networking | eBPF-based, with rich L3–L7 policies and traffic visibility. |
If you have no specific requirement, Flannel is a safe default.
Worker node pools
A node pool is a group of worker nodes that share the same configuration. Most small clusters need just one. You want more than one when different workloads need different machines:
- A
databasepool with more memory and a faster datastore, next to a generalworkerspool. - A
gpupool pinned to the hosts that have GPUs, with a taint so only GPU workloads land there. - An
ingresspool with a label your ingress controller selects, kept small and stable while the rest of the cluster scales.
Each pool has its own name, node count, CPU / memory / disk / datastore, placement, CPU mode and topology, and labels and taints. Pools are managed from the cluster's Node Pool tab after creation — see Manage node pools.
Naming rules
Pool names become part of every node's name, so they follow the same rules as Kubernetes hostnames:
- Lowercase letters, digits and
-; must start and end with a letter or digit; at most 40 characters. - Must be unique within the cluster.
- The names
worker,masterandcontrol-planeare reserved, because nodes named from them would collide with the default worker pool or the control plane. Useworkersfor the default pool, or a distinct name such asinfraorcompute.
CPU mode and topology
By default each node gets a general-purpose virtual CPU. The CPU Mode & Topology section on each pool lets you change how the CPU is presented, which matters for workloads that inspect the processor or that are licensed per socket.
CPU Mode
| Mode | What the node sees | When to use it |
|---|---|---|
| Host Model | A CPU matching the physical host's model | Good balance of performance and portability. |
| Host Passthrough | The physical host's CPU exactly, with every feature | Maximum performance; workloads that need specific CPU instructions. Nodes should stay on hosts with identical CPUs. |
| Custom Named Model | A specific CPU model you name (for example Broadwell-IBRS) | When you need identical CPU features across hosts with different physical processors. |
Topology lets you shape the vCPUs into sockets × dies × cores × threads. The product must equal the pool's vCPU count — the wizard shows the arithmetic as you type and will not let you continue with a mismatch. For example, 4 vCPUs can be 1 × 1 × 4 × 1 (one socket, four cores) or 2 × 1 × 2 × 1 (two sockets, two cores each), which changes what per-socket-licensed software counts.
Leave the section collapsed to accept the defaults. The configured mode and topology are shown for each pool on the Node Pool tab after creation.
Node labels and taints
Labels are key–value tags that let you steer workloads onto specific nodes with a nodeSelector or node affinity. Taints do the opposite: they keep workloads off a node unless the workload explicitly tolerates the taint. Together they are how Kubernetes turns "a pool of GPU machines" into something the scheduler actually understands.
Set them per pool in the Node Labels & Taints section:
| Setting | Format | Example |
|---|---|---|
| Label | key = value | tier = database |
| Taint | key=value:Effect, where Effect is NoSchedule, PreferNoSchedule or NoExecute | dedicated=gpu:NoSchedule |
The wizard validates the format as you type — a mistyped effect or an invalid key is refused before anything is built, rather than producing a node that silently lacks its taint.
Applied at creation
Labels and taints are given to each node when it first joins the cluster, and every node added later by scaling or a new pool gets its pool's labels and taints the same way. They cannot be changed on an existing pool from Cockpit — to change them for nodes that already exist, use kubectl label and kubectl taint, or create a new pool with the settings you want and remove the old one.
A workload then targets the pool like this:
spec:
nodeSelector:
tier: database
tolerations:
- key: dedicated
operator: Equal
value: gpu
effect: NoScheduleKeeping applications off the control plane
k3s does not taint its control-plane nodes, so by default ordinary pods can be scheduled onto them. For a production cluster, add a taint such as dedicated=control-plane:NoSchedule to the control plane in Step 2. Cluster system components already run where they need to; your applications will stay on the workers.
Keys under the kubernetes.io/ and k8s.io/ prefixes (including node-role.kubernetes.io/) are reserved for Kubernetes itself and cannot be set here — choose your own key instead.
Storage for your applications
Applications that need to keep data (databases, file uploads, and so on) request storage through a storage tier. Enable the tiers you need in Step 4; you can turn on more than one and choose per-application which to use.
| Tier | What it gives you | When to use it |
|---|---|---|
| Local Path (on by default) | Fast storage on the node where the pod runs | Simple, high-speed storage. Data stays on one node, so it is not available if the pod moves to another node. |
| Shared (NFS) | Storage many pods can share at once, available across nodes | When pods need to share files (ReadWriteMany), or keep their data when they move between nodes. |
| Replicated (Longhorn) | Highly available block storage, copied across nodes | Stateful workloads like databases that must survive a node failure. |
Shared (NFS). Pick an NFS datastore already registered in Cockpit and the server address and export path are filled in for you, or enter an external NFS server by hand. Cockpit checks that the server is reachable from the cluster's own network — which is what matters, since that is where every mount is made — before installing the driver, and confirms the driver is running on every node before the cluster is declared active.
Replicated (Longhorn). Set the replica count — how many copies of each volume Longhorn keeps, each on a different worker. The default of 3 survives the loss of two workers. The count cannot exceed the number of worker nodes; the wizard refuses a count the cluster could never satisfy, because Longhorn would otherwise leave every volume permanently degraded. Longhorn is configured to keep replicas on worker nodes only, never on the control plane.
Adding storage later
Storage tiers are chosen at creation. If you remove worker nodes below your Longhorn replica count later, volumes become degraded until enough workers exist again — scale back up to restore full redundancy.
Connect to your cluster
Once the cluster status is active, you can connect with kubectl, the standard Kubernetes command-line tool.
Open the cluster's detail page and click Download Kubeconfig. Cockpit gives you a ready-to-use file with the correct server address already filled in.
Save it and point
kubectlat it:bashmkdir -p ~/.kube mv ~/Downloads/kubeconfig-my-cluster.yaml ~/.kube/config-my-cluster chmod 600 ~/.kube/config-my-cluster export KUBECONFIG=~/.kube/config-my-clusterCheck it works:
bashkubectl get nodes --show-labelsYou should see your control-plane and worker nodes listed as Ready, each carrying the labels of its pool.
TIP
To avoid setting KUBECONFIG every time, add the export line to your shell profile (~/.bashrc or ~/.zshrc).
Manage node pools
Open the cluster and choose the Node Pool tab. Every pool is a row in a table showing its name, role, node count with how many are Ready, the vCPU / memory / disk / datastore of its nodes, and its CPU configuration, labels and taints. The control-plane pool is listed for reference and marked Locked — it cannot be scaled or removed here.
Each worker pool has Scale and Remove actions in its row, and the tab has an Add Pool button. All three are available only while the cluster is active; during any change the actions are disabled so two operations cannot collide. Every change appears in the cluster's Tasks tab and in the Tasks panel.
Scale a pool
- Click Scale on the pool's row.
- Set the new desired node count and confirm.
Scaling up adds new node VMs with the pool's exact configuration — resources, CPU mode, labels and taints — and joins them to the cluster automatically. When the new nodes show as Ready, they start accepting workloads.
Scaling down is done gracefully. Before a node is removed, Cockpit first moves any Longhorn replicas off it so volumes keep their redundancy, then drains it — moving its running workloads to the remaining nodes — and only then removes the VM and frees its resources.
If a node fails to be added
If a new node cannot be created (for example, the chosen host is temporarily out of capacity), Cockpit cleans up the incomplete node automatically and adjusts the pool to the count it actually reached. Simply run scale-up again to retry — you will not be left with half-finished nodes.
Add a pool to a running cluster
You do not need to rebuild a cluster to give it a new class of node.
- Click Add Pool on the Node Pool tab.
- Fill in the same settings as in Step 3 of the wizard — name, count, resources, datastore, placement, and optionally CPU mode and labels/taints.
- Confirm. The new nodes are provisioned and joined, and the pool appears as a new row.
The same rules apply as at creation: the name must follow the naming rules, it must not be already in use, and on a static-address cluster there must be enough free addresses for the new nodes. Cockpit checks all of this before creating anything.
Remove a pool
- Click Remove on the pool's row and confirm — removal destroys the pool's nodes and is not reversible.
- Each node is handled the way scale-down handles it: Longhorn replicas are moved off first, workloads are drained, and only then is the VM destroyed. When the last node is gone the pool disappears from the table.
The last worker pool stays
A cluster always keeps at least one worker pool. The Remove action is unavailable on the only remaining pool, and the API refuses the request. If you want the cluster to have no workers, scale that pool down; if you want the cluster gone, delete the cluster.
Upgrade a cluster
Cockpit performs a rolling upgrade, moving the cluster to a newer Kubernetes version one node at a time so your applications stay available.
- Open the cluster and choose Upgrade.
- Pick the target version from the list.
- Confirm. Cockpit upgrades the control plane first, then the workers, one node at a time.
During the upgrade each node is drained, updated, and returned to service before the next node begins. The cluster shows the version it is moving to alongside its current one until the upgrade completes.
Progress appears in the cluster's Tasks tab. Beneath the task, a Node Upgrade Jobs list shows one entry per node as the in-cluster upgrade controller works through them; click View log on any node to read exactly what happened on it. That log is the place to look if a single node stalls — the task can say a node is done, but only the log can say what it did.
Monitor cluster health
After a cluster goes active, Cockpit keeps an eye on it and shows a health status on the cluster page:
- Healthy — All nodes are present and Ready.
- Degraded — One or more nodes are not Ready (for example, a node was stopped or lost network). The cluster is still running but has reduced capacity or resilience.
Health updates on its own as nodes recover or fail, so you can tell at a glance whether attention is needed.
Troubleshooting
The cluster is stuck in "provisioning" and never becomes active. The most common cause is the network. Confirm the network you chose spans the hosts in your compute cluster and that its gateway gives the nodes real internet access — not just forwarding. Nodes that boot and answer ping but never finish installing almost always have no working route out. See Choosing a network.
The wizard refuses my pool name. Names must be lowercase letters, digits and -, and the names worker, master and control-plane are reserved. See Naming rules.
Adding a pool or scaling up is refused with "static IP pool is exhausted". The cluster's static address range has no free addresses left for the new nodes. The message states how many are free and how many were needed. Scale down something else first, or create a new cluster with a larger range — the range cannot be widened on an existing cluster.
The wizard will not let me continue past the CPU topology. Sockets × dies × cores × threads must equal the pool's vCPU count. Adjust either the topology or the vCPU count until the arithmetic shown in the wizard matches.
A label or taint was refused. Taints must be key=value:Effect with the effect exactly NoSchedule, PreferNoSchedule or NoExecute. Label keys and values follow Kubernetes rules (at most 63 characters, letters, digits, -, _ and .), and keys under kubernetes.io/ or k8s.io/ are reserved. The wizard tells you which entry is wrong.
Remove is greyed out on a worker pool. It is the cluster's only worker pool, and a cluster always keeps at least one. Add another pool first if you want to replace it, scale it down if you want fewer nodes, or delete the cluster.
Longhorn volumes show as "degraded". There are fewer worker nodes than the replica count, so Longhorn cannot place every copy on a separate node. Scale a worker pool up until the worker count is at least the replica count, and the volumes recover on their own.
The NFS tier reports the server as unreachable. The check is made from the cluster's network, not from Cockpit, because that is where the mounts happen. Confirm the NFS server actually listens on an address the nodes can reach and that its export allows the nodes' subnet — a server that is reachable from your workstation but bound only to a management interface will fail this check.
A node shows as "NotReady" or the cluster is "Degraded". Check that the node's VM is running (it may have been stopped, or its host may be down). Once the VM is back and reconnected to the network, the node rejoins and the health status returns to Healthy on its own.
kubectl cannot connect after downloading the kubeconfig. Make sure KUBECONFIG points to the downloaded file and that your machine can reach the control-plane node's address on the network. Re-download the kubeconfig if the cluster's address has changed.
Applications lost their data after a pod moved to another node. This happens with the Local Path storage tier, which keeps data on a single node. For data that must follow the application, use the Shared (NFS) or Replicated (Longhorn) tier instead. See Storage for your applications.
Related topics
- Distributed Resource Scheduler (DRS) & High Availability — how Cockpit places and balances node VMs across hosts.
- Virtual Networking — the distributed networks your cluster nodes connect to.
- Storage & Datastores — shared datastores that let clusters run across hosts.