Agree deployment and operations: WZ-IT designs, implements and operates Kubernetes on Proxmox. Planning connects the hypervisor, Kubernetes, networking and storage.
This guide creates a new k3s cluster in Proxmox KVM VMs: three servers with embedded etcd, optional workers and a fixed API endpoint. It covers deployment, while the architecture overview compares operational models. For platform selection, see Proxmox vs Kubernetes.
As of October 2026. Commands and addresses are a scaffold to adapt for new VMs. Do not install k3s on the Proxmox host. Existing clusters are not reinitialised.
Contents
- 1. Topology and prerequisites
- 2. Cloud-Init template and VMs
- 3. Networking and API endpoint
- 4. Initialise k3s and join servers
- 5. Workers and cluster access
- 6. Storage, backup and acceptance
- Sources
1. Topology and prerequisites
For embedded-etcd HA, k3s needs at least three servers; workers are called agents and are optional. Servers can also run workloads. Check resources and disks against the k3s requirements. Vendor minimums are not sizing for your applications. Use sufficiently fast storage for etcd and plan spare capacity for maintenance and failures.
| Role | Example address | Placement for host failure protection |
|---|---|---|
| API endpoint | 10.20.0.10, api.k8s.example.test | Redundant TCP load balancer in front of the servers |
| cp1 | 10.20.0.11 | Proxmox host A |
| cp2 | 10.20.0.12 | Proxmox host B |
| cp3 | 10.20.0.13 | Proxmox host C |
| Workers as needed | From your node network | Distribute according to capacity and application |
All addresses and names are examples. Three VMs on one host form a lab with a shared failure point. A redundant API IP does not replace independent hosts, power, network or storage paths. RKE2 is a different installation path; the distribution comparison and Talos guide cover alternatives.
2. Cloud-Init template and VMs
Follow the documented Proxmox Cloud-Init workflow: obtain a cloud image from the chosen Linux vendor and verify its checksum, create a new VM, import the image disk and attach it as the boot disk. Add a Cloud-Init drive and controller and console settings appropriate for the image. Check the image, guest OS and k3s version together against the requirements.
Before each clone's first boot, use Proxmox Cloud-Init to set an administrative user, its SSH key, a unique IP with gateway and DNS configuration. Convert the powered-off base into a template and create three full clones. Give each guest a unique VM ID, MAC address and hostname. The template contains no k3s state or cluster secrets yet.
Start the clones on the intended hosts. Inside each guest, verify completed Cloud-Init processing with cloud-init status --wait, IP configuration, DNS resolution, time synchronisation and SSH access. Record VM IDs and host placement. The official Cloud-Init source document also describes templates, cloning and IP/key assignment.
3. Networking and API endpoint
Node, pod and service networks must not overlap existing networks. This deployment uses k3s default pod and service CIDRs only if those ranges are free in your environment. Otherwise set identical cluster-cidr and service-cidr values on every server before creating the cluster. Check network requirements and firewall rules instead of disabling the firewall globally.
| Traffic | Access in this model |
|---|---|
| Nodes and administrative API access | TCP 6443 to API endpoint and servers |
| Embedded etcd | TCP 2379 and 2380 between servers |
| Flannel VXLAN | UDP 8472 between nodes, not publicly exposed |
| Kubelet and metrics | TCP 10250 between nodes |
Before bootstrap, configure the TCP load balancer with health checks against the three server addresses on port 6443. A single load balancer would introduce another failure point; redundant instances and IP failover are prerequisites for the HA goal. DNS points to the API IP. Verify routing and IP ownership before using that address.
This API IP is not a Kubernetes application load balancer. A Kubernetes Service of type LoadBalancer, ingress and application certificates are planned separately. Bundled components such as Traefik and ServiceLB initially retain their k3s defaults here; introduce alternative controllers only after a deliberate decision.
4. Initialise k3s and join servers
Work inside the new Linux VMs with administrative privileges. Create /etc/rancher/k3s/ accessible only to root. On cp1, create /etc/rancher/k3s/config.yaml and protect it with file mode 0600. Replace the token placeholder with a long random secret from your protected secret management system.
# Only cp1 during initial cluster creation
cluster-init: true
token: "REPLACE_WITH_PRIVATE_CLUSTER_SECRET"
tls-san:
- "10.20.0.10"
- "api.k8s.example.test"
write-kubeconfig-mode: "0600"
The configuration path and YAML options are documented. Choose a specific approved k3s version from the release notes and set K3S_VERSION to its full release tag. Use the same value on all new nodes. Then, on cp1:
# Set K3S_VERSION to a specific approved release tag first
: "${K3S_VERSION:?Set a specific k3s release tag}"
curl -fL https://get.k3s.io -o install-k3s.sh
# Review the script before execution
sudo env INSTALL_K3S_VERSION="${K3S_VERSION:?Set a specific k3s release tag}" sh install-k3s.sh server
sudo k3s kubectl get nodes -o wide
On cp2 and cp3, create an individual protected config.yaml. Use the shared token, the same TLS names and, where applicable, identical customised CIDRs. No cluster-init on these nodes:
server: "https://10.20.0.10:6443"
token: "REPLACE_WITH_PRIVATE_CLUSTER_SECRET"
tls-san:
- "10.20.0.10"
- "api.k8s.example.test"
write-kubeconfig-mode: "0600"
Once cp1 is reachable through the load balancer, run the same version-pinned installation block with role server sequentially on cp2 and cp3. Check node state after each join. This follows the documented HA bootstrap using a shared token, with fixed API access. Do not repeat initialisation as a repair procedure for an existing cluster.
5. Workers and cluster access
For each additional worker VM, create a root-protected config.yaml before installation with server: "https://10.20.0.10:6443" and the same private token. Download and review the installation script as above, set the same release tag and use role agent:
: "${K3S_VERSION:?Set a specific k3s release tag}"
sudo env INSTALL_K3S_VERSION="${K3S_VERSION:?Set a specific k3s release tag}" sh install-k3s.sh agent
On a server, check nodes and system pods:
sudo k3s kubectl get nodes -o wide
sudo k3s kubectl get pods -A -o wide
sudo k3s kubectl get --raw='/readyz?verbose'
The administrative kubeconfig is stored at /etc/rancher/k3s/k3s.yaml, as documented in k3s cluster access. On the designated admin machine, create ~/.kube with mode 0700 or check its protection if it already exists. Transfer the file securely as ~/.kube/proxmox-k3s.yaml with mode 0600, without overwriting an existing configuration. In this copy, replace the server value with https://api.k8s.example.test:6443 or your actual API endpoint. It contains administrative credentials; keep it out of Git and do not make it generally readable. Then, on the admin machine, verify access through the load balancer explicitly using this file:
kubectl --kubeconfig ~/.kube/proxmox-k3s.yaml get nodes
6. Storage, backup and acceptance
The bundled Local Path Provisioner supplies node-local storage, not automatic replication. Existing Proxmox Ceph does not become a Kubernetes StorageClass just by installing k3s. Choose an appropriate CSI/storage model before deploying persistent applications. Verify a test PVC, read/write access and behaviour during a planned node change against the volume properties.
For embedded etcd, request a manual snapshot on a server:
sudo k3s etcd-snapshot save --name acceptance
sudo k3s etcd-snapshot ls
The snapshot command alone does not prove recoverability. Back up the snapshot and actual server token from /var/lib/rancher/k3s/server/token separately from the cluster with restricted access; restore requires the token. Back up application data additionally. Plan isolated recovery testing using Kubernetes backup and restore.
| Acceptance area | Evidence before production |
|---|---|
| Control plane | Three server nodes ready; API state and host placement recorded |
| Networking | Node connectivity, DNS and pod traffic verified |
| Application | Your test application reachable through the intended access path |
| Persistence | Chosen StorageClass and data access verified after an appropriate recovery |
| Failure | Approved test of one host and the API load balancer; observe quorum and application |
| Recovery | etcd with its token and application data restored in isolation |
Run failure tests only under an agreed plan in the test environment. Healthy node status alone is not full acceptance. This scaffold provides neither automatic hardening nor complete production operations.
From installation to operations: Kubernetes on Proxmox combines agreed cluster deployment with network, storage and operational planning. The architecture overview covers HA and both layers' lifecycles.










