[WIP] Add support for server-side stacks#38832
Conversation
|
This initial revision builds, but likely does not pass tests. |
b6a024f to
d5e55b1
Compare
|
Really glad to see this! Do you have a link to the PR introducing the API for custom resources in swarmkit? |
|
p.s. this really would have been nice to have in the roadmap.md |
|
I have no intention of exposing the Resource API publicly at this time. I think there's too much work involved in making it consumable by end users. However, I do believe that there are probably more things like Stacks which we might want to store in Swarmkit, so the API is available internally for new object types. |
|
Sorry about the code drop. I actually got involved with this project relatively late in the process, after the code had been started. I'm carrying this PR because I have the most experience working in the engine like this. |
|
It may be worth nothing that besides the portions vendored through this PR, the https://github.com/docker/stacks project includes components that can be used outside the scope of the moby project, such as:
|
|
|
||
| # stacks and their deps | ||
| github.com/docker/stacks 8e8ca77c0ac58e3f2fafbf7490340be1a91c8659 git@github.com:docker/stacks.git | ||
| github.com/docker/stacks 68ec0f837572a4e63e4e8993c8b3504a99eb9c2e /home/dperny/go/src/github.com/docker/stacks |
There was a problem hiding this comment.
repo is public now, so /home/dperny/go/src/github.com/docker/stacks could be removed (I guess vndr is failing on that right now)
| Client: c.client, | ||
| Version: c.version, | ||
| CustomHTTPHeaders: c.customHTTPHeaders, | ||
| }) |
There was a problem hiding this comment.
I should point out that we're not 100% happy with this implementation detail just yet, but what we've been aiming for is a pattern where projects integrating into Moby can define their own API and client libraries that can work in isolation, and also be integrated into the overall client library with minimal integration glue. There's more cut-and-paste code in https://github.com/docker/stacks/tree/master/pkg/client than we'd like, so ultimately where I think this should go is more of the APIs docker/docker/client are teased out into importable pkg modules that are reusable.
There was a problem hiding this comment.
What are you missing? from the client package here?
There was a problem hiding this comment.
Should this be passed as an op perhaps?
NewClientWithOpts(client.WithStackClient(...))There was a problem hiding this comment.
These were the two major chunks
- https://github.com/docker/stacks/blob/master/pkg/client/errors.go
- https://github.com/docker/stacks/blob/master/pkg/client/request.go
... and something to address https://github.com/docker/stacks/blob/master/pkg/client/client.go#L12-L31
There was a problem hiding this comment.
I'm really not sure what this subclient is for.
We have the client in github.com/docker/docker/client -- what is missing from the client for you to implement a stacks client? Are you looking for a more HTTP client wrapper?
There was a problem hiding this comment.
I'm really not sure what this subclient is for
It's a client library for dealing with stacks
There was a problem hiding this comment.
what is missing from the client for you to implement a stacks client?
We had to copy-and-paste a bit of the low-level code for interacting with a Docker REST style API server, since the functions in the docker/docker/client package were not exported. As we try to break up the monolith and fulfill the Moby vision, other projects will wind up re-inventing this same low-level http client code, so it seems like we should consider generalizing that so its reusable.
There was a problem hiding this comment.
Seems like these could be refactored into a HTTP client wrapper.
There was a problem hiding this comment.
@cpuguy83 in general, what are you thinking by "refactored into a HTTP client wrapper"? i'm unclear on what you mean by that.
There was a problem hiding this comment.
I mean make a new package for the low level HTTP handling that can be shared by both github.com/docker/docker/client and github.com/docker/stacks/pkg/client.
|
I'm using new commits instead of force-pushing so that we can keep up on changes. We can squash this one way or another before we ship it. |
|
Thinking a bit about this. Something that worries me is pulling in something that is completely a client side specification into the API. Of course I understand that this (at least potentially) brings much better safety guarantees than the client implementation is able to do, however the format itself is a bit problematic. There's already many open issues about shortcomings of the (compose) format that have been left unaddressed with many heated arguments on the issue tracker. This bares a striking resemblance to the situation with Dockerfiles where we have this highly opinionated format which, historically, is notoriously difficult to introduce new features for, is tied to specific versions of Docker, and is a source of much contention and strife in the community. The solution to this was buildkit, which enables users to define their own frontend format that is translated into a common instruction set (LLB) which can then be run on any backend that understand it. Now, I understand that the format being passed into the daemon is not the literal yaml doc, but it is basically just a conversion of it from yaml to json and as such it has the same issues... maybe even more because the lifecycle management is tied to the daemon rather than a client and as such makes it far less malleable. |
This flips to the correct version numbers, which means we can turn the e2e tests back on. If the engine used during testing is from master before merging moby/moby#38832 it will incorrectly think the server-side stacks APIs are present. Signed-off-by: Daniel Hiltgen <[email protected]>
|
this is sort of based around a similar idea to what you seem to be describing for buildkit, actually, but sort of different basically, there is a want to support both Kubernetes and Swarm stacks with compose. currently, as i understand, you can do that, but it's currently based around using two different sets of APIs. the goal here is to create one central stream through which you can access multiple stack providers. the compose yaml types end up being the common language spoken across the different backends. we use them because they already exist, and there is already parsing and conversion logic for compose types to the various backend types. |
|
A common API between the two is not the same thing at all. This is a very high level API. What I am saying is this PR fixes the atomicity issues of client side stacks but dramatically reduces flexibility in implementation. All this for a format that is already known to be problematic. We could expose custom swarmkit resources to the docker API as experimental and work towards a solution where docker/stacks can be built on top of that... stacks would basically be exercising the custom resource API and gives us a chance to change as needed. |
Codecov Report
@@ Coverage Diff @@
## master #38832 +/- ##
==========================================
- Coverage 36.47% 36.38% -0.09%
==========================================
Files 613 614 +1
Lines 45814 45925 +111
==========================================
+ Hits 16709 16710 +1
- Misses 26823 26931 +108
- Partials 2282 2284 +2 |
Signed-off-by: Drew Erny <[email protected]>
Adds the plumbing to support storing server-side stacks in swarmkit's distributed object store. Includes changes to support storing and retrieving stacks using swarmkit's Resource type, and changes to support stack events. Signed-off-by: Drew Erny <[email protected]>
Adds the plumbing for running the stacks reconciler Signed-off-by: Drew Erny <[email protected]>
Co-authored-by: Drew Erny <[email protected]> Co-authored-by: Daniel Hiltgen <[email protected]> Signed-off-by: Drew Erny <[email protected]> Signed-off-by: Daniel Hiltgen <[email protected]>
Signed-off-by: Drew Erny <[email protected]>
Signed-off-by: Drew Erny <[email protected]>
Signed-off-by: Drew Erny <[email protected]>
|
Updated the service inspect test to ignore the Meta.Version field, which should stop that test from failing. Rebased to resolve vendor conflict. |
|
Well this failure is a mystery: |
|
The swagger failure is unrelated; it's due to random ordering in the generator; see #36714 |
|
@cpuguy83 I don't know about the idea of adding fully general purpose CRDs to swarmkit, it seems like, well if you want that just use Kubernetes. Although I agree that compose has versioning and feature issues across different releases, it is a core part of the Docker platform for many. Potentially moving it server side can solve many of the problems in it being client side, and maybe lead to a way forward for a more stable version? |
That's what service side stacks is built on top of here in this PR, it's just not being exposed on the Docker API.
So is Dockerfile (even more so than compose). Doesn't mean we should continue down the same exact path, especially knowing the pitfalls.
Again, Dockerfile. Also versioning is just one part of the problem. Even so, here we'll have compose v1, v2, v3 (3.1, 3.2, ...), and then the API version (1.41). |
|
The compose versioning seems like it should be addressed, but does this PR actually intend to change the compose format yet again? I think this PR is part of a set of changes intended to be a very transparent to the end user that calls Would getting the server-side stacks into the codebase be helpful for the next iteration of design changes to the stacks behaviour and perhaps the compose format? @cpuguy83 that I think needs more to flesh out. |
|
To reduce the risk of this initial PR, taking a note from DOCKER_BUILDKIT, could there also be a DOCKER_SERVER_STACKS opt-in that would activate the codepaths? I think then we would have to add something desirable for the end user to want to activate the feature...perhaps some UI change that can only be accomplished with the new server-side stacks. |
|
That does not solve the issues I've brought up at all. |
|
We're gonna need some refinement before this can get anything resembling merged, so I'm closing. |
This PR is currently marked WIP, because work in the underlying
docker/stacksrepository is still ongoing. However, the code integrating it with the engine should be stable and ready for review, even if the underlying components themselves may changeContacts for this PR are me, @dhiltgen, and @alexmavr
- What I did
Add support for server-side stacks by importing and wiring up the
github.com/docker/stackslibraries.- How I did it
There are three parts to this PR:
Clusterobject, incmd/dockerd/daemon.go.Clusterobject for storing the new Stacks in swarm's distributed object store. These are wired up such that the cluster can be passed to the stacks backend. These methods leverage swarmkit's new Resources and Extensions, which allows the daemon to store arbitrary data in the distributed object store. The foundation laid out here can be, in the future, extended to other kinds of resources that are external to swarmkit, but which we would like to persist in a cluster.cmd/dockerd/daemon.go, but is also included in the daemon in order to receive callbacks. It otherwise stands alone and manages its own lifecycle.- How to verify it
The
github.com/docker/stackscode is (surprisingly thoroughly) tested in its own repo. The integration code largely does not yet have tests, as this PR is still WIP and subject to lots of review and changes. There are end-to-end tests in progress which should verify that the integration all works.- Description for the changelog
Add support for server-side stacks
- A picture of a cute animal (not mandatory but encouraged)

This is my cat, I took this picture this morning: