-
Notifications
You must be signed in to change notification settings - Fork 9.8k
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
clientv3: correct nextRev
on receiving progress notification response
#15248
Conversation
cc @mitake |
Codecov Report
📣 This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more @@ Coverage Diff @@
## main #15248 +/- ##
==========================================
- Coverage 74.94% 74.76% -0.18%
==========================================
Files 416 416
Lines 34351 34352 +1
==========================================
- Hits 25744 25683 -61
- Misses 6981 7029 +48
- Partials 1626 1640 +14
Flags with carried forward coverage won't be shown. Click here to find out more.
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
Not sure what's the purpose of this change. Bumping revision to handle manual progress request might have an adverse effect of confusing the client. I it would be better if client just hard failed and refuse to handle invalid response from server (panic, return error or reset watch). |
Note I am still in progress of debugging this issue, just marked the PR as draft. |
57b829a
to
a9b508c
Compare
watchRequest.rev
from decreasing due to RequestProgress issuenextRev
on receiving progress notification response
It turns out to be a clientv3's issue. When the clientv3 receives a progress notification response, it sets Let's work with an example,
Note that it's pretty easy to reproduce this issue using #15235. After applying this PR, it can't be reproduced anymore. We need to backport this PR to both 3.4 and 3.5. @mitake @ptabor @serathius PTAL. |
@wojtek-t does this issue have any impact on K8s? |
@ahrtr As we have established, K8s doesn't use manual progress notify so it's not affected. |
This isn't correct. Both manual progress notification and timed progress notification have this issue. Note that it can only happen when etcdserver restarts ( Could you evaluate the impact on K8s? cc @wojtek-t @dims @liggitt @nikhita @neolit123 |
@@ -880,12 +880,13 @@ func (w *watchGrpcStream) serveSubstream(ws *watcherStream, resumec chan struct{ | |||
} | |||
} else { | |||
// current progress of watch; <= store revision | |||
nextRev = wr.Header.Revision | |||
nextRev = wr.Header.Revision + 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't read this code deeply... but please make sure the 'fragment' field is properly interpreted:
etcd/api/etcdserverpb/rpc.proto
Line 835 in 586eacc
bool fragment = 7 [(versionpb.etcd_version_field)="3.4"]; |
I assume that in case of fragmented response, there might be multiple responses with the same revision.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a good question. The fragments have already been merged before the merged response being dispatched to the serveSubstream
. The rough workflow is as below,
- Firstly the client side merges all fragments if needed. See watch.go#L644-L648;
- dispatch the response. See watch.go#L651;
- The
serveSubstream
forwards the response to the subscriber. See watch.go#L845;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Er... this is going to break Kubernetes, which manually does this already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed, please don't change the meaning of the data returned to offset by one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually this change may be correct -- look at line 887, which is the normal case. It adds one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, if this doesn't change the revisions returned to clients
Right. It doesn't change anything being returned to client (again, etcd clientv3's user.
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect test changes to come in the same PR as the fix -- like did this not break any unit tests? That would be very surprising. (but I'm not familiar with etcd practice)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect test changes to come in the same PR as the fix -- like did this not break any unit tests? That would be very surprising. (but I'm not familiar with etcd practice)
Right. I am planning to add a test case today.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking to depend on the generic linearizablity test case, but it seems it makes more sense to add a specific test case to reproduce this issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That there isn't a unit test exercising this line is probably most of the problem...
First of all, please make sure if you need any clarification to the example workflow I mentioned in #15248 (comment). If it's clear to you, then I suppose it's pretty easy to intentionally create the scenario. To avoid any confusion, please see #15262, please only read the third commit.
Please see my local reproduction.
|
To give all people more confidence, I also manually reproduced this issue against
The steps are:
|
It's also reproduced on etcd 3.5.7. Is this a big problem to K8s? @liggitt |
a9b508c
to
283d0df
Compare
Signed-off-by: Benjamin Wang <wachao@vmware.com>
283d0df
to
3ca4700
Compare
Added an integration test case. Without the fix in this PR, the test case always fails. After applying the fix, the test case always succeeds. It's pretty sure it fixes the duplicated event issue . |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
With the integration test it's clear that there was a bug here. Thanks for going additional mile.
Any inclination what is missing in linearizability test that prevented reproducing this? I expect that we didn't have as it's etcd failing scenario that is not as well covered by integration/e2e tests.
Failure injection is domain of functional/linearizability tests, so I would like to identify why we didn't reproduce it that way.
umm... I'm trying to think how bad repeating the latest event in a watch stream could be... it's definitely not as bad as replaying non-latest historical events. It could definitely confuse a watcher that was taking action on observing transitions and didn't expect to see the same transition occur two times, but a quick sweep didn't turn up any obvious issues with in-tree watchers in kubernetes (we almost universally work on the latest observed object from a locally maintained cache, and replaying the latest event doesn't break that). for this scenario to occur, would all of these would have to happen:
|
The linearizability test is sort of generic test, I don't surprise that it can't reliably reproduce this issue. It's exactly the reason why I implemented a dedicated integration test for this issue. For more details, please refer to #15248 (comment) and the third commit in #15262
Yes, it only replay the latest event.
Exactly! |
Thanks @liggitt for the feedback. |
FYI Linearizability tests have reproduced the issue the even after the fix was merged! Run https://github.com/etcd-io/etcd/actions/runs/4142560023/jobs/7163370423 From run actions/checkout
From logs
|
@serathius Do you mean they reproduced the bigger issue of #15271 or something else ? |
I saw similar error message with the help of #15272. Do not get time to dig into it so far. It isn't confirmed that whether it's a test issue or production issue for now. Will take a deep dive later. |
It's my top priority next week. |
It's totally a different beast as they have different failpoint triggers. |
The manual ProgressRequest has issue, it may send inconsistent rev back to client. We should guard the
watchRequest.rev
from decreasing, otherwise, the client may receive duplicate events.Confirmed that this PR can fix the duplicated event issue.
Signed-off-by: Benjamin Wang wachao@vmware.com
Please read https://github.com/etcd-io/etcd/blob/main/CONTRIBUTING.md#contribution-flow.