Kubernetes on VPS: Install K3s in 15 Minutes
Kubernetes is a powerful container orchestration platform, but full installation requires significant resources. K3s is a lightweight Kubernetes distribution developed by Rancher that uses only ~500MB of RAM and runs on a single VPS. It supports real workloads with full kubectl commands and can be upgraded to full-scale Kubernetes in the future.
System Requirements
- VPS running Ubuntu 22.04 or Debian 12
- At least 1GB of RAM (2GB+ recommended)
- 1 CPU core or higher
- 10GB+ disk space for container images
- Port 6443 (API server) and 80/443 (ingress) open
Installing K3s
# Install K3s as single-node (master + worker on same machine)
curl -sfL https://get.k3s.io | sh -
# Check status
systemctl status k3s
# View nodes
kubectl get nodes
# Expected output
NAME STATUS ROLES AGE VERSION
vps-01 Ready control-plane,master 1m v1.29.x+k3s1
/etc/rancher/k3s/k3s.yaml — copy it to ~/.kube/config if you want to run kubectl as a regular user: mkdir -p ~/.kube && cp /etc/rancher/k3s/k3s.yaml ~/.kube/config && chown $(id -u):$(id -g) ~/.kube/config
Kubernetes Core Concepts
- Pod: The smallest unit, a single container or multiple containers running together
- Deployment: Manages pods to run the desired number, auto-restarts on crash
- Service: Exposes pod ports for access, acts as an internal load balancer
- Ingress: Routes HTTP/HTTPS from the internet to services based on domain/path
- Namespace: Separates environments (dev/staging/prod) within a cluster
Deploy Your First App: Nginx
# Create a deployment
kubectl create deployment nginx --image=nginx:alpine --replicas=2
# Expose with a service
kubectl expose deployment nginx --port=80 --type=ClusterIP
# View status
kubectl get pods
kubectl get deployments
kubectl get services
# Or use a YAML manifest (recommended for production)
nano nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80
kubectl apply -f nginx-deployment.yaml
Configuring Ingress Controller (Traefik)
K3s comes with the Traefik ingress controller built-in. Create an Ingress resource to route your domain:
nano nginx-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-svc
port:
number: 80
kubectl apply -f nginx-ingress.yaml
# Test (DNS must point to VPS IP first)
curl -H "Host: myapp.example.com" http://YOUR_VPS_IP
Automatic SSL with cert-manager
# Install cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
# Wait until ready
kubectl wait --for=condition=ready pod -l app=cert-manager -n cert-manager --timeout=120s
# Create a ClusterIssuer for Let's Encrypt
cat <
Common kubectl Commands
# View all resources
kubectl get all
# View pod logs
kubectl logs POD_NAME -f
# Execute into a container
kubectl exec -it POD_NAME -- sh
# Scale replicas
kubectl scale deployment nginx --replicas=3
# Delete resources
kubectl delete deployment nginx
kubectl delete -f nginx-deployment.yaml
# View details
kubectl describe pod POD_NAME
kubectl describe node vps-01
Monitor Resource Usage
# Check metrics-server (already included in K3s)
kubectl top nodes
kubectl top pods
K3s makes Kubernetes accessible for standard VPS deployments — ideal for small to medium microservices or teams learning Kubernetes before scaling to full production clusters in the future.
Verify K3s is Working Correctly
# Check node status
kubectl get nodes
# Should show: STATUS = Ready
# Check all pods in the namespace
kubectl get pods --all-namespaces
# Check services are running
kubectl get services
# Test cluster DNS
kubectl run test-dns --image=busybox --rm -it --restart=Never -- nslookup kubernetes
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml or copy it to ~/.kube/config to use without sudo as a regular user
Common Issues & Troubleshooting
Error: "the server doesn't have a resource type" after installing K3s
K3s is not ready yet, or kubectl is not connected to the correct cluster:
# Check if K3s is running
systemctl status k3s
# Set kubeconfig
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
kubectl cluster-info
# View K3s logs if service won't start
journalctl -u k3s -n 50
Error: Pod stuck at "Pending" and not becoming Running
Usually caused by insufficient resources or node not Ready:
# View problem details
kubectl describe pod POD_NAME
# Check the Events section at the bottom
# Check node resources
kubectl describe node
# View Capacity vs Allocatable
# Verify node is Ready
kubectl get nodes -o wide
Error: Pod stuck in "CrashLoopBackOff"
Container crashed and keeps restarting. Check the logs to see what's wrong:
# View pod logs
kubectl logs POD_NAME
kubectl logs POD_NAME --previous # logs from previous run
# Check container exit code
kubectl describe pod POD_NAME | grep -A3 "Last State"
Error: Ingress configured but not routing traffic
Verify the Traefik ingress controller is running and DNS points correctly:
# Check ingress resource
kubectl get ingress
# Check Traefik pod
kubectl get pods -n kube-system | grep traefik
# Test manually (DNS may not have propagated)
curl -H "Host: myapp.example.com" http://YOUR_VPS_IP
Error: K3s using too much RAM
K3s runs etcd, API server, and controller manager all on one machine. On 1GB VPS this may be tight:
# View K3s component resource usage
kubectl top pods -n kube-system
# On low RAM, reduce system pod resources
# Or use containerd instead of Docker: K3s uses containerd by default
# Check node resources
kubectl describe node | grep -A5 "Allocated resources"
Frequently Asked Questions
How is K3s different from full Kubernetes?
K3s is a slimmed-down Kubernetes distribution by Rancher for resource-constrained environments. It removes unnecessary cloud provider plugins, uses SQLite instead of etcd (or embedded etcd), and packages components into a single binary. kubectl commands work the same way, and you can upgrade to full-scale K8s clusters in the future.
Is a single VPS suitable for K3s?
Yes, for development, staging, small microservices, or non-critical workloads. 2GB+ RAM is recommended for production with multiple apps. The limitation is no failover — if the VPS goes down, all pods stop. For critical production, use a multi-node cluster.
How do I backup K3s cluster state?
K3s stores cluster state in SQLite at /var/lib/rancher/k3s/server/db/. Backup with cp -r /var/lib/rancher/k3s/server/db/ /backup/k3s-db-$(date +%Y%m%d) and backup all YAML manifests you used for deployments, since manifests are the source of truth for restores.