Docker & DevOps

Kubernetes basics: run k3s on a single VPS

Learn core Kubernetes concepts (pods, deployments, services, ingress) by installing lightweight k3s on one VPS and deploying a web app with kubectl.

AdvancedLinux VPS3 min read

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

ObjectWhat it is
PodOne or more containers that run together; the smallest unit
DeploymentKeeps a set number of identical pods running and handles rolling updates
ServiceA stable internal address and load balancer in front of pods
IngressHTTP(S) routing from domains to services
NamespaceA folder-like grouping to separate apps
ConfigMap / SecretConfiguration and sensitive values injected into pods
PersistentVolumeClaimStorage 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 nodes

It 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.yaml

Point 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/web to 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 pod shows 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.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.