Skip to content

Kubelet response body is read into memory with no size limit in kubeletClient.getMetrics #1856

Description

@vidyasangkar

What happened

In pkg/scraper/client/resource/client.go, kubeletClient.getMetrics reads
the entire /metrics/resource response from a kubelet with:

_, err = io.Copy(buf, response.Body)

buf is a bytes.Buffer backed by a sync.Pool s
io.LimitReader or http.MaxBytesReader wrapping response.Body anywhere in
this path. The HTTP client's Timeout is inherited from the caller's
rest.Config and is commonly unset (0 = unlimited)n
how much gets buffered is the per-node scrape context timeout (default 10s),
which limits total bytes by bandwidth × time rather than an explicit size.

pkg/scraper/scraper.go launches one goroutine per node with no concurrency
cap, so multiple nodes are scraped in parallel usin.

Why this matters

If a kubelet returns a much larger response than ex
misbehaving metrics endpoint, or a compromised node), metrics-server will
buffer all of it in memory before doing any parsing or validation. Because
this happens per-node and in parallel, it's possibl
oversized response to push metrics-server's own memory usage well past
expected levels, risking an OOM-kill of the metrics-server pod and taking the
metrics API down for the whole cluster until it rec

Suggested fix

Bound the read independently of the peer, e.g. wrap the body before copying:

limited := io.LimitReader(response.Body, maxRes
n, err := io.Copy(buf, limited)
// treat n == maxResponseBytes as "possibly trut error

with maxResponseBytes set comfortably above the l
/metrics/resource payload. The buffer returned to the sync.Pool in the
deferred cleanup should also be capped so an oversi
large slice sitting in the pool.

Versions

  • metrics-server: v0.8.0 (commit d66279c)
  • Location: pkg/scraper/client/resource/client.gos`
    (io.Copy call, ~line 127 on this tag)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triageIndicates an issue or PR lacks a `triage/foo` label and requires one.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions