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
Regression: Watching without resourceVersion fails #13809
Comments
|
Current behavior against today's master 6a5049f Expected behavior: |
|
Looking to see if I can find where the regression occurred... |
|
This issue appears to be related to introducing the watch_cache https://github.com/kubernetes/kubernetes/blob/master/pkg/storage/watch_cache.go#L253 fyi @wojtek-t |
|
I think the fix is to change https://github.com/kubernetes/kubernetes/blob/master/pkg/storage/watch_cache.go#L253 and special case for resourceVersion==0 scenario |
|
Yes - I talked with @lavalamp and he said that we don't want to support it. If we want, I'm happy to fix that (it should be few lines of code). |
|
or even you can take sth like "newest" (instead of oldest) - I think that "oldest" might be too old. |
|
@wojtek-t - the code I outlined above works in my tests (Cockpit UI is now happy)... what do you mean by we do not want to support it? It seems like we should support absence of a resource version in the same manner as etcd, no? In the snippet above, oldest defaults to w.resourceVersion which I thought is last version it has seen in the cache? |
|
"oldest" is kind of "first" (it's the oldest). So yes - it works, but it might be too old (so I would do the newest one). |
|
by "too old" I mean that we may unnecessary read to many data, because we're mostly interested in the "~ current" state |
|
I must be dense, but I read this as meaning current state: https://github.com/kubernetes/kubernetes/blob/master/pkg/storage/watch_cache.go#L74 And oldest defaults to w.resourceVersion where I did the check. If you can give an alternate fix I would be happy to review. it looks like cache_test.go complains when we special case resourceVersion==0 so it ends up being about 10 lines of code ;-) |
|
I'm OOO tomorrow, so I'm happy with your fix for now. I can change it on Monday, |
|
Ok, will open PR. |
|
[if that's urgent] |
|
@stefwalter How were you using that "feature"? I don't think it's possible to use it safely? |
|
IMO, it was broken in v1 that you could do that at all. |
|
I wondered about that... would you get the full history of the resource when watching with no resource version? |
|
We can't give the full history, and you have no idea at what point in the history we'd start. Certainly no automated system should be watching without a defined starting point. |
|
In "v1" there is no guarantee what will be returned if pass resourceVersion=0 (it basically starts with "now" which is not very well defined). |
|
@lavalamp - my understanding is that watch with no resource versoin should be equivalent to get me latest state, not full history. |
|
Yes, Cockpit gets the latest state with /watch and then keeps the connection open to receive updates. It only uses resourceVersion=X when the /watch disconnects, and it needs to pick up the /watch=resourceVersion=X from where it left off. To summarize, we're not looking for history. We're looking for latest state ... and then wait for updates behavior. This is in use against kubernetes 1.0 in released products. Hence this is a regression. |
|
@stefwalter You should list first. Otherwise you have no way of knowing when you end up with a complete state. |
|
@lavalamp - it seems like there is a difference in calling /watch/api/v1/nodes vs /watch/api/v1/nodes?resourceVersion=0 I think absence of a resourceVersion should default to latest state. It seems sensible to me to let a client make one call instead of two. |
Cockpit is a UI that tracks the state of Kubernetes live on the fly. We have no need to determine when we have a "complete" state. In fact on a moderatly active kubernetes cluster ... it is meaningless to talk about a "complete" state. |
|
To clarify: kubernetes 1.0 would list all objects with MODIFIED at the start of a /watch without resourceVersion. |
|
@derekwaynecarr Yeah, IMO |
|
@stefwalter Are you using this for single objects or multiple objects? |
Multiple simultaneous watches each for multiple objects like |
|
If your UI is view-only, it probably doesn't matter. But if you offer operations like "do x to all the pods" or "do X with all the pods" or "send all the pods to the frobber"-- you basically have no way of safely doing those operations, at least not with the objects you got from the watch. I am very reluctant to have us do things to enable the old behavior to continue, because the above error is very subtle and I don't want to keep it easy for people to misuse. @bgrant0607 Must we continue to support resourceVersion-less watches? Do you consider that a breaking change to v1? I consider it an undocumented feature that we ran out of time to remove (aka bug) and therefore think that it should be acceptable to remove from v1. @smarterclayton may also have an opinion. |
Any client doing write operations already has to handle cases where the state of the world changed between the time they received a watch event and when they made another API call acting on the watch event's object. If they are handling NotFound and Conflict errors correctly, how would this be unsafe? |
|
Yes @liggitt, a client's best hope is that their view will eventually converge. Short of kubernetes providing a way to 'lock the cluster' (heh) there never a way to know you're seeing or acting on all pods or other any other sort of item. In any distributed environment, the aim is to get things to converge and not to imagine that things are consistent at any given point. The v1 watch behavior allows us to do half the number of HTTP requests, and have a simpler client. For example, instead of 30 requests, we only do 15. Remember that Kubernetes does not provide a way to watch multiple kinds in a single watch, therefore the number of watches a client will have open can be quite high. Lastly, even if kubernetes chooses to change the v1 watch behavior in a v2 API (which I would be against due to the reasons above) ... it's still part of the v1 behavior. Kubernetes shouldn't regress the v1 API or consumers of that API. |
Different use cases, depending on what you are doing with the objects in the watch stream. My use case involved building a store and querying against it, so knowing when the initial list was complete mattered. If you're just processing one object at a time, the watch stream is enough... when you get a watch event about a resource, you know about it then. |
|
@stefwalter Even in eventually-consistent situations, there's still a need to deterministically act on every object in a collection, process every change, or update some downstream state. You can't know that you've e.g. "acted on every pod", because that's not well defined. But you can know that you've "acted on every pod as of revision 2348". |
|
I think it's a breaking change - it was definitely an intentional part of It's not the perfect pattern for everyone, and it can be emulated in the On Sep 10, 2015, at 3:19 PM, Daniel Smith notifications@github.com wrote: If your UI is view-only, it probably doesn't matter. But if you offer I am very reluctant to have us do things to enable the old behavior to @bgrant0607 https://github.com/bgrant0607 Must we continue to support @smarterclayton https://github.com/smarterclayton may also have an — |
|
I just think I expect this to map to etcd watch mental model. If I do I get the equivalent of LIST(currentstate)+(wait for updates) When we moved to watch_cache.go pattern, we broke this pattern. Seems like a bug. |
|
OK. I still think it's dangerous, but I think I'm outvoted here. |
|
I agree with @lavalamp that it's dangerous. |
|
#13910 sent out for review |
|
I want to augment my previous stmts: etcd: Response ONLY includes modifications made AFTER request was initiated. kube-1.0.6 Response has MODIFIED records for existing resources made BEFORE request was initiated, and then all subsequent WATCH events after request was initiated Call-chain ultimately leads this path to where we do a LIST and then convert the initial data in the path to a list of MODIFIED events kube-1.1 Error Summary Seems for v1 API if we want to preserve backward compatibility, we need to do the same. |
|
If it worked before, we can't take it away from the v1 API. |
|
Agree - the PR is already sent out for review. |
At some point after kubernetes 1.0 watching without a resourceVersion has broken. This is a v1 API regression.
The text was updated successfully, but these errors were encountered: