Skip to content

Commit dccaa7e

Browse files
committed
KEP 3157 (watch-list): replacing standard List request with WatchList mechanism for client-go's List method.
1 parent 7e1c131 commit dccaa7e

File tree

1 file changed

+67
-0
lines changed
  • keps/sig-api-machinery/3157-watch-list

1 file changed

+67
-0
lines changed

keps/sig-api-machinery/3157-watch-list/README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,73 @@ Then on the server side we:
581581
3. reject the request if waitUntilFreshAndBlock times out, thus forcing informers to retry.
582582
4. otherwise, construct the final list and send back to a client.
583583

584+
### Replacing standard List request with WatchList mechanism for client-go's List method.
585+
586+
Replacing the underlying implementation of the List method for client-go based clients (like typed or dynamic client)
587+
with the WatchList mechanism requires ensuring that the data returned by both the standard List request and
588+
the new WatchList mechanism remains identical. The challenge is that WatchList no longer retrieves the entire
589+
list from the server at once but only receives individual items, which forces us to "manually" reconstruct
590+
the list object on the client side.
591+
592+
To correctly construct the list object on the client side, we need ListKind information.
593+
However, simply reconstructing the list object based on these data is not enough.
594+
In the case of a standard List request, the server's response (a versioned list) is processed through a chain of decoders,
595+
which can potentially modify the resulting list object.
596+
A good example is the WithoutVersionDecoder, which removes the GVK information from the list object.
597+
Thus the "manually" constructed list object may not be consistent
598+
with the transformations applied by the decoders, leading to differences.
599+
600+
To ensure full compatibility, the server must provide a versioned empty list in the format requested by the client (e.g., protobuf representation).
601+
We don't know how the client's decoder behaves for different encodings, i.e., whether the decoder actually supports
602+
the encoding we intend to use for reconstruction. Therefore, to ensure maximal compatibility, we will ensure that
603+
the encoding used for the reconstruction of the list matches the format that the client originally requested.
604+
This guarantees that the returned list object can be correctly decoded by the client,
605+
preserving the actual encoding format as intended.
606+
607+
The proposed solution is to add a new annotation (`k8s.io/initial-events-list-blueprint`) to the object returned
608+
in the bookmark event (The bookmark event is sent when the state is synced and marks the end of WatchList stream).
609+
This annotation will store an empty, versioned list encoded as a Base64 string.
610+
This annotation will be added to the same object/place the `k8s.io/initial-events-end` annotation is added.
611+
612+
When the client receives such a bookmark, it will base64 decode the empty list and pass it to the decoder chain.
613+
Only after a successful response from the decoders the list will be populated with data received from subsequent
614+
watch events and returned.
615+
616+
For example:
617+
```
618+
GET /api/v1/namespaces/test/pods?watch=1&sendInitialEvents=true&allowWatchBookmarks=true&resourceVersion=&resourceVersionMatch=NotOlderThan
619+
---
620+
200 OK
621+
Transfer-Encoding: chunked
622+
Content-Type: application/json
623+
624+
{
625+
"type": "ADDED",
626+
"object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "8467", "name": "foo"}, ...}
627+
}
628+
{
629+
"type": "ADDED",
630+
"object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "5726", "name": "bar"}, ...}
631+
}
632+
{
633+
"type":"BOOKMARK",
634+
"object":{"kind":"Pod","apiVersion":"v1","metadata":{"resourceVersion":"13519","annotations":{"k8s.io/initial-events-end":"true","k8s.io/initial-events-embedded-list":"eyJraW5kIjoiUG9kTGlzdCIsImFwaVZlcnNpb24iOiJ2MSIsIm1ldGFkYXRhIjp7fSwiaXRlbXMiOm51bGx9Cg=="}} ...}
635+
}
636+
...
637+
<followed by regular watch stream starting>
638+
```
639+
640+
## Alternatives
641+
642+
We could modify the type of the object passed in the last bookmark event to include the list.
643+
This approach would require changes to the reflector, as it would need to recognize the new object type in the bookmark event.
644+
However, this could potentially break other clients that are not expecting a different object in the bookmark event.
645+
646+
Another option would be to issue an empty list request to the API server to receive a list response from the client.
647+
This approach would involve modifying client-go and implementing some form of caching mechanism,
648+
possibly with invalidation policies.
649+
Non-client-go clients that want to use this new feature would need to rebuild this mechanism as well.
650+
584651
### Test Plan
585652
<!--
586653
**Note:** *Not required until targeted at a release.*

0 commit comments

Comments
 (0)