Kubernetes runs containers across machines, restarts them when they fail and rolls out updates without downtime. Full clusters are complex, but k3s, a certified lightweight distribution, runs on a single VPS and is a practical way to learn Kubernetes basics or host a few container apps.
Before you start
- A Linux VPS with at least 2 vCPU and 2 GB RAM (4 GB is more comfortable) and root access.
- A KVM VPS; container-based VPS types often cannot run Kubernetes.
- Familiarity with Docker images helps.
- Ports 80 and 443 free (stop any existing Nginx/Apache).
Key Kubernetes concepts
| Object | What it is |
|---|---|
| Pod | One or more containers that run together; the smallest unit |
| Deployment | Keeps a set number of identical pods running and handles rolling updates |
| Service | A stable internal address and load balancer in front of pods |
| Ingress | HTTP(S) routing from domains to services |
| Namespace | A folder-like grouping to separate apps |
| ConfigMap / Secret | Configuration and sensitive values injected into pods |
| PersistentVolumeClaim | Storage that survives pod restarts |
Install k3s
curl -sfL https://get.k3s.io | sh -This installs k3s as a systemd service with containerd, the Traefik ingress controller and a local-path storage provisioner. Check the node:
kubectl get nodesIt should show one node in Ready state within a minute. The kubeconfig lives in /etc/rancher/k3s/k3s.yaml; copy it to ~/.kube/config on your computer (replacing 127.0.0.1 with the server IP) to manage the cluster remotely, and restrict port 6443 to your IP.
Deploy an app
Create app.yaml with a Deployment, Service and Ingress:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 2
selector:
matchLabels: { app: web }
template:
metadata:
labels: { app: web }
spec:
containers:
- name: web
image: nginx:1.27-alpine
ports:
- containerPort: 80
resources:
limits: { memory: "128Mi", cpu: "250m" }
---
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector: { app: web }
ports:
- port: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
spec:
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service: { name: web, port: { number: 80 } }Apply it:
kubectl apply -f app.yamlPoint app.example.com at the VPS IP and open it in a browser; Traefik routes the request to one of the two pods.
Everyday kubectl commands
kubectl get pods -A: all pods in all namespaces.kubectl describe pod <name>: events, useful when a pod will not start.kubectl logs -f deploy/web: follow logs.kubectl exec -it deploy/web -- sh: shell inside a container.kubectl set image deploy/web web=nginx:1.27.3-alpine: rolling update;kubectl rollout undo deploy/webto roll back.kubectl scale deploy/web --replicas=3: scale.
Add HTTPS
Install cert-manager and create a Let's Encrypt ClusterIssuer, then add a tls section and the annotation cert-manager.io/cluster-issuer to the Ingress. cert-manager then requests and renews certificates automatically. Follow the version-specific install command from the cert-manager documentation.
Troubleshooting
- Pod stuck in Pending: not enough CPU/RAM or no storage.
kubectl describe podshows the reason. - ImagePullBackOff: wrong image name or a private registry without credentials (create an
imagePullSecret). - CrashLoopBackOff: the app exits on start. Read
kubectl logs --previous. - 404 from Traefik: the Ingress host does not match the domain you request, or the Service selector does not match pod labels.
Kubernetes FAQ
Do I need Kubernetes for one website?
Usually not. Docker Compose is simpler for a few containers on one server. Kubernetes pays off with many services, several nodes or a team that already uses it.
k3s vs full Kubernetes?
k3s is a fully conformant Kubernetes packaged as a single small binary with sensible defaults; it suits single servers, edge and labs.
Can I add more servers later?
Yes. Join extra nodes with the token in /var/lib/rancher/k3s/server/node-token and the k3s agent install command.
