Allow to set memory / CPU limits higher than requests, ACI will request that limits are not higher than the total request for the container group. Also set requests = limits when only limits are set

Signed-off-by: Guillaume Tardif <guillaume.tardif@docker.com>
This commit is contained in:
Guillaume Tardif 2020-10-05 17:23:08 +02:00
parent c09f771359
commit 343d54dac5
2 changed files with 125 additions and 19 deletions

View File

@ -353,34 +353,73 @@ func (s serviceConfigAciHelper) getAciContainer(volumesCache map[string]bool) (c
volumes = &allVolumes
}
memRequest := 1. // Default 1 Gb
var cpuRequest float64 = 1
if s.Deploy != nil && s.Deploy.Resources.Reservations != nil {
if s.Deploy.Resources.Reservations.MemoryBytes != 0 {
memRequest = bytesToGb(s.Deploy.Resources.Reservations.MemoryBytes)
}
if s.Deploy.Resources.Reservations.NanoCPUs != "" {
cpuRequest, err = strconv.ParseFloat(s.Deploy.Resources.Reservations.NanoCPUs, 0)
resource, err := s.getResourceRequestsLimits()
if err != nil {
return containerinstance.Container{}, err
}
}
}
return containerinstance.Container{
Name: to.StringPtr(s.Name),
ContainerProperties: &containerinstance.ContainerProperties{
Image: to.StringPtr(s.Image),
Command: to.StringSlicePtr(s.Command),
EnvironmentVariables: getEnvVariables(s.Environment),
Resources: &containerinstance.ResourceRequirements{
Resources: resource,
VolumeMounts: volumes,
},
}, nil
}
func (s serviceConfigAciHelper) getResourceRequestsLimits() (*containerinstance.ResourceRequirements, error) {
memRequest := 1. // Default 1 Gb
var cpuRequest float64 = 1
var err error
hasMemoryRequest := func() bool {
return s.Deploy != nil && s.Deploy.Resources.Reservations != nil && s.Deploy.Resources.Reservations.MemoryBytes != 0
}
hasCPURequest := func() bool {
return s.Deploy != nil && s.Deploy.Resources.Reservations != nil && s.Deploy.Resources.Reservations.NanoCPUs != ""
}
if hasMemoryRequest() {
memRequest = bytesToGb(s.Deploy.Resources.Reservations.MemoryBytes)
}
if hasCPURequest() {
cpuRequest, err = strconv.ParseFloat(s.Deploy.Resources.Reservations.NanoCPUs, 0)
if err != nil {
return nil, err
}
}
memLimit := memRequest
cpuLimit := cpuRequest
if s.Deploy != nil && s.Deploy.Resources.Limits != nil {
if s.Deploy.Resources.Limits.MemoryBytes != 0 {
memLimit = bytesToGb(s.Deploy.Resources.Limits.MemoryBytes)
if !hasMemoryRequest() {
memRequest = memLimit
}
}
if s.Deploy.Resources.Limits.NanoCPUs != "" {
cpuLimit, err = strconv.ParseFloat(s.Deploy.Resources.Limits.NanoCPUs, 0)
if err != nil {
return nil, err
}
if !hasCPURequest() {
cpuRequest = cpuLimit
}
}
}
resources := containerinstance.ResourceRequirements{
Requests: &containerinstance.ResourceRequests{
MemoryInGB: to.Float64Ptr(memRequest),
CPU: to.Float64Ptr(cpuRequest),
},
Limits: &containerinstance.ResourceLimits{
MemoryInGB: to.Float64Ptr(memLimit),
CPU: to.Float64Ptr(cpuLimit),
},
VolumeMounts: volumes,
},
}, nil
}
return &resources, nil
}
func getEnvVariables(composeEnv types.MappingWithEquals) *[]containerinstance.EnvironmentVariable {

View File

@ -561,6 +561,73 @@ func TestComposeContainerGroupToContainerResourceRequests(t *testing.T) {
request := *((*group.Containers)[0]).Resources.Requests
assert.Equal(t, *request.CPU, float64(0.1))
assert.Equal(t, *request.MemoryInGB, float64(0.1))
limits := *((*group.Containers)[0]).Resources.Limits
assert.Equal(t, *limits.CPU, float64(0.1))
assert.Equal(t, *limits.MemoryInGB, float64(0.1))
}
func TestComposeContainerGroupToContainerResourceRequestsAndLimits(t *testing.T) {
_0_1Gb := 0.1 * 1024 * 1024 * 1024
project := types.Project{
Services: []types.ServiceConfig{
{
Name: "service1",
Image: "image1",
Deploy: &types.DeployConfig{
Resources: types.Resources{
Reservations: &types.Resource{
NanoCPUs: "0.1",
MemoryBytes: types.UnitBytes(_0_1Gb),
},
Limits: &types.Resource{
NanoCPUs: "0.3",
MemoryBytes: types.UnitBytes(2 * _0_1Gb),
},
},
},
},
},
}
group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
assert.NilError(t, err)
request := *((*group.Containers)[0]).Resources.Requests
assert.Equal(t, *request.CPU, float64(0.1))
assert.Equal(t, *request.MemoryInGB, float64(0.1))
limits := *((*group.Containers)[0]).Resources.Limits
assert.Equal(t, *limits.CPU, float64(0.3))
assert.Equal(t, *limits.MemoryInGB, float64(0.2))
}
func TestComposeContainerGroupToContainerResourceLimitsOnly(t *testing.T) {
_0_1Gb := 0.1 * 1024 * 1024 * 1024
project := types.Project{
Services: []types.ServiceConfig{
{
Name: "service1",
Image: "image1",
Deploy: &types.DeployConfig{
Resources: types.Resources{
Limits: &types.Resource{
NanoCPUs: "0.3",
MemoryBytes: types.UnitBytes(2 * _0_1Gb),
},
},
},
},
},
}
group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
assert.NilError(t, err)
request := *((*group.Containers)[0]).Resources.Requests
assert.Equal(t, *request.CPU, float64(0.3))
assert.Equal(t, *request.MemoryInGB, float64(0.2))
limits := *((*group.Containers)[0]).Resources.Limits
assert.Equal(t, *limits.CPU, float64(0.3))
assert.Equal(t, *limits.MemoryInGB, float64(0.2))
}
func TestComposeContainerGroupToContainerResourceRequestsDefaults(t *testing.T) {