Kubernetes is the de facto standard for container orchestration, but a full kubeadm install with etcd, kubelet, and multiple control-plane components is heavy for a single VPS. K3s packages the control plane, the kubelet, and the container runtime into one binary under 100 MB and runs comfortably in 512 MB of RAM. For a small deployment — a side project, a CI runner, or a low-traffic application — K3s gives you a real Kubernetes cluster without the resource tax.
Before you start, make sure the VPS you are installing on has enough CPU and memory for both the control plane and your workloads. If you are unsure what to provision, compare VPS plans side by side in our comparison table and pick an instance with at least 1 GB of RAM and 2 vCPUs. K3s will run on less, but your applications need headroom too.
Prerequisites
- A VPS running Ubuntu 22.04/24.04 or Debian 12, with at least 1 GB of RAM
- A domain name and a DNS A record pointing to the server (needed for ingress and TLS)
kubectlinstalled on your local machine
Step 1: Install K3s
The installer registers a systemd service and starts the cluster immediately:
curl -sfL https://get.k3s.io | sh -
Check that the node reports Ready:
sudo k3s kubectl get nodes
Step 2: Configure kubectl on Your Local Machine
The kubeconfig file lives at /etc/rancher/k3s/k3s.yaml on the server. Copy it locally and replace the server: address with your server’s public IP or domain so your workstation can reach the API. The file contains a CA certificate and an admin token, so keep permissions tight:
sudo cat /etc/rancher/k3s/k3s.yaml
# change: server: https://127.0.0.1:6443
# to: server: https://YOUR_SERVER_IP:6443
chmod 600 k3s.yaml
kubectl --kubeconfig k3s.yaml get nodes
If the API port is not reachable, allow 6443 through the firewall: sudo ufw allow 6443/tcp. For anything beyond a lab, restrict that rule to your own IP address instead of leaving it open to the internet.
Step 3: Deploy a Sample Application
Create a Deployment and a Service. Save this manifest as app.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo
spec:
replicas: 2
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
spec:
containers:
- name: demo
image: nginx:alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: demo
spec:
selector:
app: demo
ports:
- port: 80
targetPort: 80
Apply it and wait for the pods to start:
kubectl apply -f app.yaml
kubectl rollout status deployment/demo
Step 4: Expose It with an Ingress
K3s ships with Traefik as the default ingress controller, so no extra install is needed. Create an Ingress resource that routes your domain to the service:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo
spec:
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: demo
port:
number: 80
Point the DNS A record at the VPS IP, and within a minute Traefik starts serving the app. K3s bundles cert-manager, so adding an annotation to the Ingress requests a Let’s Encrypt certificate automatically.
Step 5: Monitor the Cluster
K3s includes metrics-server out of the box, so kubectl top works immediately. It shows real CPU and memory usage per node and per pod, which is the fastest way to spot a container that is silently eating the whole VPS:
kubectl top nodes
kubectl top pods -A
For a quick health sweep, kubectl get events --sort-by=.lastTimestamp lists recent scheduler and runtime events, and kubectl describe pod <name> shows why a pod is stuck in CrashLoopBackOff or Pending.
Step 6: Persist Data with a Volume
Pods are ephemeral: when a pod is deleted, everything written to its container filesystem disappears with it. For stateful workloads such as a database, mount a hostPath volume or a Longhorn volume so the data survives pod restarts:
volumes:
- name: data
hostPath:
path: /var/lib/demo-data
containers:
- name: demo
image: nginx:alpine
volumeMounts:
- name: data
mountPath: /data
On a single node a hostPath is fine; if you later join more nodes, move to Longhorn (bundled with K3s) so volumes can follow pods across the cluster.
Step 7: Back Up etcd
K3s snapshots its embedded datastore to /var/lib/rancher/k3s/server/db/snapshots on a schedule you configure with the --etcd-snapshot-schedule-cron server flag. Always take a manual snapshot before upgrading the cluster:
sudo k3s etcd-snapshot save
sudo k3s server --cluster-reset # disaster recovery path
Scaling Later
When one node is not enough, join additional servers or agents using the token in /var/lib/rancher/k3s/server/node-token. The single-node setup you start with upgrades cleanly to a multi-node cluster, so there is no migration penalty for beginning small.
Conclusion
K3s turns a modest VPS into a production-grade Kubernetes cluster with a single command and a fraction of the memory footprint of a full distribution. Start small, back up etcd before every change, and scale out only when your workloads justify the extra nodes. If you are choosing hardware for the cluster, see the full specs and pricing in our comparison table to match the right VPS to your node count.



Leave a Reply
You must be logged in to post a comment.