Skip to content

Add support for sysctl options in services#37701

Merged
vdemeester merged 1 commit intomoby:masterfrom
dperny:add-swarmkit-sysctl-support
Sep 26, 2018
Merged

Add support for sysctl options in services#37701
vdemeester merged 1 commit intomoby:masterfrom
dperny:add-swarmkit-sysctl-support

Conversation

@dperny
Copy link
Contributor

@dperny dperny commented Aug 22, 2018

- What I did
Adds support for sysctl options in docker services.

  • Adds API plumbing for creating services with sysctl options set.
  • Adds swagger.yaml documentation for new API field.
  • Changes executor package to make use of the Sysctls field on objects
  • Includes integration test to verify that new behavior works.

Essentially, everything needed to support the equivalent of docker run's --sysctl option except the CLI.

Depends on moby/swarmkit#2729, which is not merged yet, and so has my fork branch of swarmkit vendored in to demonstrate passing integration test.

- How I did it

Altered all of the API objects and plumbing to accommodate the new field, which swarmkit blindly passes into the executor.

- How to verify it

Includes an integration test.

Related issues:

- Description for the changelog

Add support for sysctl options on docker services.

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

Thanks! Left comments/thoughts inline. We should also look at the docker/cli side for this (and add this option to the docker-compose file format)

Copy link
Member

Choose a reason for hiding this comment

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

Can you add a skip for older daemon versions? (assuming this is planned for inclusion in API 1.39)

	skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.39"), "feature was added in API version 1.39")

Copy link
Member

Choose a reason for hiding this comment

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

Do we need a separate test for service update ? (perhaps overkill)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, we should make one, actually, to verify that service update goes through correctly when Sysctls are changed.

Copy link
Member

Choose a reason for hiding this comment

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

Wondering if a subtest would make this clearer 🤔

for _, expected := range []string{"0", "1"} {
    t.Run(fmt.Sprintf("net.ipv4.ip_nonlocal_bind = %s", expected), func(t *testing.T) {
		// store the map we're going to be using everywhere.
 		sysctlOpts := map[string]string{"net.ipv4.ip_nonlocal_bind": expected}
 		...            
    })
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think that a subtest is useful honestly, because it's just 1 test, we're just trying two values so we don't have to know what the default is.

Copy link
Member

Choose a reason for hiding this comment

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

Was looking if we should have a more generic service create test where we define a list of specs to create services with. Agreed that it's just a minor issue; advantage would be to more easily find which of the test-cases failed

Copy link
Member

Choose a reason for hiding this comment

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

Services should already be removed when the test completes, so I think we can skip this, and just continue with the next iteration

Copy link
Member

Choose a reason for hiding this comment

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

We don't need a name for this service, so better remove it, and just use the serviceID (which is already used)

Copy link
Member

Choose a reason for hiding this comment

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

Remove the name

Copy link
Member

Choose a reason for hiding this comment

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

Should we use service logs instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As the person ostensibly responsible for service logs, no.

Copy link
Member

Choose a reason for hiding this comment

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

In that case, we must skip the test if it's running on a multi-node swarm.

Copy link
Member

Choose a reason for hiding this comment

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

Let me think about this;

Instead of using the container's / service's logs to check if the value was set, could we abuse the container's command for this (something like if cat /proc/sys/net/ipv4/ip_nonlocal_bind != expected value; exit 1)?

Thinking a bit further about this; I'm wondering if we need to check this at all. Creating a container with custom sysctl settings is an existing feature. The only thing being added in this PR is that that container is now created through SwarmKit instead of docker run.

Because of that, I think all we need to verify is if the container-spec is correct (the expected sysctl options are set).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Instead of using the container's / service's logs to check if the value was set, could we abuse the container's command for this (something like if cat /proc/sys/net/ipv4/ip_nonlocal_bind != expected value; exit 1)?

What do you think is better about doing it this way? Having containers exit in a swarm service test leaves us dealing with swarmkit rescheduling those containers.

Thinking a bit further about this; I'm wondering if we need to check this at all. Creating a container with custom sysctl settings is an existing feature. The only thing being added in this PR is that that container is now created through SwarmKit instead of docker run.

We do, actually, to make sure that the value of the Sysctls is plumbed through correctly. When writing this test, I actually missed a location where the value was plumbed through and so the value was making its way into the container spec, but not into the actual container.

Copy link
Member

Choose a reason for hiding this comment

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

We do, actually, to make sure that the value of the Sysctls is plumbed through correctly.

Discussed this with @dperny on Slack; inspecting the container should contain enough information that the correct container-spec was created. Creating containers from a spec/config is already covered by other tests, so for this feature we don't have to test that part 👍

api/swagger.yaml Outdated
Copy link
Member

Choose a reason for hiding this comment

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

Can you add an example here?

Sysctls:
  description: "Set kernel namedspaced parameters (sysctls) in the container."
  type: "object"
  additionalProperties:
    type: "string"
  example:
    net.ipv4.tcp_keepalive_time: "600"
    net.ipv4.tcp_keepalive_intvl: "60"
    net.ipv4.tcp_keepalive_probes: "3"
    net.ipv4.tcp_timestamps: "0"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is there a way to reference or crosslink to the documentation for this option on the container HostConfig?

Copy link
Member

Choose a reason for hiding this comment

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

Hm; good one, perhaps just refer to it in the description 🤔 ("this option accepts the same sysctls as can be specified for containers", or something along those lines 😂)

api/swagger.yaml Outdated
Copy link
Member

Choose a reason for hiding this comment

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

Can you update the API version history, and add a bullet for this new option? https://github.com/moby/moby/blob/master/docs/api/version-history.md#v139-api-changes

(make sure to mention all of POST /services/create, POST /services/{id}/update, and GET /services/{id})

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah I always forget the API version history.

@dperny dperny force-pushed the add-swarmkit-sysctl-support branch from 3ff99e4 to a8e023b Compare August 23, 2018 15:03
Copy link
Member

Choose a reason for hiding this comment

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

missed a closing back tic after Sysctls

Copy link
Member

Choose a reason for hiding this comment

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

👍 Good one; wondering now if creating a service without ContainerSpec is actually a valid request.

Not something to address in this PR, but just wondering that; and if we should validate/error in that situation 🤔

@dperny dperny force-pushed the add-swarmkit-sysctl-support branch from a8e023b to 6a24f7b Compare August 23, 2018 15:41
@codecov
Copy link

codecov bot commented Aug 23, 2018

Codecov Report

Merging #37701 into master will increase coverage by 0.01%.
The diff coverage is 100%.

@@            Coverage Diff             @@
##           master   #37701      +/-   ##
==========================================
+ Coverage   36.12%   36.14%   +0.01%     
==========================================
  Files         610      610              
  Lines       45083    45086       +3     
==========================================
+ Hits        16288    16297       +9     
+ Misses      26555    26551       -4     
+ Partials     2240     2238       -2

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

LGTM after the t.Skip() is added for API < 1.39
https://github.com/moby/moby/pull/37701/files#r212267159

of course, depends on the upstream swarmkit PR to be merged

@dperny
Copy link
Contributor Author

dperny commented Aug 23, 2018

I forgot to add the t.Skip(), so I'll go back and do so when I revendor swarmkit

@dperny dperny force-pushed the add-swarmkit-sysctl-support branch from 6a24f7b to 1f8f6c3 Compare August 24, 2018 14:51
@dperny
Copy link
Contributor Author

dperny commented Aug 24, 2018

@thaJeztah updated the swagger.yml description of the Sysctls option in container specs. It should be much more clear. PTAL.

vendor.conf Outdated
Copy link
Member

Choose a reason for hiding this comment

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

Upstream was merged; can you un-fork the dependency?

@thaJeztah
Copy link
Member

OH, can you also add the example to the swagger YAML (see my comment here; #37701 (comment))

@dperny dperny force-pushed the add-swarmkit-sysctl-support branch from 1f8f6c3 to dd7434e Compare August 27, 2018 14:23
Copy link
Contributor

Choose a reason for hiding this comment

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

Move this to a function and use it here and below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i disagree, but mostly because i'm unsure what the best signature for that function would be, and considering it's only like 8 lines duplicated, i don't think there's much of a benefit to the refactoring.

Copy link
Contributor

Choose a reason for hiding this comment

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

every duplicated line of code counts :)
But that's borderline bikeshedding

Copy link
Contributor

@wk8 wk8 Sep 12, 2018

Choose a reason for hiding this comment

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

I would tend to agree with @anshulpundir here (though the question of the fun's signature is indeed interesting!)

Also, I'm a little worried that this file is gonna get littered with version checks really fast if we really want to ensure never adding new features to frozen versions; don't get me wrong, it makes sense, but I'm actually quite surprised there's only one check as of now. There's certainly going to be a lot more if we do all of #25303 . There might be a better way of doing this?

Copy link
Member

Choose a reason for hiding this comment

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

just for the sake of it, I tend to agree with @dperny : sometimes a little duplication is better than the wrong abstraction… once we find a correct abstraction for those, we'll refactor 😉

Copy link
Contributor

Choose a reason for hiding this comment

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

Is this only used in the unit-test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes (well, it's technically an integration test), but a lot of these functions are only used in one test.

Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't we have a similar test for updates too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

there isn't one for the other things tested here.

@cballou
Copy link

cballou commented Sep 15, 2018

The pre-req, moby/swarmkit#2729, was already merged into master 22 days ago.

How close are we to seeing this in nightly? I'm really looking to utilize the addition of sysctls to my docker compose files to run in combination with swarm and docker stack deploy. It's a performance blocker for high IO applications.

@cballou
Copy link

cballou commented Sep 18, 2018

@vdemeester Just checking if it's possible to get this in docker-ce 18.9.0 beta. I'm literally in the process of migrating to k8s because they have --allowed-unsafe-sysctls implemented already. It's not feasible to run a production level swarm stack under high throughput without this fixed. Customization at the sysctl level is necessary.

@dperny dperny force-pushed the add-swarmkit-sysctl-support branch 2 times, most recently from 8e0ce06 to 5785f17 Compare September 19, 2018 14:43
@dperny
Copy link
Contributor Author

dperny commented Sep 19, 2018

I had an error from not running swagger generation. However, when I ran it, container_wait.go was altered. I do not know if this change is of any impact @thaJeztah.

@dave-receptiviti
Copy link

dave-receptiviti commented Sep 19, 2018

During a load test against one of our containers, we found that hitting the container directly, outside of swarm mode, resulted in 1.8x more throughput than when that container was running as one service instance in a one node Swarm.

Like @dperny and @cballou, we are really looking forward to having performance fixes / sysctl options expedited

Adds support for sysctl options in docker services.

* Adds API plumbing for creating services with sysctl options set.
* Adds swagger.yaml documentation for new API field.
* Updates the API version history document.
* Changes executor package to make use of the Sysctls field on objects
* Includes integration test to verify that new behavior works.

Essentially, everything needed to support the equivalent of docker run's
`--sysctl` option except the CLI.

Includes a vendoring of swarmkit for proto changes to support the new
behavior.

Signed-off-by: Drew Erny <[email protected]>
@dperny dperny force-pushed the add-swarmkit-sysctl-support branch from 5785f17 to 14da20f Compare September 20, 2018 15:52
Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

LGTM

ping @vdemeester @anshulpundir PTAL

Copy link
Member

@vdemeester vdemeester left a comment

Choose a reason for hiding this comment

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

LGTM 🐯

Copy link
Member

Choose a reason for hiding this comment

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

just for the sake of it, I tend to agree with @dperny : sometimes a little duplication is better than the wrong abstraction… once we find a correct abstraction for those, we'll refactor 😉

@marzlarz
Copy link

So are we finally able to set "sysctl" options for Docker services or is this just the underlying updates required to eventually expose this to the CLI ?

@cballou
Copy link

cballou commented Oct 29, 2018

So I see that the API version was changed from 1.3.9 to 1.4.0. Is there a tentative release of that schedule in the near future? The documentation currently points to a non-existent page of the version:

https://docs.docker.com/engine/api/v1.40/

@thaJeztah
Copy link
Member

@cballou API v1.40 is not finalised yet (as in; changes will still arrive). That version will be included in the next Docker release (after Docker 18.09, which has API v1.39)

@netoneko
Copy link

netoneko commented Dec 17, 2018

@thaJeztah hey, did the feature make it into the release? I am trying set the sysctl for a stack via Golang code and it doesn't work for me (but works for the regular containers).

I set my API version in Golang client code to 1.39 to no avail.

Also trying to deploy from command line give me this:

docker stack deploy --compose-file docker-compose.yml demo
Ignoring unsupported options: sysctls
Server: Docker Engine - Community
 Engine:
  Version:          18.09.0
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.4
  Git commit:       4d60db4
  Built:            Wed Nov  7 00:16:44 2018
  OS/Arch:          linux/amd64
  Experimental:     false

@thaJeztah
Copy link
Member

No, this didn't make it for 18.09, so will be in 19.03

@mariusglauer
Copy link

mariusglauer commented Feb 27, 2019

Hi, updated to docker-ce nightly and tried to pass sysctls: in my docker-compose file.

This is the resulting output:

Ignoring unsupported options: sysctls
...

Anything required to make this work? @thaJeztah

@thaJeztah
Copy link
Member

Opened a PR for the cli and compose-file changes (for docker stack); docker/cli#1754

@netoneko
Copy link

netoneko commented May 3, 2019

@thaJeztah I have tried with the latest 19.0.3 beta to no avail:

docker service create --sysctl net.core.somaxconn=9999 --name test-sysctl ubuntu sh -c "sysctl net.core.somaxconn ; sleep 100000"

Still returns 128.

I have copied your test to reproduce the issue programmatically, and it also fails: https://github.com/orbs-network/boyarin/pull/80/files#diff-e5db09d7878227a83cc084a0fd016450

I have tried both API versions 1.39 and 1.40 and nothing changes. Also, when I do docker service inspect it also omits Sysctls section. I have tried golang client from master as well.

Client: Docker Engine - Community
 Version:           19.03.0-beta3
 API version:       1.40
 Go version:        go1.12.4
 Git commit:        c55e026
 Built:             Thu Apr 25 19:05:38 2019
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.0-beta3
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.4
  Git commit:       c55e026
  Built:            Thu Apr 25 19:13:00 2019
  OS/Arch:          linux/amd64
  Experimental:     true
 containerd:
  Version:          v1.2.6
  GitCommit:        894b81a4b802e4eb2a91d1ce216b8817763c29fb
 runc:
  Version:          1.0.0-rc7+dev
  GitCommit:        029124da7af7360afa781a0234d1b083550f797c
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

@thaJeztah thaJeztah added area/swarm kind/feature Functionality or other elements that the project doesn't currently have. Features are new and shiny labels Jul 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/swarm impact/api impact/changelog impact/documentation kind/feature Functionality or other elements that the project doesn't currently have. Features are new and shiny status/2-code-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.