docs: clarify admission export record size and spool retention limits - #4783
Open
ShiyunXu wants to merge 2 commits into
Open
docs: clarify admission export record size and spool retention limits#4783ShiyunXu wants to merge 2 commits into
ShiyunXu wants to merge 2 commits into
Conversation
Record the measured basis for the 64 KiB bound and why oversized records are dropped rather than truncated. Signed-off-by: ShiyunXu <ShiyunXu@users.noreply.github.com>
Explain what counts toward the 64 KiB record, add spool retention guidance, and correct the log rate-limit description: all drop reasons share one limiter, not one per class. Signed-off-by: ShiyunXu <ShiyunXu@users.noreply.github.com>
|
Contributor
There was a problem hiding this comment.
Pull request overview
Clarifies admission export record sizing, spool retention, and rate-limited logging behavior.
Changes:
- Documents the complete-record 64 KiB limit.
- Explains disk segment rotation and retention.
- Corrects shared log-limiter documentation.
Show a summary per file
| File | Description |
|---|---|
website/docs/export.md |
Expands operational guidance. |
pkg/webhook/export.go |
Documents the record-size bound. |
pkg/export/disk/disk.go |
Clarifies disk segment sizing. |
Review details
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Suppressed comments (5)
website/docs/export.md:163
- Violation messages are not bounded by the community templates' static text:
result.Msgis copied directly into the record and may include arbitrarily large policy-interpolated input. The measured sample supports an ordinary-case estimate, but not the claim that message content cannot exhaust the limit.
In practice a violation record encodes to **around 1.7 KiB**, so the limit is far from ordinary output. Violation messages are not the constraining factor: messages produced by community policy libraries are typically 60–110 bytes and rarely exceed 350 bytes even when a policy interpolates an entire allow-list into the message. The remaining space is the envelope described below.
website/docs/export.md:172
- The list of unbounded fields omits
message, even though policy output is copied without a size bound before the complete record is checked. Include it so the following claim that oversized records arise from one of these fields remains accurate.
| `details` | Returned by the policy itself | Determined by the policy author |
website/docs/export.md:181
- This troubleshooting advice incorrectly rules out the violation message and also omits
detailsand user groups. Each is copied intoExportMsgwithout a bound and can independently causemessage_too_large, so users need to inspect all large record fields.
If you observe `message_too_large` drops, inspect the annotations on the constraint and the labels on the objects being reviewed rather than the violation message.
website/docs/export.md:187
- This paragraph gives an unsupported ten-records-per-minute threshold and points to telemetry that cannot detect the stated loss. A continuously active stream already rotates on the one-minute timer, and successful retention eviction increments no metric or status error; the existing admission export metrics only cover queue drops and backend publish outcomes.
At sustained volume the 24-hour age limit is effectively unreachable: once the workload produces more than about ten records per minute, the 20-segment count limit evicts segments first. Treat the spool as a short buffer sized in minutes, not as a day of history. Segments removed before a reader consumes them are not reported in `ConnectionPodStatus`; use the admission export metrics to detect a reader that has fallen behind.
pkg/webhook/export.go:48
- Being below the segment size guarantees only that the record fits in a fresh segment; writes can still fail because of the total-spool reservation, free-space guard, or I/O errors. Avoid saying it can always be written.
// driver's per-segment size so a single record can always be written.
- Files reviewed: 3/3 changed files
- Comments generated: 2
- Review effort level: Balanced
| The 64 KiB record limit applies to the entire JSON object after encoding, not only to the violation message. JSON field names and escaping, policy-provided details, constraint annotations, resource labels, and request identity all count toward the limit. KiB measures bytes, so the number of characters that fit varies with UTF-8 and JSON escaping. The limit leaves room for normal policy and request metadata while preventing one user-influenced result from consuming a disproportionate share of the queue and disk spool. The `kubectl.kubernetes.io/last-applied-configuration` constraint annotation is omitted, but other annotations still count. An oversized record is dropped before enqueue and reported with drop reason `message_too_large`. | ||
| #### Understanding the 64 KiB record limit | ||
|
|
||
| The 64 KiB limit applies to the **entire JSON object after encoding**, not only to the violation message. Everything in the record counts: JSON field names and escaping, the constraint identity, policy-provided `details`, constraint annotations, resource labels, and request identity. Because KiB measures bytes, the number of characters that fit varies with UTF-8 and JSON escaping — roughly 64,000 ASCII characters, but only about half that for escape-heavy content and about a quarter for CJK or emoji. Gatekeeper accounts for escaping exactly when it measures a record, so a string of quotes, control characters, or `<`, `>`, and `&` consumes more budget than its raw length suggests. |
Comment on lines
+30
to
+44
| // A typical record encodes to roughly 1.7 KiB: violation messages in | ||
| // community policy libraries top out near 350 bytes, and the surrounding | ||
| // envelope of constraint identity, request identity, resource labels, and | ||
| // annotations accounts for the rest. 64 KiB therefore accepts a normal | ||
| // record with roughly thirty times headroom, so the limit is not reached by | ||
| // message content alone. | ||
| // | ||
| // The headroom exists for the fields this package cannot bound. Constraint | ||
| // annotations, resource labels, request user groups, and policy-provided | ||
| // details are copied through verbatim, and Kubernetes permits far more | ||
| // annotation data on a single object than a record may occupy. Truncating | ||
| // those fields would silently misreport a violation, so an oversized record | ||
| // is dropped whole and counted under admissionExportDropReasonMessageTooLarge. | ||
| // Keeping the bound well above ordinary records makes that outcome a signal | ||
| // of unusual metadata rather than routine policy output. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
Documentation-only. Explains the 64 KiB admission export record limit and the disk spool retention behavior, and corrects one inaccurate statement about log rate limiting.
No functional change. Every line changed under
pkg/is a comment:returns nothing.
Why
The existing text says the 64 KiB limit "leaves room for normal policy and request metadata," but never says how much room, so it is hard to tell what would actually exceed it. The limit is easy to misread as applying to the violation message. It does not — it applies to the whole encoded record, and the fields most likely to exhaust it are ones a policy author does not control.
Measured basis for the numbers
To check whether 64 KiB is well chosen, I measured the message templates shipped by gatekeeper-library and modelled full encoded records around them.
Message templates extracted from 48
src.regofiles (132 templates):Full encoded
ExportMsgbuilt around each template, including constraint identity, request identity, eight resource labels, five constraint annotations, and three user groups:A bare envelope with a one-character message and no labels or annotations is 804 B.
So message content does not approach the limit — roughly 30x headroom on the largest realistic record. What can approach it is the pass-through metadata. Holding everything else fixed, the limit is reached at:
That asymmetry is what the new documentation and the constant comment try to make visible, along with its two operational consequences: the condition is systematic per-constraint rather than occasional, and it is silent apart from metrics.
Correction included
website/docs/export.mdclaimed drop and publish-error logs are limited to "one per minute for each class." There are two limiters, not five:lastDropLogandlastPublishLog(pkg/webhook/export.go). All five drop reasons sharelastDropLog, so aqueue_fullburst suppresses amessage_too_largeline for the same minute. The bullet now says so and points to the metrics, which do count per reason.Also documented
The 24-hour spool TTL is effectively unreachable under sustained load. Above roughly ten records per minute the 20-segment count limit evicts segments first, so the spool is a buffer measured in minutes rather than a day of history. Evictions that happen before a reader consumes a segment are not surfaced in
ConnectionPodStatus.Testing
Documentation and comments only; no behavior to test. I was not able to run
make lintorgo buildin the environment where this was written, so please let CI confirm gofmt is happy with the reflowed comment block.