Skip to content

handler3: gzip-compress cached OpenAPI V3 JSON specs - #656

Open
mauriciopoppe wants to merge 1 commit into
kubernetes:masterfrom
mauriciopoppe:pr-handler3-compressed-cache
Open

mauriciopoppe wants to merge 1 commit into
kubernetes:masterfrom
mauriciopoppe:pr-handler3-compressed-cache

Conversation

@mauriciopoppe

@mauriciopoppe mauriciopoppe commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

What type of PR is this?

/kind cleanup

What this PR does / why we need it:

In kube-apiserver, pkg/handler3 caches the marshaled JSON bytes of each accessed GroupVersion's OpenAPI V3 spec in openAPIV3Group.jsonCache for the lifetime of the server (6.85 MB of retained heap for just 3 GroupVersions, and ~18+ MB across all built-in GroupVersions).

This PR stores gzip-compressed JSON bytes in jsonCache without changing ETag hashes, discovery URLs, or response payloads:

  1. Compress cached JSON in openAPIV3Group.jsonCache (pkg/handler3/handler.go and newOpenAPIV3Group): Computes computeETag(jsonBytes) on the uncompressed JSON first, then stores the gzip-compressed slice (bytes.Clone(buf.Bytes())) in timedSpec.spec using sync.Pool (gzipWriterPool and gzipReaderPool) to reuse gzip.Writer and gzip.Reader state machines without lock contention. Only readers that complete io.ReadAll and Close without error are returned to gzipReaderPool.
  2. Serve pre-compressed bytes on Accept-Encoding: gzip and lazy-decompress via lazyGzipReadSeeker (pkg/handler3/handler.go and HandleGroupVersion): HandleGroupVersion sets Vary: Accept-Encoding on JSON responses so HTTP caches and reverse proxies distinguish compressed and uncompressed representations. When acceptsGzip(r) is true (iterating all r.Header.Values("Accept-Encoding") header lines per RFC 9110 and verifying no Range header is present), HandleGroupVersion sets Content-Encoding: gzip and serves timedSpec.spec directly. Plain JSON requests pass &lazyGzipReadSeeker{compressed: data} to http.ServeContent, delaying decompression until Seek or Read is invoked after http.ServeContent evaluates If-None-Match and If-Modified-Since preconditions (304 Not Modified responses perform zero gzip decompression).

Special notes for your reviewer:

1. pkg/handler3 Benchmarks (go test -bench=. -benchmem -count=5 ./pkg/handler3/...)

Benchmark Metric Before (e2e80c32a35f) After (This PR) Delta
BenchmarkHandler3CachedSpecMemory Retained cached-bytes (len) 604,218 B 16,386 B -97.3% (36.9x smaller)
BenchmarkHandler3CachedSpecMemory Retained cached-cap-bytes (cap) 622,592 B 18,432 B -97.0% (33.8x smaller)
BenchmarkServeGroupVersionGzip Serve Latency (ns/op) 263,455 ns/op 17,590 ns/op -93.3% (15.0x faster)
BenchmarkServeGroupVersionGzip Serve Bytes (B/op) 526,292 B/op 11,784 B/op -97.8% (-514.5 KB/op)

2. kube-apiserver Heap Impact (pprof inuse_space via TestAPIServerMemoryIntegration, 3 GroupVersions Queried)

Metric / pprof Symbol (inuse_space) Before After Delta
bytes.Clone (from handler3 json.Marshal) 6,853.25 kB < 218 kB -6.67 MB (-96.8%)
Net kube-apiserver Live Heap Impact 6,853.25 kB ~1,481 kB -5.51 MB net live heap

Does this PR introduce a user-facing change?

NONE

@kubernetes-prow kubernetes-prow Bot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. kind/cleanup Categorizes issue or PR as related to cleaning up code, process, or technical debt. labels Oct 7, 2026
@kubernetes-prow
kubernetes-prow Bot requested review from Jefftree and jpbetz October 7, 2026 23:50
@kubernetes-prow kubernetes-prow Bot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Oct 7, 2026
@jpbetz

jpbetz commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

/assign @seans3 @Jefftree

@mauriciopoppe
mauriciopoppe force-pushed the pr-handler3-compressed-cache branch from 82f223b to fa06d53 Compare October 8, 2026 00:04
@kubernetes-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: mauriciopoppe
Once this PR has been reviewed and has the lgtm label, please ask for approval from jefftree. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@mauriciopoppe
mauriciopoppe force-pushed the pr-handler3-compressed-cache branch from fa06d53 to 5c71d05 Compare October 8, 2026 00:41
@kubernetes-prow kubernetes-prow Bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Oct 8, 2026
@mauriciopoppe
mauriciopoppe force-pushed the pr-handler3-compressed-cache branch from 5c71d05 to 115a031 Compare October 8, 2026 01:49
@mauriciopoppe
mauriciopoppe marked this pull request as ready for review October 8, 2026 16:40
@kubernetes-prow kubernetes-prow Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Oct 8, 2026
@kubernetes-prow
kubernetes-prow Bot requested a review from sttts October 8, 2026 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/cleanup Categorizes issue or PR as related to cleaning up code, process, or technical debt. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants