k3s server memory grows steadily: separating a real leak from cache and containerd
0 reputation · 24 Feb 2024, 06:42 UTC
0 reputation · 24 Feb 2024, 06:42 UTC
k3s ships the control plane, kubelet, containerd, flannel, CoreDNS and ServiceLB as a single binary per node. When the k3s server process shows steady RSS growth on a node with otherwise stable workloads, node-level metrics alone cannot say whether that growth is a genuine leak in one embedded component, page cache accounted to the process, or containerd image and content-store expansion.
k3s does expose Go pprof profiling through the supervisor when debug settings are enabled, so heap snapshots taken at two points under steady load should, in principle, separate control-plane growth from cache. The hard part is interpretation. Historical leak reports have spanned subsystems such as the supervisor's tunnel (remotedialer) connections and metrics handling, and whether any particular leak is fixed depends on the exact release line — release notes have to be checked per version, and profiling flags and memory baselines also shift between releases.
Before escalating a growth pattern as a bug, what evidence is actually sufficient — a diffed heap profile from the supervisor's pprof endpoint, RSS trended alongside node allocatable memory and containerd store size, or both? And once true process growth is confirmed, what is the dependable way to attribute it to a specific embedded component and match it against closed issues in the relevant k3s release notes?
30775 reputation · 24 Feb 2024, 15:51 UTC
To confirm a genuine memory leak in a k3s server process, you need both a trended RSS (Resident Set Size) report and a diffed heap profile. An RSS trend alone is insufficient because the Go runtime may retain freed memory without returning it to the kernel, and node-level metrics often conflate process memory with page cache.
Node-level "used memory" includes reclaimable page cache. To isolate the k3s server, monitor the specific process rather than the node. Note that containerd runs as a separate child process; its memory and disk-based content store must be tracked independently.
VmRSS and VmHWM from /proc/[pid]/status for the k3s server and the containerd child separately.free -m (available memory) to ensure the growth isn't just the OS caching files.du on the k3s data directory (typically /var/lib/rancher/k3s) to confirm that containerd image expansion is a disk issue, not a RAM issue.If RSS grows monotonically under stable workloads, use the pprof endpoint (enabled via debug flags) to determine if the growth is inside the Go heap.
go tool pprof -base profile_A.pb.gz profile_B.pb.gz
inuse_space to identify which functions are retaining memory.Analyze the symbol paths in the diff to attribute the leak to a specific embedded component:
| Symbol Path / Package | Likely Component |
|---|---|
k8s.io/apiserver or client-go |
Control-plane caches or informers |
rancher/remotedialer |
Agent tunnel connections |
kine |
SQLite datastore layer |
Before filing a bug, verify that the growth is not a known issue by checking the release notes for your specific minor version line. Upgrade to the latest patch release and re-baseline the RSS. If growth persists, provide the following evidence in your report:
inuse_space growth.Required Diagnostic Detail: To refine this recommendation, please provide the exact k3s version and whether the node is a standalone SQLite server or part of an HA etcd cluster with tunneling agents.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.