How to Set Up a Kubernetes Cluster on VPS (K3s Lightweight Guide)
Kubernetes is the industry standard for container orchestration — but its full installation is notoriously complex and resource-hungry. K3s changes that equation completely. Developed by Rancher, K3s is a certified, production-ready Kubernetes distribution that installs in under 2 minutes, uses less than 512 MB of RAM, and runs comfortably on a single VPS.
This guide sets up a K3s cluster on Ubuntu VPS, deploys your first application, configures Traefik as an Ingress controller with SSL, and gives you a fully functional Kubernetes environment for development and small-scale production.
K3s vs Full Kubernetes
| K3s | kubeadm (full K8s) | |
|---|---|---|
| Install time | ~2 minutes | 30–60 minutes |
| Binary size | ~100 MB | Multiple GB |
| RAM usage (idle) | ~300–500 MB | 1–2 GB+ |
| etcd | SQLite (default) or etcd | etcd required |
| Kubernetes certified | ✅ Yes | ✅ Yes |
| ARM support | ✅ Yes | Partial |
| Best for | VPS, edge, IoT, dev | Large production clusters |
K3s is 100% Kubernetes API compatible — every kubectl command, every Helm chart, and every YAML manifest works exactly as it would on a full cluster.
💡 VPS.DO Recommendation: K3s works on 2 GB RAM, but 4 GB gives comfortable headroom for running multiple workloads. VPS.DO’s USA VPS 500SSD (2 vCPU / 4 GB RAM) is a solid single-node K3s host. View Plans →
Step 1: Prepare Your VPS
sudo apt update && sudo apt upgrade -y
# Disable swap (Kubernetes requires this)
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab
# Verify swap is off
free -h # Swap should show 0
Step 2: Install K3s (Single-Node)
# Official one-line installer
curl -sfL https://get.k3s.io | sh -
That’s it. K3s installs, starts, and enables itself as a systemd service automatically.
# Verify K3s is running
sudo systemctl status k3s
# Check node status
sudo kubectl get nodes
You should see your node listed as Ready. ✅
Step 3: Configure kubectl Access
# Copy the kubeconfig to your user's home directory
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $USER:$USER ~/.kube/config
# Set KUBECONFIG environment variable
echo 'export KUBECONFIG=~/.kube/config' >> ~/.bashrc
source ~/.bashrc
# Now use kubectl without sudo
kubectl get nodes
kubectl get pods --all-namespaces
Access from your local machine
# On your VPS, get the kubeconfig
cat ~/.kube/config
# On your local machine, save the config and replace the server IP
mkdir -p ~/.kube
# Copy the content above to ~/.kube/config-vps
# Edit the server line: server: https://YOUR_VPS_IP:6443
export KUBECONFIG=~/.kube/config-vps
kubectl get nodes
Step 4: Deploy Your First Application
nano nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-demo
labels:
app: nginx-demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx-demo
template:
metadata:
labels:
app: nginx-demo
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
name: nginx-demo-service
spec:
selector:
app: nginx-demo
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
kubectl apply -f nginx-deployment.yaml
# Watch pods start
kubectl get pods -w
# Check deployment status
kubectl get deployments
kubectl get services
Step 5: Configure Ingress with SSL (Traefik)
K3s ships with Traefik as the built-in Ingress controller. Configure it to route external traffic to your services with automatic Let’s Encrypt SSL.
Configure Traefik for Let’s Encrypt
sudo nano /var/lib/rancher/k3s/server/manifests/traefik-config.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: traefik
namespace: kube-system
spec:
valuesContent: |-
globalArguments:
- "--global.sendanonymoususage=false"
additionalArguments:
- "--certificatesresolvers.letsencrypt.acme.email=your@email.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/data/acme.json"
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
ports:
web:
redirectTo:
port: websecure
websecure:
tls:
certResolver: letsencrypt
# Restart K3s to apply Traefik config
sudo systemctl restart k3s
sleep 30
kubectl get pods -n kube-system | grep traefik
Create an Ingress resource
nano nginx-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls.certresolver: letsencrypt
spec:
rules:
- host: app.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-demo-service
port:
number: 80
tls:
- hosts:
- app.yourdomain.com
kubectl apply -f nginx-ingress.yaml
# Check ingress
kubectl get ingress
Point your domain’s DNS A record to your VPS IP and wait for propagation. Your app will be accessible at https://app.yourdomain.com with automatic SSL. ✅
Step 6: Persistent Storage with Local Path Provisioner
K3s includes the Local Path Provisioner for PersistentVolumes backed by the VPS filesystem:
nano postgres-with-pv.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16
env:
- name: POSTGRES_PASSWORD
value: "SecurePass123!"
- name: POSTGRES_DB
value: "myapp"
ports:
- containerPort: 5432
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-pvc
kubectl apply -f postgres-with-pv.yaml
kubectl get pods,pvc
Step 7: Install Helm (Kubernetes Package Manager)
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
helm version
Deploy applications with Helm
# Add popular repositories
helm repo add stable https://charts.helm.sh/stable
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
# Install WordPress with Helm
helm install my-wordpress bitnami/wordpress \
--set wordpressUsername=admin \
--set wordpressPassword=SecurePass123! \
--set ingress.enabled=true \
--set ingress.hostname=wp.yourdomain.com
Step 8: Multi-Node Cluster (Agent Nodes)
Add worker nodes to your cluster from additional VPS instances:
# On the server (master) VPS, get the node token
sudo cat /var/lib/rancher/k3s/server/node-token
# On each agent (worker) VPS:
curl -sfL https://get.k3s.io | K3S_URL=https://MASTER_VPS_IP:6443 \
K3S_TOKEN=YOUR_NODE_TOKEN sh -
# Verify on master
kubectl get nodes
# Should now show multiple nodes
Essential kubectl Commands
| Command | Action |
|---|---|
kubectl get pods -A |
List all pods across namespaces |
kubectl describe pod POD_NAME |
Detailed pod info and events |
kubectl logs POD_NAME -f |
Stream pod logs |
kubectl exec -it POD_NAME -- bash |
Shell into a running pod |
kubectl apply -f file.yaml |
Apply manifest |
kubectl delete -f file.yaml |
Delete resources from manifest |
kubectl scale deploy NAME --replicas=3 |
Scale a deployment |
kubectl rollout restart deploy NAME |
Rolling restart |
Final Thoughts
K3s makes Kubernetes accessible on a VPS without the complexity and resource overhead of a full cluster. For developers learning Kubernetes, teams running internal tools, or small-scale production workloads, K3s on a VPS.DO KVM VPS delivers a complete Kubernetes environment at minimal cost.
- 🇺🇸 USA VPS — from $20/month (4 GB RAM recommended for K3s)
- 🖥️ USA Dedicated Server — for multi-node production clusters
Related articles: