Skip to content
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

Add network restore to support docker live restore container #1244

Merged
merged 7 commits into from
Jun 14, 2016
Merged

Add network restore to support docker live restore container #1244

merged 7 commits into from
Jun 14, 2016

Conversation

aboch
Copy link
Contributor

@aboch aboch commented Jun 11, 2016

This is an extract from #1135 retaining the changes in libnetwork core to support the network restore, with few modifications:

  • network drivers state restore not controlled by libnetwork
  • so no changes to driverapi
  • active sandboxes passed via config option
  • no change to controller.New() input and return params

Plus other commits which bring the endpoint persist logic to the existing network drivers and which reserve with the ipam driver the addresses of the existing local endpoints.

Note: this change has the advantage it can be merged irrespective of docker side changes

@coolljt0725 changes in overlay driver to restore the osl sandbox will be pushed as part of a separate commit.

Signed-off-by: Lei Jitang [email protected]
Signed-off-by: Alessandro Boch [email protected]

@aboch
Copy link
Contributor Author

aboch commented Jun 12, 2016

Corresponding changes to @coolljt0725 docker/docker commit can be found at https://github.com/aboch/docker/commit/5f3a9a7f2ed5df06aca88a28ac26ca59a9486069:

  • daemon to pass active sandbox list along with options via SandboxOption
  • do not modify sandbox port mapping config on restore

@@ -198,7 +201,7 @@ func (c *controller) sandboxCleanup() {
dbExists: true,
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aboch let's do

// restore sb.config
 sb.processOptions(option...)
 sb.restorePath()

here
instead of at https://github.com/docker/libnetwork/pull/1244/files#diff-ffc9c06e306285f214919ed203907012R707
because sb.Key() relay on sb.config.useDefaultSandBox
I had this change on local but forget to push to github in time :)

Copy link
Contributor Author

@aboch aboch Jun 12, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I am refactoring that code. I am now restoring in cleanupSandboxes()
Thanks for the suggestion

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aboch nice refactor :)

@coolljt0725
Copy link
Contributor

@aboch should we also rename the defaultScopes https://github.com/docker/libnetwork/blob/master/datastore/datastore.go#L134?
Once this pr is merged, the host and none network is persist to local db, if we downgrade the docker version, the the daemon will failed to start on creating host and none because we doesn't check if host and none exist before creation host and none.

@chenchun
Copy link
Contributor

controller.go.orig should be deleted.

@aboch
Copy link
Contributor Author

aboch commented Jun 12, 2016

@coolljt0725 AFAIK host and none network are not saved to store. Maybe I missed where this got enabled.

@aboch
Copy link
Contributor Author

aboch commented Jun 12, 2016

@chenchun yes

@coolljt0725
Copy link
Contributor

@aboch
Copy link
Contributor Author

aboch commented Jun 12, 2016

@aboch host and none network are enabled to save to store in daemon side
aboch/docker@5f3a9a7#diff-b56258ecab11f7b797306907327cc904R605

Ah, thanks @coolljt0725 That needs attention. Will think about it tomorrow.
Actually it could be fine, id will be unique, there isn't and there wasn't any check for existance by name in libnetwork or in docker/docker before creating null and host networks, if I have not missed that as well.

@@ -1009,6 +1012,10 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
}
}

if err := d.storeUpdate(endpoint); err != nil {
logrus.Warnf("Failed to save bridge endpoint %s to store: %v", ep.id[0:7], err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we return error here given we will invoke necessary rollback functions on error ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The roll-back function should not be invoked given the if scope of err.
I do not want to fail the container start if we cannot save it to the bridge store.
The container may not even live long enough to go through a daemon reload.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a problem in failing the operation if the storeUpdate fails ?
I think that will be consistent with other store failures in the create path.
(Its understandable that we can warn on Delete - since there is no recovery path).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can fail, just that we will fail even if the user did not start the daemon with the restore flag.
Anyhow, I think that if the save to store fails for this, it would fail for many others, so I do not think the system would be usable anyway. I will make the change.

@coolljt0725
Copy link
Contributor

some test cases about this on daemon side is moby/moby@4cfcd60, I'll add more test cases tomorrow. I'm busy today and got no time to test this and look into this, I'll do this tomorrow.

// TODO: Do we need this change ?
// check if the rule exists
var (
doCheck bool
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coolljt0725 Do you think we still need this change ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aboch This is not need any more since we will remove the iptables during bridge driver initialization in https://github.com/docker/libnetwork/blob/master/drivers/bridge/bridge.go#L381

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, that's what I thought. Thanks for confirming.

@mavenugo
Copy link
Contributor

@aboch overall I think the refactor has simplified the interactions. Yes, it adds the states to the store. I guess that is okay given the requirement.

@coolljt0725 wdyt ?

@coolljt0725
Copy link
Contributor

@mavenugo I'm agree with this refactor. it's much more simple 👍

@mavenugo
Copy link
Contributor

@coolljt0725 Please let us know if you got a chance to test this out and / or added more test cases

@sanimej
Copy link

sanimej commented Jun 13, 2016

restoring the overlay network sandbox has some issues. After daemon restart starting another container on an existing network fails. Will update the PR when its addressed.

@sanimej
Copy link

sanimej commented Jun 13, 2016

@aboch For overlay networks, after a daemon restart I was getting this error when starting a new container..

could not add veth pair inside the network sandbox: error setting interface "veth93e7d95" master to "br": Device does not exist

This was a because of a bug if the osl sandbox restore logic. Its a one liner..

sanimej@fccee4c

You can make this change in the overlay commit included in the PR

@aboch
Copy link
Contributor Author

aboch commented Jun 13, 2016

Thanks @sanimej will update shortly

@coolljt0725
Copy link
Contributor

@mavenugo working on it :)

sb.isStub = false
isRestore = true
opts := val.([]SandboxOption)
sb.processOptions(opts...)
Copy link
Contributor

@coolljt0725 coolljt0725 Jun 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing sb.restorePath() here, this will cause docker network connect /disconnect failed on old running container
docker network connect foo 882d7eb8a982 Error response from daemon: rename /var/lib/docker/containers/882d7eb8a982986ac37d75dc2ca5fe18cc0cdc37c8307124de73aace68954362/hash708549390 : no such file or directory

Copy link
Contributor Author

@aboch aboch Jun 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Verified.

@coolljt0725
Copy link
Contributor

coolljt0725 commented Jun 13, 2016

The daemon tests case for networking restore is coolljt0725/docker@52d5507
the test cases cover bridge host none network mode, and docker network connect/disconnect, and docker stats , embed dns. All these tests passed with commit sanimej/libnetwork@fccee4c and change in comment https://github.com/docker/libnetwork/pull/1244/files#r66754900
the ipvlan , macvlan and overlay doesn't cover.
I'll test these driver manually

if key == "" {
return fmt.Errorf("failed to find old sandbox key %s", osl.GenerateKey(fmt.Sprintf("%d-", n.initEpoch)+n.id))
}
sbox, nerr := osl.NewSandbox(key, false, true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be osl.NewSandbox(key, true, true)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.

@coolljt0725
Copy link
Contributor

overlay work for me with commit sanimej/libnetwork@fccee4c and change in comment https://github.com/docker/libnetwork/pull/1244/files#r66786053

I'll test ipvlan and macvlan tomorrow

@mavenugo
Copy link
Contributor

@aboch @coolljt0725 @sanimej thanks a lot for reducing the complexity and making it clean/modular. 👍

LGTM

@coolljt0725
Copy link
Contributor

@sanimej I got this error Could not open netlink handle during vni population for ns /var/run/docker/netns/2-3e0a937d28: failed to set into network namespace 23 while creating netlink socket: invalid argument when I try to start a container with overlay network, but it works fine yesterday.
am I missing something?

ifaceOptions[j] = append(ifaceOptions[j], sb.osSbox.InterfaceOptions().MacAddress(i.mac))
}
Ifaces[fmt.Sprintf("%s+%s", i.srcName, i.dstPrefix)] = ifaceOptions[j]
if joinInfo != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing LinkLocalAddresses?

Copy link
Contributor Author

@aboch aboch Jun 14, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saw this, but it is not really needed. FWIW only i.addr is needed as it is being evaluated during the restore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, I added the link-local addresses. Thanks.

@coolljt0725
Copy link
Contributor

one more thing I concern about is shall we pass the active endpoints to driver on driver initialization so that we can clean up used driver endpoints?
the driver endpoints and the sandbox endpoints are stored separate, if daemon shutdown ungracefully, the driver endpoints and the sandbox endpoints could not be consistent, so it may cause fail to delete network with ActiveEndpointsError.

@mavenugo
Copy link
Contributor

@coolljt0725 ActiveEndpointsError will be seen ONLY if the libnetwork core endpoint is left stale in the store. It will not be impacted by driver states.

Also, as you know, the libnetwork core performs stale endpoint and sandbox cleanup on bootup and also makes sure that the driver endpoint states are cleaned up (via the deleteEndpoint call) before cleaning up its own states. Hence, the cleanup functionality at bootup should handle the stale endpoint issues for ungraceful restart scenarios.

Do you see it behaving otherwise ? Did you hit the ActiveEndpointsError due to this change ?

@aboch
Copy link
Contributor Author

aboch commented Jun 14, 2016

@coolljt0725 Agree with @mavenugo, libnetwork endpoint removal from store will happen only if driver endpoint removal has succeeded. And libnetwork core will perform stale endpoint removal at each boot. So this ensures we won;t end up in acase where drivers has stale endpoints but libnetwork does not.

@aboch
Copy link
Contributor Author

aboch commented Jun 14, 2016

@sanimej I got this error Could not open netlink handle during vni population for ns /var/run/docker/netns/2-3e0a937d28: failed to set into network namespace 23 while creating netlink socket: invalid argument when I try to start a container with overlay network, but it works fine yesterday.
am I missing something?

@coolljt0725 I have not seen this problem and I have tested several cases in overlay. Given few changes/refactoring have happened, make sure to start from a clean state.

I updated https://github.com/aboch/docker/commits/rst with the latest changes and add the --live-restore commit changes.

Did you do anything special or just start a container on overlay network after a daemon restart ?

@coolljt0725
Copy link
Contributor

@mavenugo @aboch no, I didn't hit this error for now, just my concern :)
you explanation make it clear 👍

@coolljt0725
Copy link
Contributor

coolljt0725 commented Jun 14, 2016

@coolljt0725 I have not seen this problem and I have tested several cases in overlay. Given few changes/refactoring have happened, make sure to start from a clean state.
I updated https://github.com/aboch/docker/commits/rst with the latest changes and add the --live-restore commit changes.
Did you do anything special or just start a container on overlay network after a daemon restart ?

I just can't run a container with a overlay network without daemon restart
I'll try again with https://github.com/aboch/docker/commits/rst

@sanimej
Copy link

sanimej commented Jun 14, 2016

@coolljt0725

I got this error Could not open netlink handle during vni population for ns /var/run/docker/netns/2-3e0a937d28: failed to set into network namespace 23 while creating netlink socket: invalid argument when I try to start a container with overlay network, but it works fine yesterday.

I didn't see this error in my testing.

I just can't run a container with a overlay network without daemon restart

Do you mean containers work after a daemon restart ? If you didn't see it before and it happens now it could be because of the new changes.

Can you try from a clean state and with a new network ?

@coolljt0725
Copy link
Contributor

coolljt0725 commented Jun 14, 2016

@sanimej when I reboot my system and also delete the old states, it worked :)
@aboch @mavenugo for now, the overlay , ipvlan macvlan also work for me. so LGTM 👍

@icecrime
Copy link

Thanks a lot for all the hard work on this everyone <3

@chenchun
Copy link
Contributor

chenchun commented Jun 14, 2016

Tested bridge/overlay network with https://github.com/aboch/docker/commits/rst manually. Everything seems fine except that MASQUERADE rules duplicates if restarting daemon with live containers in bridge network. We didn't clean POSTROUTING chain during bridge driver init and we recreate MASQUERADE rules on AllocatePort.

@aboch
Copy link
Contributor Author

aboch commented Jun 14, 2016

Thanks @chenchun. If it is ok with you, we can take care of the duplicate iptables rules as a subsequent bug fix.

@chenchun
Copy link
Contributor

That's ok.

@aboch
Copy link
Contributor Author

aboch commented Jun 14, 2016

@coolljt0725 The error you were hitting Could not open netlink handle during vni population for ns /var/run/docker/netns/2-3e0a937d28: failed to set into network namespace 23 while creating netlink socket: invalid argument was likely due a stale netns. Latest commit which restart the sandbox GC should have fixed it.

@mrjana
Copy link
Contributor

mrjana commented Jun 14, 2016

@coolljt0725 @aboch @sanimej @mavenugo Thanks for the marathon effort in getting this done in time before 1.12-RC1. The design and changes LGTM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants