K3s on Proxmox: Kubernetes Cluster Setup Guide
Run a lightweight Kubernetes cluster on Proxmox VMs. This guide walks through VM prep, K3s installation, kubectl access, and your first deployment.
This post contains affiliate links. If you buy through them, I earn a small commission at no extra cost to you.
Running K3s on Proxmox VMs gives you a real Kubernetes cluster without buying separate hardware. The Proxmox hypervisor handles the VMs; K3s handles the orchestration. The combination is standard for homelab Kubernetes setups.
This guide builds a three-node K3s cluster: one control plane VM and two worker nodes, all on Proxmox.
What You’ll Need
- A Proxmox host with at least 8GB RAM and 4 CPU cores free (more is better)
- Three VMs (or two at minimum — you can start with a single-node cluster)
- Ubuntu 22.04 or Debian 12 as the VM OS
- A static IP for each VM, or DHCP reservations
VM Configuration
For each node, create a VM in Proxmox with:
- CPU: 2 cores minimum (4 for the control plane)
- RAM: 2GB minimum (4GB recommended for control plane)
- Disk: 20GB (thin provisioned is fine)
- Network: Bridge to your LAN or homelab VLAN
Clone the same base VM template for all three nodes to save time. After cloning, update each VM’s hostname and static IP before proceeding.
On each VM:
# Set hostname (replace with your chosen names)
sudo hostnamectl set-hostname k3s-server
# Disable swap (required for Kubernetes)
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab
# Update packages
sudo apt update && sudo apt upgrade -y
# Install required packages
sudo apt install -y curl wget apt-transport-https
Install K3s on the Control Plane
SSH into your control plane VM and run:
curl -sfL https://get.k3s.io | sh -
Wait for it to complete (takes 1-2 minutes). Then verify it’s running:
sudo k3s kubectl get nodes
You should see your control plane node in Ready state.
Get the join token — you’ll need this for worker nodes:
sudo cat /var/lib/rancher/k3s/server/node-token
Also note the control plane’s IP address:
hostname -I | awk '{print $1}'
Install K3s on Worker Nodes
On each worker node, run (replace the values):
curl -sfL https://get.k3s.io | K3S_URL=https://CONTROL_PLANE_IP:6443 K3S_TOKEN=YOUR_NODE_TOKEN sh -
After installation, go back to the control plane and verify all nodes joined:
sudo k3s kubectl get nodes
All three nodes should show Ready.
Set Up kubectl on Your Local Machine
Instead of SSHing into the control plane every time, copy the kubeconfig to your local machine.
On the control plane:
sudo cat /etc/rancher/k3s/k3s.yaml
Copy that output. On your local machine:
mkdir -p ~/.kube
# Paste the content into ~/.kube/config
nano ~/.kube/config
Replace the server address 127.0.0.1 with your control plane’s actual IP:
server: https://YOUR_CONTROL_PLANE_IP:6443
Test it:
kubectl get nodes
Install Helm
Helm is the package manager for Kubernetes. Most homelab apps have Helm charts.
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
helm version
Deploy Your First App
Test the cluster with a simple nginx deployment:
kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get svc nginx
The NodePort shown (something in the 30000-32767 range) is accessible at http://any-node-ip:NODEPORT.
Persistent Storage
K3s includes a built-in local-path provisioner for persistent volumes. It stores data on the node where the pod runs.
For a homelab, this is fine for most uses. If you need storage accessible from any node (for pod rescheduling), add a NFS provisioner:
helm repo add nfs-subdir-external-provisioner \
https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
helm install nfs-subdir-external-provisioner \
nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
--set nfs.server=YOUR_NAS_IP \
--set nfs.path=/your/nfs/share
Managing the Cluster
Useful day-to-day commands:
# List all pods across all namespaces
kubectl get pods -A
# Show resource usage per node
kubectl top nodes
# Describe a pod (useful for debugging)
kubectl describe pod POD_NAME
# View logs
kubectl logs POD_NAME
# Delete a deployment
kubectl delete deployment DEPLOYMENT_NAME
Snapshots for Safety
Before experimenting with your cluster, take Proxmox snapshots of all three VMs. A snapshot takes seconds and gives you a clean rollback point if you break something. Kubernetes experimentation goes better when you can restore to a known good state in 30 seconds.
A USB drive or external SSD for Proxmox backup storage is worth having — Proxmox can back up VMs to an external drive automatically on a schedule.
What’s Next
With a working cluster:
- Install Traefik or Nginx Ingress Controller for HTTP routing
- Set up cert-manager for automatic TLS certificates
- Try ArgoCD or Flux for GitOps deployments
- Deploy a real app — Vaultwarden, Nextcloud, or Jellyfin all have Helm charts
K3s on Proxmox is a solid foundation. The VMs can be snapshotted, resized, or migrated — giving you flexibility that bare-metal Kubernetes can’t match.