-
Notifications
You must be signed in to change notification settings - Fork 882
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
Cleanup interfaces properly when vxlan plumbing fails #1800
Conversation
Signed-off-by: Santhosh Manohar <[email protected]>
@@ -601,6 +618,9 @@ func (n *network) initSubnetSandbox(s *subnet, restore bool) error { | |||
} | |||
} else { | |||
if err := n.setupSubnetSandbox(s, brName, vxlanName); err != nil { | |||
// The error in setupSubnetSandbox could be a temporary glitch. reset the | |||
// subnet once object to allow the setup to be retried on another endpoint join. | |||
s.once = &sync.Once{} |
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.
This makes sense for initSubnetSandbox. How does the restore path work ?
I have to spend some time analyzing that as well to confirm if this change is complete.
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.
@sanimej Reviewing the restore path, I think if restoreSubnetSandbox
fails for any reason, I think we will end up in the same issue.
And the current fix will not help, because your changes currently performs deleteInterface
for vxlan device only if AddInterface
fails. But if the restoreSubnetSandbox
fails, then the failure will happen in createVxlan
call and there is no recovery for that.
Do you think it is valid ?
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.
@mavenugo The way restore works is fundamentally different. For the restore case we do handle something similar, but at the network level; https://github.com/docker/libnetwork/blob/master/drivers/overlay/overlay.go#L99
Going strictly by the code, yes, restoreSubnetSandbox
can also fail. But all the recent issues reported for this error are in swarm mode (ie: not the restore code path). For the restore
case we have to try with a forced error and verify things end to end. It belongs in a separate PR.
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 agree. Thanks.
not super familiar with this part of the code, but the fix looks reasonable to me |
polite bump for @mavenugo~ Any particular reason this has been sitting [seemingly] approved but unmerged for so long? |
@selansen can you take over this patch? |
Will do that. |
Reviewed this, and it looks mostly ok to me. But I am a bit nervous about the "re-once"ing. (i.e. assigning a new |
I think there is a race here. Assume that 2 goroutines are trying to join the network at the same time. The first one gets in and hits the "once" and starts spinning things up but fails. On the way out (but not completely out) it resets the "once". Now the second goroutine joins the sandbox and succeeds, going through the once and back out again before the first goroutine returns from initSubnetSandbox(). it assigns a 'nil' to the subnet.initErr field because it succeeded. Then the first goroutine completes and assigns its error to subnet.initErr. Subsequent goroutines will all get the wrong initErr as a result. This is probably not likely to happen because there aren't blocking calls between reinitializing the "once" and setting the initErr field. But one should never rely on things like this. |
Having thought through this and reviewed sync.Once for loopholes and the like, I think the options are either to accept as is, or use a pattern like:
I don't see any way of re-oncing that is clean. |
carried by #2146 |
Related to #1765
There have been many reports of container creation failing with "Error creating vxlan: file exists" error. This happens very randomly (but typically after lot of stack deploy/rm) without a specific sequence to recreate the issue.
I haven't been able to recreate it either. But with a forced error I can hit this issue. When setting up the overlay network we create a separate namespace for the overlay network, create a vxlan device and move it into the overlay namespace and configure it (interface name for ex). If something goes wrong here vxlan interface wasn't getting cleaned up properly. If that network is delated, another network could get its vni id. Since an orphaned interface exists with that vni id, new vxlan device can't be created.
Changes in this PR does proper cleanup of the vxlan interface and the overlay namespace on any failure so that subsequent attempts or another network which gets the same vxlan id can succeed.
Signed-off-by: Santhosh Manohar [email protected]