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

allow unbounded ram tasks windows #2239

Merged
merged 3 commits into from
Oct 20, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ additional details on each available environment variable.
| `ECS_CGROUP_PATH` | `/sys/fs/cgroup` | The root cgroup path that is expected by the ECS agent. This is the path that accessible from the agent mount. | `/sys/fs/cgroup` | Not applicable |
| `ECS_CGROUP_CPU_PERIOD` | `10ms` | CGroups CPU period for task level limits. This value should be between 8ms to 100ms | `100ms` | Not applicable |
| `ECS_ENABLE_CPU_UNBOUNDED_WINDOWS_WORKAROUND` | `true` | When `true`, ECS will allow CPU unbounded(CPU=`0`) tasks to run along with CPU bounded tasks in Windows. | Not applicable | `false` |
| `ECS_ENABLE_RAM_UNBOUNDED_WINDOWS_WORKAROUND` | `true` | When `true`, ECS will allow tasks with no memory reservation to run along with memory bounded tasks in Windows. To run a memory unbounded task, omit the memory hard limit and set any memory reservation, it will be ignored. | Not applicable | `false` |
Copy link
Contributor

Choose a reason for hiding this comment

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

what would be a good counterpoint for calling this ECS_ENABLE_MEMORY_UNBOUNDED_WINDOWS_WORKAROUND ?

Copy link
Contributor

Choose a reason for hiding this comment

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

s/allow tasks with no memory reservation/ignore the memory reservation parameter (soft limit)/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

im okay with this

| `ECS_TASK_METADATA_RPS_LIMIT` | `100,150` | Comma separated integer values for steady state and burst throttle limits for task metadata endpoint | `40,60` | `40,60` |
| `ECS_SHARED_VOLUME_MATCH_FULL_CONFIG` | `true` | When `true`, ECS Agent will compare name, driver options, and labels to make sure volumes are identical. When `false`, Agent will short circuit shared volume comparison if the names match. This is the default Docker behavior. If a volume is shared across instances, this should be set to `false`. | `false` | `false`|
| `ECS_CONTAINER_INSTANCE_PROPAGATE_TAGS_FROM` | `ec2_instance` | If `ec2_instance` is specified, existing tags defined on the container instance will be registered to Amazon ECS and will be discoverable using the `ListTagsForResource` API. Using this requires that the IAM role associated with the container instance have the `ec2:DescribeTags` action allowed. | `none` | `none` |
Expand Down
11 changes: 11 additions & 0 deletions agent/api/task/task_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ type PlatformFields struct {
// CpuUnbounded determines whether a mix of unbounded and bounded CPU tasks
// are allowed to run in the instance
CpuUnbounded bool `json:"cpuUnbounded"`
// RamUnbounded determines whether a mix of unbounded and bounded Memory tasks
// are allowed to run in the instance
RamUnbounded bool `json:"ramUnbounded"`
}

var cpuShareScaleFactor = runtime.NumCPU() * cpuSharesPerCore
Expand All @@ -51,6 +54,7 @@ func (task *Task) adjustForPlatform(cfg *config.Config) {
task.downcaseAllVolumePaths()
platformFields := PlatformFields{
CpuUnbounded: cfg.PlatformVariables.CPUUnbounded,
RamUnbounded: cfg.PlatformVariables.RAMUnbounded,
}
task.PlatformFields = platformFields
}
Expand Down Expand Up @@ -119,6 +123,13 @@ func (task *Task) platformHostConfigOverride(hostConfig *dockercontainer.HostCon
hostConfig.CPUPercent = minimumCPUPercent
}
hostConfig.CPUShares = 0

if hostConfig.Memory <= 0 && task.PlatformFields.RamUnbounded {
// As of version 17.06.2-ee-6 of docker. MemoryReservation is not supported on windows. This ensures that
// this parameter is not passed, allowing to launch a container without a hard limit.
hostConfig.MemoryReservation = 0
}

return nil
}

Expand Down
49 changes: 49 additions & 0 deletions agent/api/task/task_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ import (

const (
minDockerClientAPIVersion = dockerclient.Version_1_24

nonZeroMemoryReservationValue = 1
expectedMemoryReservationValue = 0
)

func TestPostUnmarshalWindowsCanonicalPaths(t *testing.T) {
Expand Down Expand Up @@ -254,6 +257,52 @@ func TestCPUPercentBasedOnUnboundedEnabled(t *testing.T) {
}
}

func TestWindowsMemoryReservationOption(t *testing.T) {
// Testing sending a task to windows overriding MemoryReservation value
rawHostConfigInput := dockercontainer.HostConfig{
Resources: dockercontainer.Resources{
MemoryReservation: nonZeroMemoryReservationValue,
},
}

rawHostConfig, err := json.Marshal(&rawHostConfigInput)
if err != nil {
t.Fatal(err)
}

testTask := &Task{
Arn: "arn:aws:ecs:us-east-1:012345678910:task/c09f0188-7f87-4b0f-bfc3-16296622b6fe",
Family: "myFamily",
Version: "1",
Containers: []*apicontainer.Container{
{
Name: "c1",
DockerConfig: apicontainer.DockerConfig{
HostConfig: strptr(string(rawHostConfig)),
},
},
},
PlatformFields: PlatformFields{
RamUnbounded: false,
},
}

// With RamUnbounded set to false, MemoryReservation is not overridden
config, configErr := testTask.DockerHostConfig(testTask.Containers[0], dockerMap(testTask), defaultDockerClientAPIVersion)
if configErr != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

this can be assert. same below

Copy link
Contributor

Choose a reason for hiding this comment

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

you can use require.NoError(t, err) if you want the exit behavior you get from t.fatal

Copy link
Contributor Author

Choose a reason for hiding this comment

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

t.Fatal(configErr)
}
assert.EqualValues(t, nonZeroMemoryReservationValue, config.MemoryReservation)

// With RamUnbounded set to true, tasks with no memory hard limit will have their memory reservation set to zero
testTask.PlatformFields.RamUnbounded = true
config, configErr = testTask.DockerHostConfig(testTask.Containers[0], dockerMap(testTask), defaultDockerClientAPIVersion)
if configErr != nil {
t.Fatal(configErr)
}
assert.EqualValues(t, expectedMemoryReservationValue, config.MemoryReservation)
}

func TestGetCanonicalPath(t *testing.T) {
testcases := []struct {
name string
Expand Down
3 changes: 3 additions & 0 deletions agent/config/config_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ func DefaultConfig() Config {
dataDir := filepath.Join(ecsRoot, "data")
platformVariables := PlatformVariables{
CPUUnbounded: false,
RAMUnbounded: false,
}
return Config{
DockerEndpoint: "npipe:////./pipe/docker_engine",
Expand Down Expand Up @@ -118,8 +119,10 @@ func (cfg *Config) platformOverrides() {
cfg.TaskCPUMemLimit = ExplicitlyDisabled

cpuUnbounded := utils.ParseBool(os.Getenv("ECS_ENABLE_CPU_UNBOUNDED_WINDOWS_WORKAROUND"), false)
ramUnbounded := utils.ParseBool(os.Getenv("ECS_ENABLE_RAM_UNBOUNDED_WINDOWS_WORKAROUND"), false)
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe these need unit tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added tests to check default config

platformVariables := PlatformVariables{
CPUUnbounded: cpuUnbounded,
RAMUnbounded: ramUnbounded,
}
cfg.PlatformVariables = platformVariables
}
Expand Down
3 changes: 3 additions & 0 deletions agent/config/types_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ type PlatformVariables struct {
// CPUUnbounded specifies if agent can run a mix of CPU bounded and
// unbounded tasks for windows
CPUUnbounded bool
// RAMUnbounded specifies if agent can run a mix of Memory bounded and
// unbounded tasks for windows
RAMUnbounded bool
}