TL;DR #
- k3s is Kubernetes, packaged for simplicity: fewer moving parts, smaller footprint, fast install.
- Best for small teams, edge, homelabs, dev/test, and cost-sensitive production.
- A safe default looks like: 1 or 3 server nodes — never 2 + 2+ agent nodes, embedded etcd (or external), automated backups, and a boring ingress + cert setup.
- It ships with batteries included: Traefik, ServiceLB, local-path storage, CoreDNS, metrics-server. Know what they are before you replace them.
What is k3s? #
k3s (from Rancher/SUSE) is a CNCF-certified Kubernetes distribution designed to be:
- lightweight (small binaries, fewer dependencies)
- easy to install and upgrade
- sensible out of the box
It’s not “Kubernetes-lite” in the sense of missing APIs. It’s Kubernetes with opinionated packaging: components are bundled, defaults are chosen for you, and the install story is aggressively streamlined.
If “vanilla Kubernetes” feels like assembling IKEA furniture using only a PDF and optimism, k3s is the version that shows up with the screws already sorted.
What you get without asking for it #
This is the part people discover three weeks in, usually while debugging something. A default curl -sfL https://get.k3s.io | sh - install gives you, already running:
- SQLite as the datastore. Not etcd — a single file at
/var/lib/rancher/k3s/server/db/. Fine for one server, and the reason a single-node k3s is so light. You opt into embedded etcd with--cluster-init, and that choice is much easier to make on day 0 than on day 90. - Traefik as the ingress controller, installed as a bundled HelmChart.
- ServiceLB (formerly Klipper LB), which makes
type: LoadBalancerservices actually get an address on bare metal by binding the node’s host ports. This is why aLoadBalancerservice works on a Hetzner box with no cloud controller — and also why two services can fight over port 80. - local-path-provisioner as the default StorageClass. PVCs bind to a directory on whichever node the pod landed on. It works immediately and it does not follow your pod to another node. Plan real storage before you put a database on it.
- CoreDNS and metrics-server.
Each of these can be disabled at install time (--disable=traefik,servicelb, --disable-helm-controller), and Rancher’s own docs tell you how. The point is to disable them deliberately, not to find out they existed when something collides.
Who should use k3s (and who shouldn’t) #
Great fits #
- 3–10 person teams that want Kubernetes without building a platform org.
- Internal tools, staging environments, and small production workloads.
- Edge / retail / IoT setups where resources and connectivity are constrained.
- Homelabs that eventually become “a surprisingly real prod.”
Not a great fit #
- You already run managed Kubernetes (EKS/GKE/AKS) and your main problem is application architecture, not cluster ops.
- You need a strict enterprise feature matrix, complex multi-tenancy, or you plan to run a large fleet of clusters.
- Your team has zero appetite for patching hosts, rotating certs, and handling the occasional “why is DNS weird?” incident.
k3s vs k8s vs k3d vs microk8s (quick comparison) #
k3s vs “upstream” Kubernetes #
- Upstream: maximally flexible, but you assemble (almost) everything.
- k3s: chooses defaults so you can ship faster.
k3s bundles and/or simplifies parts of the control plane and common add-ons. That’s the point: fewer decisions, fewer services, fewer ways to have an accidentally broken cluster.
k3s vs k3d #
- k3s runs on real hosts/VMs.
- k3d runs k3s inside Docker (great for local dev).
Use k3d when you want a local cluster you can nuke and recreate in seconds. Use k3s when you want nodes with real networking and real persistence.
k3s vs microk8s #
Both target similar audiences. Differences come down to packaging and ecosystem preferences. If you’re already comfortable in the Rancher ecosystem (or want a very common “small cluster” path), k3s is often the default pick.
The mental model: what you still need to operate #
k3s removes friction, but it doesn’t remove responsibility. Even a “simple Kubernetes” still needs:
- node OS lifecycle (updates, reboots, disk pressure)
- networking (CNI, service routing, north-south traffic)
- storage (PVCs, backups, restores)
- certificates (TLS, internal PKI assumptions)
- observability (metrics/logs/alerts)
If you plan this upfront, k3s is very manageable.
A practical k3s architecture for small teams #
Small production (boring, resilient) #
- 3 server nodes (control plane) with embedded etcd
- 2+ agent nodes for workloads
- backups of etcd (scheduled)
- the bundled Traefik for ingress until you have a reason to swap it
- cert-manager for TLS automation
Why 3 servers? Quorum. etcd needs a majority of members alive to accept writes: 3 members tolerate 1 failure, 5 tolerate 2.
Cheapest “real” setup #
- 1 server node + regular backups
- accept that certain failures become “restore from backup” events
This can still be fine for internal tools if you set expectations.
Never run exactly 2 servers #
This is the one sizing mistake worth calling out, because it looks like a sensible halfway house and is strictly worse than the thing it is halfway to.
With embedded etcd, a 2-member cluster needs a majority of 2 — which is 2. Lose either node and the survivor has no quorum: etcd goes read-only, the API server stops accepting writes, and your control plane is down. A 1-server cluster also goes down when its node dies, but it only had one node that could die. So two servers double your machine bill, double your patching surface, and double the probability of a control-plane outage compared to one server. You have bought negative availability.
Go 1 → 3, not 1 → 2 → 3. If the budget for the third machine is not there yet, stay at one and spend the money on backups and a tested restore instead.
Day-1 checklist (do these before you host anything serious) #
- Decide datastore
- SQLite (the default — single server only)
- embedded etcd via
--cluster-init(common for HA) - external datastore (when you already have a managed DB and want separation)
- Backups
- automate backups
- test restoring to a fresh cluster
- Ingress + TLS
- start with the bundled Traefik; it is already there and it works
- move to Gateway API (Traefik supports it, as does Envoy Gateway) if and when you actually need what it adds: cross-namespace routing, a clean split between the person who owns the gateway and the people who own routes, or protocol support Ingress can’t express
- cert-manager and a clear DNS strategy
- Storage class strategy
- define what gets persistent storage
- define retention + backup approach
- Cost and capacity guardrails
- quotas/limits (at least per namespace)
- requests/limits for apps
- Upgrade policy
- monthly security updates
- a staging cluster (even tiny) if prod matters
Operating k3s: upgrades, backups, and failure modes #
Upgrades (keep them boring) #
- Upgrade server nodes one at a time, servers before agents.
- You don’t manage kubelet or containerd versions separately — k3s ships them inside its single binary, so upgrading k3s upgrades them together. That is one whole class of version-skew problem you simply don’t have here. What you do need to watch is skew between nodes: don’t leave an agent two minor versions behind its servers.
- Read the release notes and plan for matching changes in add-ons (ingress, cert-manager, CNI).
Small-team rule: if you can’t upgrade it, you can’t own it.
Backups (the one thing you should over-engineer) #
At minimum:
- daily etcd backups (and before upgrades)
- backup encryption at rest
- store backups off-node
- run restore drills (quarterly)
k3s has this built in, which is the good news — you do not need Velero on day one. On a server node with embedded etcd:
# take one now, e.g. before an upgrade
k3s etcd-snapshot save --name pre-upgrade
# what do I have?
k3s etcd-snapshot lsScheduled snapshots are on by default (every 12 hours, 5 retained) and land in /var/lib/rancher/k3s/server/db/snapshots/ — on the node. A backup that lives on the machine you are backing up is not a backup, so push them off-node by adding S3 flags to the server:
# on the server node, in its systemd unit / install flags
--etcd-s3 \
--etcd-s3-bucket=your-k3s-snapshots \
--etcd-s3-region=eu-central-1 \
--etcd-s3-folder=prod \
--etcd-snapshot-schedule-cron="0 */6 * * *" \
--etcd-snapshot-retention=10Any S3-compatible endpoint works (--etcd-s3-endpoint=), so Backblaze B2 or MinIO are fine if you’d rather not use AWS. Restoring is k3s server --cluster-reset --cluster-reset-restore-path=<snapshot> — read that procedure once before you need it, and note that if you used --etcd-s3 you can restore straight from the bucket onto a fresh machine.
If you’re on the default SQLite datastore instead, k3s etcd-snapshot does not apply: back up /var/lib/rancher/k3s/server/db/ and the server/token file.
Also remember: Kubernetes “state” is not just etcd. If you have persistent volumes, you need volume snapshots/backups too — and with the default local-path provisioner, that means backing up a directory on each node yourself.
Security basics that pay off immediately #
- Don’t expose the Kubernetes API to the public internet.
- Use a minimal set of admins, and prefer short-lived credentials.
- Turn on audit logging if you have compliance requirements.
- Treat your nodes like pets only in naming; in reality, they should be replaceable.
Observability: don’t fly blind #
A small, sane baseline:
- metrics: Prometheus-compatible (or a hosted backend)
- dashboards: Grafana
- logs: ship to a single place (even if it’s SaaS)
- alerts: 5–10 actionable alerts (node disk pressure, etcd health, ingress errors)
If you’re deciding between hosted vs self-hosted observability, see: SaaS vs self-hosted monitoring.
Common “k3s gotchas” (so you don’t lose a weekend) #
- Disk pressure causes mysterious pod evictions. Put alerts on node disk usage.
- High-cardinality metrics can melt your monitoring. Keep metrics intentional.
- Ingress + DNS is where most time goes. Standardize early, whichever API you pick.
- Storage is the difference between a demo and production. Know your PV story.
When to choose managed Kubernetes instead #
Pick managed Kubernetes when:
- you need high availability but don’t want to own the control plane
- compliance requires managed control-plane guarantees
- you’d rather spend engineer time on product than nodes
k3s is fantastic when you want the control and can own the operational playbook. Managed Kubernetes is fantastic when you want to buy reliability with money.
A simple decision rule #
- If you have one environment and no dedicated platform time → go managed.
- If you have multiple environments, cost pressure, or edge constraints → k3s is a strong choice.