Question and context
A controller needs only object names, labels, namespaces, and resourceVersion, yet it reads large Pod spec and status fields. Use Kubernetes metadata-only negotiation for list requests, then explain unsupported aggregated APIs, 406 responses, and the subsequent watch.
What the interviewer is testing
- Whether you construct the
Acceptparameters correctly and distinguish single-object from list representations. - Whether you understand partial responses as a representation, not an arbitrary field-filter patch.
- Whether you design 406, version-skew, and full-object fallback without making startup fail or retry forever.
- Whether list/watch
resourceVersionand cache consistency remain correct.
Clarifying questions to ask first
Resource and server boundary
Is the target an in-tree API, a CRD, or an aggregated API? Do every apiserver and proxy support metadata-only responses?
Usage pattern
Does the client only build existence and label indexes, or will it later need spec? Must it start a watch immediately after list?
Failure policy
May the client read full objects when partial responses are unavailable, or must it fail explicitly to protect bandwidth and memory budgets?
A 30-second answer framework
I would prefer application/json;as=PartialObjectMetadataList;g=meta.k8s.io;v=v1 for a list and accept only metadata plus the list resourceVersion. I would add lower-quality application/json as fallback, then inspect the response kind to learn what was actually returned. Without fallback, treat 406 as an unsupported capability rather than a retryable storm. Start the watch from the returned resource version and record the representation in the cache.
Deep-dive answer steps
1. Distinguish the representations
Use as=PartialObjectMetadata for one object and as=PartialObjectMetadataList for a collection. The response omits spec and status and retains metadata; that lowers serialization, network, and decode cost but cannot serve callers that need business fields.
2. Construct a fallback request
GET /api/v1/pods
Accept: application/json;as=PartialObjectMetadataList;g=meta.k8s.io;v=v1, application/json;q=0.9If the preferred representation is unavailable, the server may choose normal JSON. The client must inspect kind, apiVersion, and Content-Type; HTTP 200 alone does not prove that a partial object was returned.
3. Handle strict mode and 406
When the request advertises only a partial representation that the target API does not support, Kubernetes returns 406. Record that as a capability result and switch to full objects, skip the resource, or surface configuration error according to policy. Do not retry the same Accept header indefinitely or classify 406 as a transient network failure.
4. Handle aggregated APIs and CRDs
Built-in APIs generally support metadata-only responses, but an API behind aggregation may not. CRD and third-party implementations can also expose only full objects. Probe capabilities by resource and server, cache the result with expiry, and never generalize one resource's success to every resource.
5. Preserve list/watch consistency
The list resourceVersion remains the starting point for the watch. Save it, handle expiry, disconnects, and relist, and remember that metadata-only changes representation rather than resource-version semantics. A full-object fallback must use the same version to populate the cache, avoiding stale mixed data.
6. Design cache and upgrade behavior
Cache entries should record representation and field availability. A path that needs spec must not assume it exists in a metadata-only entry; issue a controlled full GET by name. Re-probe Accept capability after upgrading a server or proxy so a needless full-object path does not remain forever.
7. Measure cost and security
Compare request bytes, decode CPU, heap peak, list latency, watch reconnect rate, and full-GET ratio. Labels, annotations, and owner references can still contain sensitive data; authorization does not disappear because only metadata is returned. Avoid dumping every annotation into logs and metrics.
A high-quality sample answer
I would prefer PartialObjectMetadataList and include lower-quality normal JSON as fallback. The client validates the returned kind and performs one capability switch on 406. It starts a watch from the list resourceVersion and records field availability in cache. Aggregated APIs, CRDs, and paths needing spec get separate probes and reads, while bytes, CPU, memory, and reconnect metrics prove the benefit.
Common mistakes
- Using the single-object
PartialObjectMetadataparameter for a list. - Treating metadata-only as arbitrary server-side field filtering and ignoring response kind.
- Treating 406 as a retryable 5xx when no fallback was offered.
- Assuming in-tree capability applies to aggregated APIs or every CRD.
- Dropping list
resourceVersionand restarting watch from the wrong point. - Measuring response size without decode CPU, heap peak, or reconnect cost.
Follow-up questions and answers
Why use PartialObjectMetadataList for a list?
A collection request returns a list representation, and PartialObjectMetadataList explicitly says each item contains metadata only. The single-object form is for one GET; the client should not mix them and guess.
What if the server does not support partial responses?
With normal JSON as a lower-quality fallback, inspect the response kind and use the full object. In strict mode, record 406 as missing capability and skip or fail according to resource policy. Do not retry forever.
Does metadata-only change resourceVersion?
No. It changes representation, not resource-version semantics. The list version still anchors the watch and cache consistency.
Do all CRDs support this request?
Do not assume so. Aggregated APIs and CRDs may not implement partial representations; probe and cache capability per resource.
When must you read the full object?
When a decision needs spec, status, or another business field. Use metadata to build an index, then trigger a controlled full GET by name or event.