-
-
Notifications
You must be signed in to change notification settings - Fork 313
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Shareable Controller
stream interfaces
#1189
Comments
I think I'm running into this problem now, as I'm trying to use a |
Hey @louismrose. I am still not sure which one works out to be the best. Ideally, a PoC for 2 would really help disambiguate the problem space because that is the most breaking change, and it would help us get a feel for whether it is a justifiable one. If it isn't justifiable, then we can probably do 1 or 3 pretty easily at the cost of some user ergonomics. |
I'd be happy to try and get a PoC for 2 if that helps, unless someone else wants to try their hand in which case I'm fine with stepping aside :) |
No one else has jumped at this for two months so I'd say go for it @mateiidavid :-) |
Thanks @mateiidavid. I had a quick attempt at this, but it's a bit beyond my level of Rust at the moment! |
@mateiidavid did you get anywhere with this? :D |
@clux thanks for the nudge. My progress has been slow :( It's been a few busy weeks at work and I struggled to find the time for it. I know you're all probably eager to see this through. My motivation didn't waver tho and I'm still committed to getting this done; give me a few more days to fully mobilise and I'll get something written up here. |
Hehe, that's great. DW, just checking in :-) |
Just to give you an update, I've been making some progress here. Trying to get solution number (2) to work since big object stores & the associated memory pressure are actually the bane of my existence now. I have some additional motivation in the tank to do this as efficiently as possible. It's a bit harder than I expected, but so far (2) seems to also imply (1). Here's an overview:
Wiring up the What I'd ideally like to do is get a branch to look at the diff and then think things through in terms of where things can go wrong. Keep ya all posted. Update: Okay, so I got it to pass Update 2: ugh, seems like the subscribe interface wraps the entire event in an arc, will have to make some changes to the branch. Update 3: Arc'd output from watchers and again fell in the trap of not checking the subscribe signature 🙃 it seems like the subscriber adapter actually Arcs the results. We could probably arc the results in the watcher as well and propagate that upstream. We'd have to change the subscriber interface to take in a stream that's already Arc'd and avoid cloning if we want to share watcher streams, presumably? imo having the watcher use |
A fourth potential avenue was brought up in the meeting yesterday:
This could be an easier, approach since the With a store-stream approach (if it works out) users could still have the option to memory prune before going into the store, but have many users pull copies from the store into the controller. |
Arc
wrap watcher
and/or Controller
stream interfacesController
stream interfaces
Would you like to work on this feature?
Maybe
What problem are you trying to solve?
As a final step to allow stream sharing #1080 we need to allow
StreamExt::stream_subscribe
output to be able to be passed into the controller streams interfaces:Controller::for_stream
Controller::watches_stream
Controller::owns_stream
Which currently is not possible because
StreamExt::stream_subscribe
producesStream<Item = Result<Arc<K>, Error>>
, but the input streams are normal watche streams of the formStream<Item = Result<K, Error>>
.Arc wrapping can help reduce memory consumption + reduce awkward arc wrap points:
Controller
before calling out to thereconcile
anderror_policy
fns anywayDescribe the solution you'd like
We need the streams that
watcher
produces to ultimately end up with equal types for both the subscribepath and the non-subscribe path. Options are considered below, but personally, I think that if it's viable, we should experiment with arc-wrapping earlier.Describe alternatives you've considered
1. Always
Arc
wrap output fromEventFlatten
Arc wrap once it's intended to be consumed; when it's flattened (
::applied_objects()
or::touched_objects()
). It's late enough that it won't really affect any store implementations, and it will work with::stream_subscribe
.While this is less breaking than the suggestion below, it also creates another copy of the object; as each
Store
is cloning:kube/kube-runtime/src/reflector/store.rs
Lines 54 to 69 in c30b376
2. Always
Arc
wrap output fromwatcher
A much more fundamental change to our api, but it will provide a much more consistent api, and possibly clone less huge k8s objects while passing through streams.
If we do it this deep, then we basically add it to
step_trampolined
where the objects are handled first:kube/kube-runtime/src/watcher.rs
Lines 371 to 472 in c30b376
This has the potential to help reduce cloning between streams and reflectors. Given reflector stores and Kubernetes objects account for most of the memory usage of typical rust controllers, this could be a worthwhile avenue.
However, not sure if this is a practical solution.
3. Internally
Arc
withArc
wrapper helper forWatchStreamExt
WatchStreamExt::arc
(or something like that) to map the OkK
elements to anArc<K>
.Controller
, call::arc
on all managed streams::arc()
call to be compatibleFairly simple. Just propagate the
Arc
insideController
only, and do it at an earlier point.This does not solve memory issues with
Store
, and it puts the onus on the user to figure out when to arc-wrap or not.Documentation, Adoption, Migration Strategy
Examples, doc tests, kube.rs controller guide updates where relevant.
I suspect this can be done in a mostly non-disruptive way. We have arc-wrapped a bunch of things in the past, and it's generally been a good idea.
Target crate for feature
kube-runtime
The text was updated successfully, but these errors were encountered: