Kubernetes·5 min read·

Tuning a Production-Ready Single-Node K3s Cluster on High-Speed VPS

Optimize K3s on a single node by disabling surplus controllers, tuning SQLite/etcd write intervals, and configuring system resource reservations.

NB

Netbay Engineering

Netbay Engineering

On this page

Rancher K3s is a certified, fully compliant Kubernetes distribution packaged as a single binary under 100MB. It strips legacy in-tree cloud providers and alpha features while substituting heavy etcd clusters with an embedded SQLite or Kine datastore. This makes K3s the gold standard for running single-node Kubernetes on VPS instances.

However, running a default K3s installation in production without tuning can lead to memory exhaustion, aggressive log churn, and node instability when unexpected traffic spikes arrive. Tuning the control plane and defining explicit cgroup resource reservations ensures that system daemons like sshd and systemd remain responsive even if user pods consume excessive memory.

In a default Kubernetes node setup, the kubelet allows workloads to allocate memory up to the physical limits of the host unless explicitly constrained. If user workloads experience a memory leak or an unconstrained burst, the Linux kernel Out-Of-Memory (OOM) killer intervenes. Because the OOM killer targets processes with the highest oom_score, it frequently terminates container runtime daemons or critical system services, leading to node deadlocks that require physical reboots. Implementing node allocatable sizing prevents this catastrophe.

Expand
Single-Node K3s Production Setup
K3s lightweight Kubernetes architecture on Linux

Streamlining the Control Plane via config.yaml

Before initializing K3s, create a declarative configuration file at /etc/rancher/k3s/config.yaml. You can disable built-in components such as the bundled Traefik proxy and servicelb if you intend to manage ingress via your own Caddy or Nginx gateway:

Single-Node K3s Production Architecture & Resource Slicing K3s Control Plane Process (k3s server) - Embedded SQLite / Kine datastore - API Server + Controller Manager + Scheduler - Flannel CNI (host-gw backend) - Local Path Provisioner (storage) Disabled: traefik, servicelb, local-storage Saves ~350MB baseline RAM System Resource Reservation (cgroups) system-reserved: cpu=500m, memory=512Mi kube-reserved: cpu=250m, memory=256Mi eviction-hard: memory.available < 250Mi Allocatable Pool (User Workloads): Remaining RAM & vCPU guaranteed against system OOM killer panics
yaml
# /etc/rancher/k3s/config.yaml
write-kubeconfig-mode: "0644"
tls-san:
  - "k8s.example.com"
  - "127.0.0.1"

# Disable default bundled controllers for custom ingress
disable:
  - traefik
  - servicelb

# Flannel network configuration
flannel-backend: "host-gw"

# Kubelet system reservations to prevent host starvation
kubelet-arg:
  - "system-reserved=cpu=500m,memory=512Mi"
  - "kube-reserved=cpu=250m,memory=256Mi"
  - "eviction-hard=memory.available<250Mi,nodefs.available<10%"
  - "max-pods=64"

Setting flannel-backend to host-gw eliminates VXLAN packet encapsulation overhead, routing pod traffic directly across host network interfaces with native MTU efficiency. In a single-node setup, VXLAN tunnels merely waste CPU cycles calculating outer IP and UDP checksums.

The kubelet-arg parameters carve out system-reserved and kube-reserved slices in cgroups. In this configuration, 768MB of RAM is strictly cordoned off for the Linux kernel, systemd, sshd, and the K3s supervisor daemon. Kubernetes subtracts these reservations from total node capacity to compute the node's "Allocatable" limit, ensuring that user pods can never exhaust the RAM required to keep the host alive.

Executing the Installation Script

Run the official K3s installation script with your configuration file in place:

bash
# Download and install K3s with channel pin
curl -sfL https://get.k3s.io | INSTALL_K3S_CHANNEL=v1.30 sh -

# Verify node status and allocatable capacity
kubectl get nodes -o wide
kubectl describe node | grep -A 8 "Allocatable:"

# Configure local kubectl alias and autocomplete
echo 'export KUBECONFIG=/etc/rancher/k3s/k3s.yaml' >> ~/.bashrc
source ~/.bashrc

Tuning SQLite Datastore Performance on SSDs

The embedded SQLite datastore maintains cluster state. On high-speed SSD drives, configure WAL (Write-Ahead Logging) mode and synchronous pragma to ensure durability without excessive fsync bottlenecks:

bash
# Inspect SQLite database size and WAL journal
ls -lh /var/lib/rancher/k3s/server/db/

# Verify journal mode
sqlite3 /var/lib/rancher/k3s/server/db/state.db "PRAGMA journal_mode;"

SQLite's WAL mode permits concurrent reads while write transactions append to a separate journal file, eliminating read-write table lock contention when multiple controllers query the API server simultaneously.

Configuring resource boundaries between system daemons and Kubernetes pods provides the operational stability required for mission-critical microservices.

Kubernetes Architecture and K3s Essentials
YouTube

You can spin up an Ubuntu 24.04 instance on Netbay in under 60 seconds with Intel Xeon Platinum compute and high-speed SSD storage in Lucknow — netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance