K3s
K3s is a CNCF-conformant Kubernetes distribution packaged as one binary under 100 MB. It bundles containerd, Flannel, CoreDNS, Traefik, a service load balancer, local-path storage and a Helm controller, and stores cluster state in SQLite through the Kine shim by default, with embedded etcd or an external SQL database for HA. Apache 2.0 and free. It fits edge sites, homelabs, CI and small VMs where a full kubeadm or RKE2 install costs more than it returns.
K3s is a Kubernetes distribution that installs as a single binary and starts a working cluster with one command. It removes the setup work of a standard cluster: certificates, a datastore, a CNI, ingress, DNS and storage all come in the box with defaults that suit small machines. The official docs at docs.k3s.io own the full flag reference.
What it is
A packaged distribution of upstream Kubernetes, not a fork. The project keeps its Kubernetes patches small and says it intends not to change core Kubernetes behaviour. The k3s server process runs the control plane, the datastore and the node components in one supervisor; k3s agent runs only the node components. Licence is Apache 2.0. Rancher Labs created it, SUSE now sponsors it, and it has been a CNCF Sandbox project since August 2020.
The bundle, as listed in the project README:
- containerd and runc for containers, Flannel for the CNI, kube-router for NetworkPolicy.
- CoreDNS, Metrics Server, Traefik for ingress, ServiceLB (Klipper) for
LoadBalancerServices. - Local-path-provisioner for node-local persistent volumes.
- Helm controller for CRD-driven Helm installs.
- Kine, a shim that serves the etcd API from SQLite, MySQL, MariaDB or Postgres.
Releases track upstream Kubernetes minors, with patch lines for each supported minor shipped together. On 2026-09-30 the project shipped v1.37.1+k3s1, v1.36.5+k3s1, v1.35.9+k3s1 and v1.34.12+k3s1. The stable channel points at v1.36.5+k3s1 and latest at v1.37.1+k3s1. v1.36.5 bundles Traefik v3.7.13, CoreDNS v1.14.7, containerd v2.3.4, helm-controller v0.17.9 and local-path-provisioner v0.0.37.
Two recent changes need attention on upgrade. The September releases move the packaged Traefik chart to v40, which renames the ingress-nginx migration provider from kubernetesIngressNginx to kubernetesIngressNGINX. The same releases reject anonymous access to the supervisor's router for the Spegel registry, pprof and metrics endpoints.
How it works
A server node runs one process that contains the API server, scheduler, controller manager, kubelet, containerd and the K3s supervisor on port 6443. With the default datastore, the API server talks the etcd API to Kine, and Kine turns those calls into SQL against a SQLite file on the server's disk. That arrangement makes a single-server cluster cheap and simple, and it is also why SQLite supports only one server.
Agents join with the server URL and the cluster token. Each agent holds a websocket tunnel to the supervisor, and a client-side load balancer inside the agent keeps a list of server endpoints. The kubelet API is reached over that tunnel, so worker nodes do not expose it to the control plane on an open port.
The server also runs a deploy controller that watches the manifests directory. Every file there is applied like kubectl apply at start-up and on each change, and is tracked as an AddOn object in kube-system. The packaged components are themselves HelmChart objects in that directory, which the Helm controller installs by running a Helm job pod.
Step 1 of 4. A client sends a create or update. The API server authenticates it, runs admission and validates the object.
Single server with the default SQLite datastore. With embedded etcd, Kine is replaced by etcd on each server.
For high availability, three or more servers run embedded etcd instead of Kine and SQLite, and an odd server count keeps quorum. An existing single server can be converted by restarting it with --cluster-init. Two or more servers can also share an external MySQL, MariaDB or Postgres database through Kine.
When to use it
Reach for it when:
- The cluster runs on small machines: VMs on a laptop, edge boxes, ARM boards, CI runners.
- A working cluster with ingress, DNS and storage is needed in minutes, without picking each component.
- Platform add-ons should be declared as files on the server and installed by the cluster itself.
- Rancher will manage the cluster; K3s is a supported Rancher host and downstream distro.
Skip it when:
- A compliance regime needs a CIS-hardened distro by default. RKE2 is SUSE's distro for that case.
- A managed service (EKS, AKS, GKE) is already available and its cost is acceptable.
- The cluster needs replicated block storage. Local-path volumes stay on one node; add Longhorn or a CSI driver.
- Several servers must share state but etcd is unwanted and no external SQL database exists. SQLite is single-server only.
At a glance
Core concepts
- Server / agent — a server runs the control plane and datastore; an agent runs only kubelet, containerd and the CNI.
- Token — joins nodes and encrypts confidential data in the datastore. Losing it makes a datastore backup unusable.
- Datastore — SQLite through Kine (default), embedded etcd (HA), or an external SQL database through Kine.
- Manifests directory —
/var/lib/rancher/k3s/server/manifests; files are applied automatically and tracked asAddOnobjects. - HelmChart / HelmChartConfig — CRDs in
helm.cattle.io/v1. The first installs a chart; the second overrides values of an existing HelmChart with the same name and namespace. - Release channels —
stable(default),latest, and one channel per Kubernetes minor.
Key facts
| Item | Value |
|---|---|
| Licence | Apache 2.0 |
| Current lines | v1.37.1, v1.36.5, v1.35.9, v1.34.12 (2026-09-30) |
| Stable channel | v1.36.5+k3s1 |
| Server minimum | 2 CPU, 2 GB RAM |
| Agent minimum | 1 CPU, 512 MB RAM |
| Architectures | x86_64, arm64, armhf |
| Main port | TCP 6443 (supervisor and API server) |
| Other ports | UDP 8472 Flannel VXLAN, TCP 10250 kubelet, TCP 2379–2380 embedded etcd |
| Default kubeconfig | /etc/rancher/k3s/k3s.yaml |
K3s vs RKE2
| Aspect | K3s | RKE2 |
|---|---|---|
| Aim | Small footprint, edge, homelab | Security and compliance |
| Default datastore | SQLite through Kine | Embedded etcd |
| Packaging | One binary | Binary plus control-plane static pods |
| Add-ons | HelmChart CRDs via the Helm controller | Same Helm controller |
| Managed by Rancher | Yes | Yes |
How to integrate
Install a server and join an agent
# Server, pinned to a release; config can also live in /etc/rancher/k3s/config.yaml
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.36.5+k3s1 sh -s - server \
--write-kubeconfig-mode 0644
sudo cat /var/lib/rancher/k3s/server/node-token # join token
# Agent on another host
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.36.5+k3s1 \
K3S_URL=https://server.example.com:6443 K3S_TOKEN=<token> sh -
Packaged components can be dropped with --disable (traefik, servicelb, local-storage, metrics-server, coredns).
Install a chart from the manifests directory
# /var/lib/rancher/k3s/server/manifests/cert-manager.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: cert-manager
namespace: kube-system
spec:
repo: https://charts.jetstack.io
chart: cert-manager
version: <pinned-version>
targetNamespace: cert-manager
createNamespace: true
valuesContent: |-
crds:
enabled: true
Override a packaged component
# /var/lib/rancher/k3s/server/manifests/traefik-config.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: traefik # must match the packaged HelmChart
namespace: kube-system
spec:
valuesContent: |-
ports:
web:
forwardedHeaders:
trustedIPs:
- 10.0.0.0/8
Automated upgrades with system-upgrade-controller
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
name: server-plan
namespace: system-upgrade
spec:
concurrency: 1
cordon: true
nodeSelector:
matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: In
values: ["true"]
serviceAccountName: system-upgrade
upgrade:
image: rancher/k3s-upgrade
version: v1.36.5+k3s1 # or channel: https://update.k3s.io/v1-release/channels/stable
An agent plan selects nodes without the control-plane label and uses a prepare step so agents wait for the server plan.
Back up a SQLite server
The docs require a copy of /var/lib/rancher/k3s/server/db/ and the token file /var/lib/rancher/k3s/server/token. Restoring both together brings the cluster back; the database without its token is unreadable.
In the GL stack
K3s v1.36.5+k3s1 runs on all three clusters of the GodfreyLabs homelab: management, beta and prod. Each cluster is a single-server K3s install inside its own Lima VM on a Mac. The VM template's provision script installs K3s at a pinned version, so a rebuilt VM comes back on the same release.
Every cluster keeps the default SQLite datastore through Kine, which matches the one-server shape of each cluster. The built-in Traefik ingress and local-path storage stay on, and Traefik is tuned through HelmChartConfig rather than replaced. The built-in Helm controller installs the platform charts from HelmChart objects, so a fresh cluster pulls its base layer from files on the server.
A control-plane snapshot runs nightly. It takes a consistent sqlite3 .backup of the datastore and copies the token, credential and TLS directories to the backup store, with 14 days kept. That snapshot covers the case the docs warn about: a datastore copy is only useful with its token. Workload objects and volumes are covered separately by Velero.
Upgrades are driven from Rancher, which runs them through the System Upgrade Controller one node at a time with cordon and drain. The order is beta first, then prod, then the management cluster. After that, the same version is pinned in the VM template so new VMs match.
Gotchas
- The token is part of the backup. It encrypts confidential data in the datastore. A database copy restored without the matching token cannot be read.
- Deleting a manifest file does not delete its resources. Remove the objects by hand, or use
--disablefor packaged components. A<name>.yaml.skipfile stops future deploys but leaves existing resources in place. - Do not edit packaged manifests. K3s rewrites them on every start. Use a HelmChartConfig with the same name and namespace.
- Manifests are not synced between servers. In a multi-server cluster, custom files must be kept identical on each server by other means.
- Do not skip minor versions. The upgrade controller does not enforce the Kubernetes skew policy. A downgrade plan fails and leaves cordoned nodes cordoned.
- Rancher-managed clusters upgrade through Rancher. The docs say to use the Rancher UI, not hand-written Plans, when Rancher manages the cluster. Rancher v2.15's support matrix stops at Kubernetes v1.36, so check it before moving to the v1.37 line.
- Traefik chart v40 rename. Configs using the ingress-nginx migration provider must change
kubernetesIngressNginxtokubernetesIngressNGINX. - Local-path ignores capacity. The provisioner does not enforce PVC size limits, and each volume is tied to the node it was created on.
Risks
- Stewardship. SUSE sponsors the project and its release process. The code is Apache 2.0 and the project sits in the CNCF Sandbox, which lowers but does not remove single-vendor risk.
- Patch cadence. Several patch lines ship together roughly monthly, often with CVE fixes in bundled components. A cluster pinned in a VM template drifts unless the pin moves with each upgrade.
- Single-server datastore. SQLite has no replication. One server means one failure domain; the nightly snapshot and token copy are the recovery path.
- Bundled defaults. Traefik, Flannel and local-path are opinionated choices. Swapping one later means a migration, not a flag.
Alternatives
- RKE2 — SUSE's hardened distro with embedded etcd by default; pick it when CIS posture and compliance matter more than footprint.
- k0s — another single-binary distribution, from Mirantis; pick it when its bundled defaults suit better than K3s's.
- kubeadm — the upstream bootstrap tool; pick it to choose every component by hand.
- kind or k3d — clusters in containers; pick them for throwaway test clusters in CI or on a laptop.
Related
- Lima — the VMs the clusters run in.
- Rancher, Fleet and the System Upgrade Controller — management and upgrades.
- Traefik, cert-manager and Argo CD — ingress, certificates and app delivery on top.
- Velero and Rancher Backups — backups beyond the control-plane snapshot.
- K3s documentation
- K3s releases on GitHub
- K3s Helm controller docs
- Automated upgrades with system-upgrade-controller
