K3s, Lightweight Kubernetes
Install K3s on a VPS for a production-ready Kubernetes cluster, single-node setup, kubectl, Helm and basic deployments
K3s is Kubernetes reduced to ~70MB, ideal for VPS deployments. It is production-ready, uses containerd, and includes Traefik ingress controller built-in. Perfect for running containerized workloads without the overhead of full Kubernetes.
Requirements
- CPU: 2 vCPU minimum (4 recommended)
- RAM: 2GB minimum (4GB recommended)
- OS: Linux x64 (Ubuntu, CentOS, Alpine, etc.)
- Network: Port 6443 (API) and 10250 (kubelet) accessible between nodes
Single-Node Installation
Install K3s server (acts as both control plane and worker):
curl -sfL https://get.k3s.io | sh -Check status:
systemctl status k3s
kubectl get nodesConfigure kubectl
Export kubeconfig for local access:
export KUBECONFIG=/etc/rancher/k3s/k3s.yamlOr copy to standard location:
mkdir -p ~/.kube
cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
chmod 600 ~/.kube/configVerify:
kubectl get nodes
kubectl get pods --all-namespacesDeploy Your First Application
Example: Nginx Deployment
Create deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80Deploy:
kubectl apply -f deployment.yamlCheck deployment status:
kubectl get deployments
kubectl get pods
kubectl logs deployment/nginxServices
Expose your deployment as a service:
kubectl expose deployment nginx --port=80 --target-port=80 --type=ClusterIP --name=nginx-svcOr define in YAML:
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
ports:
- port: 80
targetPort: 80
selector:
app: nginxList services:
kubectl get svcIngress with Traefik
K3s includes Traefik ingress controller by default. Create an IngressRoute:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: nginx-ingress
spec:
entryPoints:
- web
routes:
- match: Host(`example.com`)
kind: Rule
services:
- name: nginx-svc
port: 80Apply:
kubectl apply -f ingressroute.yamlFor HTTPS with Let's Encrypt:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: nginx-https
spec:
entryPoints:
- websecure
routes:
- match: Host(`example.com`)
kind: Rule
services:
- name: nginx-svc
port: 80
tls:
certResolver: letsencryptHelm Package Manager
Install Helm:
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
helm versionAdd Helm repositories:
helm repo add stable https://charts.helm.sh/stable
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo updateSearch for charts:
helm search repo nginxInstall a chart:
helm install my-nginx stable/nginx-ingressList releases:
helm listUninstall:
helm uninstall my-nginxCommon kubectl Commands
List resources:
kubectl get pods
kubectl get nodes
kubectl get services
kubectl get deployments
kubectl get allView logs:
kubectl logs deployment/nginx
kubectl logs -f pod-name # follow
kubectl logs pod-name -c container # specific containerExecute commands in pod:
kubectl exec -it pod-name -- /bin/shDescribe resource:
kubectl describe pod pod-name
kubectl describe node node-nameDelete resource:
kubectl delete pod pod-name
kubectl delete deployment nginxApply configuration:
kubectl apply -f file.yamlWatch resources:
kubectl get pods --watchUpdating K3s
Re-run the installation script to upgrade to the latest version:
curl -sfL https://get.k3s.io | sh -Or pin a specific version:
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.27.0 sh -Check version:
kubectl versionMulti-Node Cluster
On Server Node
Get the token:
cat /var/lib/rancher/k3s/server/node-tokenOn Worker Node
Join the cluster:
curl -sfL https://get.k3s.io | K3S_URL=https://server-ip:6443 K3S_TOKEN=token sh -Replace server-ip with the server's IP and token with the token from above.
Verify:
kubectl get nodesDisabling Traefik (to Save Resources)
If you don't need Traefik:
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--disable traefik" sh -Or for existing installation, edit /etc/systemd/system/k3s.service and add --disable traefik to the ExecStart line, then:
systemctl daemon-reload
systemctl restart k3sCommon Issues
High Memory Usage
K3s is lightweight but can use significant memory with many pods. Monitor:
kubectl top nodes
kubectl top podsCertificate Errors
K3s generates self-signed certificates. For multi-node clusters, ensure NTP is synchronized:
timedatectl status
timedatectl set-ntp trueFor multi-node K3s clusters on separate VPS, ensure ports 6443 (API server) and 10250 (kubelet) are open between nodes. Use firewall rules or security groups in your control panel.
On VPS with 1GB RAM, K3s runs but with tight margins. Disable Traefik if not needed: --disable traefik. Monitor resource usage closely with kubectl top nodes.