Ver Fonte

Add ulimits support to services

Add Ulimits field to the ContainerSpec API type and wire it to Swarmkit.

This is related to #40639.

Signed-off-by: Albin Kerouanton <albin@akerouanton.name>
Albin Kerouanton há 5 anos atrás
pai
commit
c76f380bea

+ 2 - 1
api/server/router/swarm/helpers.go

@@ -97,10 +97,11 @@ func adjustForAPIVersion(cliVersion string, service *swarm.ServiceSpec) {
 	}
 	if versions.LessThan(cliVersion, "1.41") {
 		if service.TaskTemplate.ContainerSpec != nil {
-			// Capabilities for docker swarm services weren't
+			// Capabilities and Ulimits for docker swarm services weren't
 			// supported before API version 1.41
 			service.TaskTemplate.ContainerSpec.CapabilityAdd = nil
 			service.TaskTemplate.ContainerSpec.CapabilityDrop = nil
+			service.TaskTemplate.ContainerSpec.Ulimits = nil
 		}
 		if service.TaskTemplate.Resources != nil && service.TaskTemplate.Resources.Limits != nil {
 			// Limits.Pids  not supported before API version 1.41

+ 16 - 0
api/server/router/swarm/helpers_test.go

@@ -5,6 +5,7 @@ import (
 	"testing"
 
 	"github.com/docker/docker/api/types/swarm"
+	"github.com/docker/go-units"
 )
 
 func TestAdjustForAPIVersion(t *testing.T) {
@@ -39,6 +40,13 @@ func TestAdjustForAPIVersion(t *testing.T) {
 						ConfigName: "configRuntime",
 					},
 				},
+				Ulimits: []*units.Ulimit{
+					{
+						Name: "nofile",
+						Soft: 100,
+						Hard: 200,
+					},
+				},
 			},
 			Placement: &swarm.Placement{
 				MaxReplicas: 222,
@@ -78,6 +86,10 @@ func TestAdjustForAPIVersion(t *testing.T) {
 		t.Error("MaxReplicas was stripped from spec")
 	}
 
+	if len(spec.TaskTemplate.ContainerSpec.Ulimits) == 0 {
+		t.Error("Ulimits were stripped from spec")
+	}
+
 	// next, does calling this with an earlier version correctly strip fields?
 	adjustForAPIVersion("1.29", spec)
 	if spec.TaskTemplate.ContainerSpec.Sysctls != nil {
@@ -100,4 +112,8 @@ func TestAdjustForAPIVersion(t *testing.T) {
 		t.Error("MaxReplicas was not stripped from spec")
 	}
 
+	if len(spec.TaskTemplate.ContainerSpec.Ulimits) != 0 {
+		t.Error("Ulimits were not stripped from spec")
+	}
+
 }

+ 16 - 0
api/swagger.yaml

@@ -3306,6 +3306,22 @@ definitions:
               type: "string"
             example:
               - "CAP_NET_RAW"
+          Ulimits:
+            description: |
+              A list of resource limits to set in the container. For example: `{"Name": "nofile", "Soft": 1024, "Hard": 2048}`"
+            type: "array"
+            items:
+              type: "object"
+              properties:
+                Name:
+                  description: "Name of ulimit"
+                  type: "string"
+                Soft:
+                  description: "Soft limit"
+                  type: "integer"
+                Hard:
+                  description: "Hard limit"
+                  type: "integer"
       NetworkAttachmentSpec:
         description: |
           Read-only spec type for non-swarm containers attached to swarm overlay

+ 2 - 0
api/types/swarm/container.go

@@ -5,6 +5,7 @@ import (
 
 	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/api/types/mount"
+	"github.com/docker/go-units"
 )
 
 // DNSConfig specifies DNS related configurations in resolver configuration file (resolv.conf)
@@ -75,4 +76,5 @@ type ContainerSpec struct {
 	Sysctls        map[string]string   `json:",omitempty"`
 	CapabilityAdd  []string            `json:",omitempty"`
 	CapabilityDrop []string            `json:",omitempty"`
+	Ulimits        []*units.Ulimit     `json:",omitempty"`
 }

+ 31 - 0
daemon/cluster/convert/container.go

@@ -7,6 +7,7 @@ import (
 	"github.com/docker/docker/api/types/container"
 	mounttypes "github.com/docker/docker/api/types/mount"
 	types "github.com/docker/docker/api/types/swarm"
+	"github.com/docker/go-units"
 	swarmapi "github.com/docker/swarmkit/api"
 	gogotypes "github.com/gogo/protobuf/types"
 	"github.com/pkg/errors"
@@ -39,6 +40,7 @@ func containerSpecFromGRPC(c *swarmapi.ContainerSpec) *types.ContainerSpec {
 		Sysctls:        c.Sysctls,
 		CapabilityAdd:  c.CapabilityAdd,
 		CapabilityDrop: c.CapabilityDrop,
+		Ulimits:        ulimitsFromGRPC(c.Ulimits),
 	}
 
 	if c.DNSConfig != nil {
@@ -267,6 +269,7 @@ func containerToGRPC(c *types.ContainerSpec) (*swarmapi.ContainerSpec, error) {
 		Sysctls:        c.Sysctls,
 		CapabilityAdd:  c.CapabilityAdd,
 		CapabilityDrop: c.CapabilityDrop,
+		Ulimits:        ulimitsToGRPC(c.Ulimits),
 	}
 
 	if c.DNSConfig != nil {
@@ -471,3 +474,31 @@ func isolationToGRPC(i container.Isolation) swarmapi.ContainerSpec_Isolation {
 	}
 	return swarmapi.ContainerIsolationDefault
 }
+
+func ulimitsFromGRPC(u []*swarmapi.ContainerSpec_Ulimit) []*units.Ulimit {
+	ulimits := make([]*units.Ulimit, len(u))
+
+	for i, ulimit := range u {
+		ulimits[i] = &units.Ulimit{
+			Name: ulimit.Name,
+			Soft: ulimit.Soft,
+			Hard: ulimit.Hard,
+		}
+	}
+
+	return ulimits
+}
+
+func ulimitsToGRPC(u []*units.Ulimit) []*swarmapi.ContainerSpec_Ulimit {
+	ulimits := make([]*swarmapi.ContainerSpec_Ulimit, len(u))
+
+	for i, ulimit := range u {
+		ulimits[i] = &swarmapi.ContainerSpec_Ulimit{
+			Name: ulimit.Name,
+			Soft: ulimit.Soft,
+			Hard: ulimit.Hard,
+		}
+	}
+
+	return ulimits
+}

+ 10 - 0
daemon/cluster/executor/container/container.go

@@ -21,6 +21,7 @@ import (
 	executorpkg "github.com/docker/docker/daemon/cluster/executor"
 	clustertypes "github.com/docker/docker/daemon/cluster/provider"
 	"github.com/docker/go-connections/nat"
+	"github.com/docker/go-units"
 	netconst "github.com/docker/libnetwork/datastore"
 	"github.com/docker/swarmkit/agent/exec"
 	"github.com/docker/swarmkit/api"
@@ -438,6 +439,15 @@ func (c *containerConfig) resources() enginecontainer.Resources {
 		resources.PidsLimit = &pidsLimit
 	}
 
+	resources.Ulimits = make([]*units.Ulimit, len(c.spec().Ulimits))
+	for i, ulimit := range c.spec().Ulimits {
+		resources.Ulimits[i] = &units.Ulimit{
+			Name: ulimit.Name,
+			Soft: ulimit.Soft,
+			Hard: ulimit.Hard,
+		}
+	}
+
 	// If no limits are specified let the engine use its defaults.
 	//
 	// TODO(aluzzardi): We might want to set some limits anyway otherwise

+ 4 - 0
docs/api/version-history.md

@@ -76,6 +76,10 @@ keywords: "API, Docker, rcli, REST, documentation"
   single set of stats instead of waiting for two collection cycles to have 2 CPU stats over a 1 second period.
 * The `KernelMemory` field in `HostConfig.Resources` is now deprecated.
 * The `KernelMemory` field in `Info` is now deprecated.
+* `GET /services` now returns `Ulimits` as part of `ContainerSpec`.
+* `GET /services/{id}` now returns `Ulimits` as part of `ContainerSpec`.
+* `POST /services/create` now accepts `Ulimits` as part of `ContainerSpec`.
+* `POST /services/{id}/update` now accepts `Ulimits` as part of `ContainerSpec`.
 
 ## v1.40 API changes