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

Plugins on swarm #33575

Merged
merged 1 commit into from Jul 7, 2017
Merged

Plugins on swarm #33575

merged 1 commit into from Jul 7, 2017

Conversation

cpuguy83
Copy link
Member

@cpuguy83 cpuguy83 commented Jun 7, 2017

Support deploying plugins via swarm services

Modifies the services API to support deploying plugins (previously only
supported containers).
This makes use of some of the existing work around generic service
runtimes.

With this change you can curl -X POST myDocker:2375/services/create with a
PluginSpec defined in the TaskTemplate.
The plugin defined by in the PluginSpec will be deployed similar to a
"global mode" service.

Work still needed:

  • More tests (test constraints, others)
  • Deal with some race conditions in the plugin manager
  • Better way to filter swarm managed plugins from non-swarm managed plugins
  • Support enable/disable via services API?
  • Handle (old) task removes (ie, don't remove a plugin that has an active task)

The format of the plugin request that is sent to swarm is currently just a json encoded object specified in api/types/swarm... wondering if it would be better to change this to protobuf.

Ping @ehazlett @tiborvass

What this does not tackle:

  • UX, CLI is not handled here, only API's are added... even API's could maybe use some tweaks but worried about back-compat for older clients... specifically on service and task listings which currently only list services/tasks with the container runtime unless you set a runtime in the list filter.
  • Secrets, configs, mounts, networks, etc... this requires deeper changes to plugins and can be done separately.

@cpuguy83 cpuguy83 force-pushed the plugins_on_swarm branch 4 times, most recently from 8322070 to 977fcc8 Compare June 8, 2017 02:19
@cpuguy83 cpuguy83 changed the title [WIP] Plugins on swarm Plugins on swarm Jun 8, 2017
@cpuguy83 cpuguy83 force-pushed the plugins_on_swarm branch 3 times, most recently from 9ab7953 to 97dec15 Compare June 8, 2017 18:37
@cpuguy83
Copy link
Member Author

cpuguy83 commented Jun 8, 2017

Ok, I think this is ready for design review, and code is in a pretty good state.

ping @aaronlehmann

@cpuguy83 cpuguy83 force-pushed the plugins_on_swarm branch 2 times, most recently from efcd344 to 9b02932 Compare June 8, 2017 18:54
@ehazlett
Copy link
Contributor

ehazlett commented Jun 8, 2017

Sorry for the delay. +1 for pb encoding. In the "original" design, that was the intention we just left it out of the Generic Runtime PR as we didn't have anything to use yet.

@aaronlehmann
Copy link
Contributor

wondering if it would be better to change this to protobuf.

Yes, I think protobuf would be better.

@@ -66,7 +66,8 @@ type TaskSpec struct {
// parameters have been changed.
ForceUpdate uint64

Runtime RuntimeType `json:",omitempty"`
Runtime RuntimeType `json:",omitempty"`
PluginSpec *PluginSpec `json:",omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd suggest putting this next to ContainerSpec in the struct definition and adding a comment that they are mutually exclusive. We should probably change ContainerSpec to be a pointer (and make sure no code assumes it exists).

logrus.WithFields(logrus.Fields{
"controller": "plugin",
}).Debug("Prepare")

// TODO(@cpuguy83): support digest pinning
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like tag+digest is already supported. What else needs to be done?

Copy link
Member Author

Choose a reason for hiding this comment

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

Should we pin this before sending off to swarm?

Copy link
Contributor

Choose a reason for hiding this comment

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

Pinning happens on the CLI side starting with API 1.30.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok makes sense to do that there.

}

if canonical, ok := remote.(canonicalWithTag); ok {
remote, err = reference.WithDigest(reference.TrimNamed(remote), canonical.Digest())
Copy link
Contributor

Choose a reason for hiding this comment

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

It should be possible to pass a reference with both a tag and a digest to the pull code. This wasn't working properly earlier, but it was fixed recently.

Not sure if there are any plugin-specific issues with doing this, but ideally there shouldn't be.

Copy link
Member Author

Choose a reason for hiding this comment

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

So you are saying to drop the TrimNamed bit?

if err != context.Canceled {
t.Fatal(err)
}
case <-time.After(500 * time.Millisecond):
Copy link
Contributor

Choose a reason for hiding this comment

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

Is 500 ms enough? I like to be very conservative with timeouts in test so that loaded machines don't cause spurious failures.

switch g.Kind {
case string(types.RuntimePlugin):
var p types.GenericPluginPayload
json.Unmarshal(g.Payload.Value, &p)
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess we'll change this to gRPC anyway, but the error needs to be checked.

@@ -50,14 +50,16 @@ func (c *Cluster) GetServices(options apitypes.ServiceListOptions) ([]types.Serv
return nil, err
}

if len(options.Filters.Get("runtime")) == 0 {
// Default to using the container runtime filter
Copy link
Contributor

Choose a reason for hiding this comment

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

Wondering if we should do this in the CLI instead of the API. No strong preference though.

Copy link
Member Author

Choose a reason for hiding this comment

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

I would prefer the CLI, but I didn't want to make a breaking change to the API here.

d2 := s.AddDaemon(c, true, true)
d3 := s.AddDaemon(c, true, false)

time.Sleep(1 * time.Second) // make sure all daemons are ready to accept
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this sleep is necessary. I don't recall any other tests that create services doing this.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh I copied this from the test above it. I can remove.

s.Spec.TaskTemplate.Runtime = "plugin"
s.Spec.TaskTemplate.PluginSpec = &swarm.PluginSpec{
Name: "test",
Remote: "cpuguy83/docker-logdriver-test",
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm hoping we can avoid adding new dependencies on Docker Hub in tests; see #30626

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I keep putting this off... I'll work on something for this.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, added a plugin builder + some registry integration. Check it out in integration-cli/fixtures/plugin.

plugin/events.go Outdated
"github.com/docker/docker/api/types"
)

// Event is emitted for actions performed on the
Copy link
Contributor

Choose a reason for hiding this comment

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

I remember this truncated comment from swarmkit :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Such a coincidence :)

liron-l pushed a commit to twistlock/swarmkit that referenced this pull request Jun 11, 2017
This commit extends SwarmKit secret management with pluggable secret
backends support, using the current cluster configuration to understand
if secrets are being stored locally, or need to be retrieved from a
remote secret store. The solution will use the existing docker plugin
framework.

The approach is to add a new `driver` parameter to existing secrets,
which defines whether the values are loaded from SwarmKit or from one of
the secret plugins. The loading of secrets is done using the standard
docker plugin infrastructure, which is already accessible in swarmkit
and used in other flows (e.g., networking)

Remarks:
* I've added support to mock the plugin subsystem in controlapi server,
I preferred this approach over loading the full plugin subsystem.

Work still needed in this CR:
- [ ] More unit tests (pending initial iteration)
- [ ] Customized error handling

Work still needed to complete this feature:
- [ ] Inject secrets as part of plugin initialization
- [ ] CLI support in docker

References:
moby/moby#33575

Signed-off-by: liron <liron@twistlock.com>
liron-l pushed a commit to twistlock/swarmkit that referenced this pull request Jun 11, 2017
This commit extends SwarmKit secret management with pluggable secret
backends support. The solution uses the existing docker plugin
framework for loading plugins and the existing SwarmKit data backend for
storing them.

The approach is to add a new `driver` parameter to existing secrets,
which defines whether the values are taken as is or fetched from one of
the secret plugins. The loading of secrets is done using the standard
docker plugin infrastructure, which is already accessible in SwarmKit
and used in other flows (e.g., networking).
The fetched values are are stored as regular SwarmKit secrets.

Remarks:
* I've added support for mocking the plugin subsystem when settings up
the controlapi server.
I preferred this approach over loading the full plugin subsystem in UT.

Work still needed in this CR:
- [ ] More unit tests (pending initial iteration)
- [ ] Customized error handling (e.g., customize error string for Not
Found)

Work still needed to complete this feature:
- [ ] Inject secrets as part of plugin initialization
- [ ] CLI support in docker
- [ ] Docs
- [ ] Support scheduling plugins in swarm
moby/moby#33575

Signed-off-by: liron <liron@twistlock.com>
liron-l pushed a commit to twistlock/swarmkit that referenced this pull request Jun 11, 2017
This commit extends SwarmKit secret management with pluggable secret
backends support. The solution uses the existing docker plugin
framework for loading plugins and the existing SwarmKit data backend for
storing them.

The approach is to add a new `driver` parameter to existing secrets,
which defines whether the values are taken as is or fetched from one of
the secret plugins. The loading of secrets is done using the standard
docker plugin infrastructure, which is already accessible in SwarmKit
and used in other flows (e.g., networking).
The fetched values are are stored as regular SwarmKit secrets.

Remarks:
* I've added support for mocking the plugin subsystem when settings up
the controlapi server.
I preferred this approach over loading the full plugin subsystem in UT.

Work still needed in this CR:
- [ ] More unit tests (pending initial iteration)
- [ ] Customized error handling (e.g., customize error string for Not
Found)

Work still needed to complete this feature:
- [ ] Inject secrets as part of plugin initialization
- [ ] CLI support in docker
- [ ] Docs
- [ ] Support scheduling plugins in swarm
moby/moby#33575

Signed-off-by: liron <liron@twistlock.com>
liron-l pushed a commit to twistlock/swarmkit that referenced this pull request Jun 11, 2017
This commit extends SwarmKit secret management with pluggable secret
backends support. The solution uses the existing docker plugin
framework for loading plugins and the existing SwarmKit data backend for
storing them.

The approach is to add a new `driver` parameter to existing secrets,
which defines whether the values are taken as is or fetched from one of
the secret plugins. The loading of secrets is done using the standard
docker plugin infrastructure, which is already accessible in SwarmKit
and used in other flows (e.g., networking).
The fetched values are are stored as regular SwarmKit secrets.

Remarks:
* I've added support for mocking the plugin subsystem when settings up
the controlapi server.
I preferred this approach over loading the full plugin subsystem in UT.

Work still needed in this CR:
- [ ] More unit tests (pending initial iteration)
- [ ] Customized error handling (e.g., customize error string for Not
Found)

Work still needed to complete this feature:
- [ ] Inject secrets as part of plugin initialization
- [ ] CLI support in docker
- [ ] Docs
- [ ] Support scheduling plugins in swarm
moby/moby#33575

Signed-off-by: liron <liron@twistlock.com>
@cpuguy83
Copy link
Member Author

cpuguy83 commented Jul 6, 2017

Rebased, fixed imports, added client side validation for service spec to create/update.

@yongtang
Copy link
Member

yongtang commented Jul 7, 2017

All tests passed after windowsRS1 rerun. Merging.

@yongtang yongtang merged commit 05c7c31 into moby:master Jul 7, 2017
@rogaha
Copy link
Contributor

rogaha commented Jul 7, 2017

💥 thanks @cpuguy83 for putting this together!

@cpuguy83
Copy link
Member Author

cpuguy83 commented Jul 7, 2017

Just step 1, still need:

  • Support for plugins in private repos
  • Secrets
  • Networking
  • CLI

@rogaha
Copy link
Contributor

rogaha commented Jul 7, 2017

@cpuguy83 do we have issues for those remaining pieces?

@cpuguy83 cpuguy83 deleted the plugins_on_swarm branch July 7, 2017 14:40
@carlfischer1
Copy link

@rogaha @cpuguy83 for Secrets we have #30796

liron-l pushed a commit to twistlock/swarmkit that referenced this pull request Jul 10, 2017
This commit extends SwarmKit secret management with pluggable secret
backends support. The solution uses the existing docker plugin
framework for loading plugins and the existing SwarmKit data backend for
storing them.

The approach is to add a new `driver` parameter to existing secrets,
which defines whether the values are taken as is or fetched from one of
the secret plugins. The loading of secrets is done using the standard
docker plugin infrastructure, which is already accessible in SwarmKit
and used in other flows (e.g., networking).
The fetched values are evaluated before assigning them to worker nodes,
so the payload is not stored in the raft store.

Remarks:
* I've added support for mocking the plugin subsystem when settings up
the controlapi server.
I preferred this approach over loading the full plugin subsystem in UT.

Work still needed in this CR:
- [ ] More unit tests (pending initial iteration)
- [ ] Customized error handling (e.g., customize error string for Not
Found)

Work still needed to complete this feature:
- [ ] Inject secrets as part of plugin initialization
- [ ] CLI support in docker
- [ ] Docs
- [ ] Support scheduling plugins in swarm
moby/moby#33575

Signed-off-by: liron <liron@twistlock.com>
liron-l pushed a commit to twistlock/swarmkit that referenced this pull request Jul 12, 2017
This commit extends SwarmKit secret management with pluggable secret
backends support. The solution uses the existing docker plugin
framework for loading plugins and the existing SwarmKit data backend for
storing them.

The approach is to add a new `driver` parameter to existing secrets,
which defines whether the values are taken as is or fetched from one of
the secret plugins. The loading of secrets is done using the standard
docker plugin infrastructure, which is already accessible in SwarmKit
and used in other flows (e.g., networking).
The fetched values are evaluated before assigning them to worker nodes,
so the payload is not stored in the raft store.

Remarks:
* I've added support for mocking the plugin subsystem when settings up
the controlapi server.
I preferred this approach over loading the full plugin subsystem in UT.

Work still needed in this CR:
- [ ] More unit tests (pending initial iteration)
- [ ] Customized error handling (e.g., customize error string for Not
Found)

Work still needed to complete this feature:
- [ ] Inject secrets as part of plugin initialization
- [ ] CLI support in docker
- [ ] Docs
- [ ] Support scheduling plugins in swarm
moby/moby#33575

Signed-off-by: liron <liron@twistlock.com>
liron-l pushed a commit to twistlock/swarmkit that referenced this pull request Jul 12, 2017
This commit extends SwarmKit secret management with pluggable secret
backends support. The solution uses the existing docker plugin
framework for loading plugins and the existing SwarmKit data backend for
storing them.

The approach is to add a new `driver` parameter to existing secrets,
which defines whether the values are taken as is or fetched from one of
the secret plugins. The loading of secrets is done using the standard
docker plugin infrastructure, which is already accessible in SwarmKit
and used in other flows (e.g., networking).
The fetched values are evaluated before assigning them to worker nodes,
so the payload is not stored in the raft store.

Remarks:
* I've added support for mocking the plugin subsystem when settings up
the controlapi server.
I preferred this approach over loading the full plugin subsystem in UT.

Work still needed in this CR:
- [ ] More unit tests (pending initial iteration)
- [ ] Customized error handling (e.g., customize error string for Not
Found)

Work still needed to complete this feature:
- [ ] Inject secrets as part of plugin initialization
- [ ] CLI support in docker
- [ ] Docs
- [ ] Support scheduling plugins in swarm
moby/moby#33575

Signed-off-by: liron <liron@twistlock.com>
}
if len(imgPlatforms) > 0 {
service.TaskTemplate.Placement.Platforms = imgPlatforms
}
Copy link
Member

Choose a reason for hiding this comment

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

This (and the other changes to this file) seem like the wrong place to handle these concerns. Every other function in this package is only concerned with translating a golang struct into an HTTP request, performing the request, and translating the response into a goland struct.

With this change we've introduced a bunch of application logic and validation that does not belong here.

I think this needs to be extracted to some other package.

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

This is all pre-existing, just re-organized.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, my mistake, looks like it was first introduced and modified in a few PRs starting around #33239

}

if err := validateServiceSpec(service); err != nil {
return types.ServiceCreateResponse{}, err
Copy link
Member

Choose a reason for hiding this comment

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

same problem here

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.

None yet