k3s single-node cost reduction: which bundled components can be safely disabled without an alternative ingress path
0 reputation · 02 Feb 2023, 16:39 UTC
0 reputation · 02 Feb 2023, 16:39 UTC
I'm consolidating a low-traffic internal workload onto a single small VM and evaluating k3s's single-server, SQLite-backed mode to cut baseline compute cost compared to a multi-node upstream Kubernetes cluster. The single-binary footprint and embedded datastore are documented to lower idle memory, which fits this workload's traffic profile.
The documented --disable flag can strip bundled components such as traefik, servicelb, metrics-server, and local-storage to shrink overhead further. My uncertainty is the dependency boundary: the workload currently receives traffic through the default Traefik ingress and ServiceLB, and I have no external load balancer or alternative ingress controller provisioned. I also want to keep the option of migrating from SQLite to etcd later if traffic grows, without a painful datastore migration.
Assuming a recent k3s release (component names under --disable vary by version, so I'd confirm against the installed release's docs):
kubectl top-based verification of the very savings I'm targeting?32775 reputation · 02 Feb 2023, 16:53 UTC
With Traefik terminating all inbound traffic and no external load balancer or proxy provisioned, traefik and servicelb are not safe to disable. They are your only ingress path: removing Traefik leaves Ingress resources unrouted, and removing ServiceLB leaves LoadBalancer Services without an external IP.
| Component | Safe to disable here? | Consequence |
|---|---|---|
traefik | No | Ingress rules stop routing; inbound traffic breaks |
servicelb | No | LoadBalancer Services never receive an external IP |
metrics-server | Yes, with a trade-off | Saves memory; kubectl top stops working |
local-storage | Only if stateless | local-path PVCs can no longer be provisioned |
coredns | Avoid | Cluster DNS and service discovery break |
If you later want to remove Traefik, the minimal replacements, ranked by idle cost, are a NodePort Service fronted by a lightweight host-level proxy (nginx or HAProxy installed on the VM), or exposing the workload directly via hostPort or hostNetwork: true. Both bypass the Ingress API and shift routing configuration onto the host. Until one of those exists, keep Traefik enabled.
Confirmed behavior: disabling metrics-server removes kubectl top nodes and kubectl top pods. Since verifying the savings is part of your goal, keep it enabled until you have captured an idle baseline on the VM, then test with it disabled and compare using host-level tools such as systemd-cgtop or container runtime stats. The saving is real, but you lose your primary native measurement tool, so decide from data rather than assumption.
Confirmed: k3s backup and restore is datastore-specific — SQLite backups restore into SQLite, and etcd snapshots restore into etcd. There is no supported in-place, zero-downtime migration between them. The realistic path is a scheduled outage: export your workload manifests, re-initialize the server with etcd (--cluster-init for the first server), and reapply state. Starting on SQLite does not foreclose etcd, but it does mean downtime during the transition, so keep your manifests in a GitOps-friendly form from day one. Verify the exact steps against your installed release's docs, as migration tooling has changed across versions.
k3s server \
--disable local-storage # only if the workload keeps no state in local PVCs
Keep traefik, servicelb, and metrics-server enabled initially. This preserves reachability, monitoring, and default behavior while you measure the real idle footprint.
kubectl get svc — LoadBalancer Services show an external IP while ServiceLB is active.kubectl top nodes — returns usage while metrics-server is active; errors once disabled.One diagnostic detail that changes the recommendation: does the workload use PVCs provisioned by local-path? If yes, local-storage must stay enabled; if it is fully stateless or uses external volumes, disabling it is the one clean win available today.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.