Skip to content

Commit 5b06275

Browse files
committed
Support Unified Cgroups (cgroups v2) (aws#3127)
* Support Unified Cgroups (cgroups v2) closes aws/containers-roadmap#1535 closes aws#3117 This adds support for task-level resource limits when running on unified cgroups (aka cgroups v2) with the systemd cgroup driver. Cgroups v2 has introduced a cgroups format that is not backward compatible with cgroups v1. In order to support both v1 and v2, we have added a config variable to detect which cgroup version the ecs agent is running with. The containerd/cgroups library is used to determine which mode it is using on agent startup. Cgroups v2 no longer can provide per-cpu usage stats, so this validation was removed since we never used it either. * wip * update cgroups library with nil panic bugfix * Initialize and toggle cgroup controllers
1 parent d5041e2 commit 5b06275

File tree

151 files changed

+18886
-7489
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

151 files changed

+18886
-7489
lines changed

agent/api/task/task_linux.go

+23-2
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,34 @@ func (task *Task) initializeCgroupResourceSpec(cgroupPath string, cGroupCPUPerio
7878
}
7979

8080
// BuildCgroupRoot helps build the task cgroup prefix
81-
// Example: /ecs/task-id
81+
// Example v1: /ecs/task-id
82+
// Example v2: ecstasks-$TASKID.slice
8283
func (task *Task) BuildCgroupRoot() (string, error) {
8384
taskID, err := utils.TaskIdFromArn(task.Arn)
8485
if err != nil {
8586
return "", err
8687
}
87-
return filepath.Join(config.DefaultTaskCgroupPrefix, taskID), nil
88+
89+
if config.CgroupV2 {
90+
return buildCgroupV2Root(taskID), nil
91+
}
92+
return buildCgroupV1Root(taskID), nil
93+
}
94+
95+
func buildCgroupV1Root(taskID string) string {
96+
return filepath.Join(config.DefaultTaskCgroupV1Prefix, taskID)
97+
}
98+
99+
// buildCgroupV2Root creates a root cgroup using the systemd driver's special "-"
100+
// character. The "-" specifies a parent slice, so tasks and their containers end up
101+
// looking like this in the cgroup directory:
102+
// /sys/fs/cgroup/ecstasks.slice/
103+
// ├── ecstasks-XXXXf406f70c4c678073ae96944fXXXX.slice
104+
// │ └── docker-XXXX7c6dc81f2e9a8bf1c566dc769733ccba594b3007dd289a0f50ad7923XXXX.scope
105+
// └── ecstasks-XXXX30467358463ab6bbba4e73afXXXX.slice
106+
// └── docker-XXXX7ef4e942552437c96051356859c1df169f16e1cf9a9fc96fd30614e6XXXX.scope
107+
func buildCgroupV2Root(taskID string) string {
108+
return fmt.Sprintf("%s-%s.slice", config.DefaultTaskCgroupV2Prefix, taskID)
88109
}
89110

90111
// BuildLinuxResourceSpec returns a linuxResources object for the task cgroup

agent/api/task/task_linux_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,16 @@ func TestBuildCgroupRootErrorPath(t *testing.T) {
244244
assert.Empty(t, cgroupRoot)
245245
}
246246

247+
func TestBuildCgroupV1Root(t *testing.T) {
248+
cgroupRoot := buildCgroupV1Root("111mytaskid")
249+
assert.Equal(t, "/ecs/111mytaskid", cgroupRoot)
250+
}
251+
252+
func TestBuildCgroupV2Root(t *testing.T) {
253+
cgroupRoot := buildCgroupV2Root("111mytaskid")
254+
assert.Equal(t, "ecstasks-111mytaskid.slice", cgroupRoot)
255+
}
256+
247257
// TestBuildLinuxResourceSpecCPUMem validates the linux resource spec builder
248258
func TestBuildLinuxResourceSpecCPUMem(t *testing.T) {
249259
taskMemoryLimit := int64(taskMemoryLimit)

agent/config/config.go

+3
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ var (
187187
// DefaultPauseContainerTag is the tag for the pause container image. The linker's load
188188
// flags are used to populate this value from the Makefile
189189
DefaultPauseContainerTag = ""
190+
191+
// CgroupV2 Specifies whether or not to run in Cgroups V2 mode.
192+
CgroupV2 = false
190193
)
191194

192195
// Merge merges two config files, preferring the ones on the left. Any nil or

agent/taskresource/cgroup/control/init_linux.go renamed to agent/config/config_linux.go

+5-17
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,14 @@
1313
// express or implied. See the License for the specific language governing
1414
// permissions and limitations under the License.
1515

16-
package control
16+
package config
1717

1818
import (
19-
"github.com/aws/amazon-ecs-agent/agent/config"
20-
"github.com/aws/amazon-ecs-agent/agent/logger"
21-
22-
specs "github.com/opencontainers/runtime-spec/specs-go"
19+
"github.com/containerd/cgroups"
2320
)
2421

25-
// Init is used to setup the cgroup root for ecs
26-
func (c *control) Init() error {
27-
logger.Info("Creating root ecs cgroup", logger.Fields{
28-
"cgroup": config.DefaultTaskCgroupPrefix,
29-
})
30-
31-
// Build cgroup spec
32-
cgroupSpec := &Spec{
33-
Root: config.DefaultTaskCgroupPrefix,
34-
Specs: &specs.LinuxResources{},
22+
func init() {
23+
if cgroups.Mode() == cgroups.Unified {
24+
CgroupV2 = true
3525
}
36-
_, err := c.Create(cgroupSpec)
37-
return err
3826
}

agent/config/config_unix.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,13 @@ const (
3333
// defaultRuntimeStatsLogFile stores the path where the golang runtime stats are periodically logged
3434
defaultRuntimeStatsLogFile = `/log/agent-runtime-stats.log`
3535

36-
// DefaultTaskCgroupPrefix is default cgroup prefix for ECS tasks
37-
DefaultTaskCgroupPrefix = "/ecs"
36+
// DefaultTaskCgroupV1Prefix is default cgroup v1 prefix for ECS tasks
37+
DefaultTaskCgroupV1Prefix = "/ecs"
38+
// DefaultTaskCgroupV2Prefix is default cgroup v2 prefix for ECS tasks
39+
// ecstasks is used because this creates a systemd "slice", and using just
40+
// ecs would create a confusing name conflict with the ecs systemd service.
41+
// (we would have both ecs.service and ecs.slice in /sys/fs/cgroup).
42+
DefaultTaskCgroupV2Prefix = "ecstasks"
3843

3944
// Default cgroup memory system root path, this is the default used if the
4045
// path has not been configured through ECS_CGROUP_PATH

agent/engine/docker_task_engine_linux_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func TestResourceContainerProgression(t *testing.T) {
101101
gomock.InOrder(
102102
// Ensure that the resource is created first
103103
mockControl.EXPECT().Exists(gomock.Any()).Return(false),
104-
mockControl.EXPECT().Create(gomock.Any()).Return(nil, nil),
104+
mockControl.EXPECT().Create(gomock.Any()).Return(nil),
105105
mockIO.EXPECT().WriteFile(cgroupMemoryPath, gomock.Any(), gomock.Any()).Return(nil),
106106
imageManager.EXPECT().AddAllImageStates(gomock.Any()).AnyTimes(),
107107
client.EXPECT().PullImage(gomock.Any(), sleepContainer.Image, nil, gomock.Any()).Return(dockerapi.DockerContainerMetadata{}),
@@ -263,7 +263,7 @@ func TestResourceContainerProgressionFailure(t *testing.T) {
263263
gomock.InOrder(
264264
// resource creation failure
265265
mockControl.EXPECT().Exists(gomock.Any()).Return(false),
266-
mockControl.EXPECT().Create(gomock.Any()).Return(nil, errors.New("cgroup create error")),
266+
mockControl.EXPECT().Create(gomock.Any()).Return(errors.New("cgroup create error")),
267267
)
268268
mockTime.EXPECT().Now().Return(time.Now()).AnyTimes()
269269

@@ -345,7 +345,7 @@ func TestTaskCPULimitHappyPath(t *testing.T) {
345345
},
346346
}
347347
mockControl.EXPECT().Exists(gomock.Any()).Return(false)
348-
mockControl.EXPECT().Create(gomock.Any()).Return(nil, nil)
348+
mockControl.EXPECT().Create(gomock.Any()).Return(nil)
349349
mockIO.EXPECT().WriteFile(cgroupMemoryPath, gomock.Any(), gomock.Any()).Return(nil)
350350
}
351351

agent/go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require (
77
github.com/aws/aws-sdk-go v1.36.0
88
github.com/awslabs/go-config-generator-for-fluentd-and-fluentbit v0.0.0-20190829210224-55d4fd2e6f35
99
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575
10-
github.com/containerd/cgroups v1.0.3
10+
github.com/containerd/cgroups v1.0.4-0.20220221221032-e710ed6ebb1a
1111
github.com/containerd/containerd v1.4.12 // indirect
1212
github.com/containerd/continuity v0.0.0-20181023183536-c220ac4f01b8 // indirect
1313
github.com/containernetworking/cni v0.7.1

agent/go.sum

+10
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,16 @@ github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7
2020
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
2121
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 h1:kHaBemcxl8o/pQ5VM1c8PVE1PubbNx3mjUr09OqWGCs=
2222
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575/go.mod h1:9d6lWj8KzO/fd/NrVaLscBKmPigpZpn5YawRPw+e3Yo=
23+
github.com/cilium/ebpf v0.4.0 h1:QlHdikaxALkqWasW8hAC1mfR0jdmvbfaBdBPFmRSglA=
2324
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
2425
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
2526
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
2627
github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4=
2728
github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8=
29+
github.com/containerd/cgroups v1.0.4-0.20220217190539-cf1b326d3714 h1:jCXPr1wkugK8p7oEQjuP8hBB7Q8Abq3w4ELsSs/0IwU=
30+
github.com/containerd/cgroups v1.0.4-0.20220217190539-cf1b326d3714/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8=
31+
github.com/containerd/cgroups v1.0.4-0.20220221221032-e710ed6ebb1a h1:e956Q1zTD3IIKTQPWb92C20PvU3S2ohP9jWqqD0JJWE=
32+
github.com/containerd/cgroups v1.0.4-0.20220221221032-e710ed6ebb1a/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8=
2833
github.com/containerd/containerd v1.4.12 h1:V+SHzYmhng/iju6M5nFrpTTusrhidoxKTwdwLw+u4c4=
2934
github.com/containerd/containerd v1.4.12/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
3035
github.com/containerd/continuity v0.0.0-20181023183536-c220ac4f01b8 h1:lJeDcldQnYskl7krc3lTppg8NKomoQkmQg1AzOXtQbA=
@@ -62,6 +67,7 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
6267
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
6368
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
6469
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
70+
github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
6571
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
6672
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
6773
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@@ -102,8 +108,10 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGi
102108
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
103109
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
104110
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
111+
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
105112
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
106113
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
114+
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
107115
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
108116
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
109117
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
@@ -156,13 +164,15 @@ github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936 h1:J9gO8RJCAFlln
156164
github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
157165
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
158166
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
167+
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
159168
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
160169
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3 h1:f4/ZD59VsBOaJmWeI2yqtHvJhmRRPzi73C88ZtfhAIk=
161170
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
162171
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
163172
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
164173
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
165174
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
175+
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
166176
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
167177
golang.org/x/net v0.0.0-20191204025024-5ee1b9f4859a h1:+HHJiFUXVOIS9mr1ThqkQD1N8vpFCfCShqADBM12KTc=
168178
golang.org/x/net v0.0.0-20191204025024-5ee1b9f4859a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=

agent/stats/utils_unix.go

+11-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package stats
1818
import (
1919
"fmt"
2020

21+
"github.com/aws/amazon-ecs-agent/agent/config"
2122
"github.com/cihub/seelog"
2223
"github.com/docker/docker/api/types"
2324
)
@@ -39,9 +40,16 @@ func dockerStatsToContainerStats(dockerStats *types.StatsJSON) (*ContainerStats,
3940
}
4041

4142
func validateDockerStats(dockerStats *types.StatsJSON) error {
42-
// The length of PercpuUsage represents the number of cores in an instance.
43-
if len(dockerStats.CPUStats.CPUUsage.PercpuUsage) == 0 || numCores == uint64(0) {
44-
return fmt.Errorf("invalid container statistics reported, no cpu core usage reported")
43+
if config.CgroupV2 {
44+
// PercpuUsage is not available in cgroupv2
45+
if numCores == uint64(0) {
46+
return fmt.Errorf("invalid number of cores returned from runtime.NumCPU, numCores=0")
47+
}
48+
} else {
49+
// The length of PercpuUsage represents the number of cores in an instance.
50+
if len(dockerStats.CPUStats.CPUUsage.PercpuUsage) == 0 || numCores == uint64(0) {
51+
return fmt.Errorf("invalid container statistics reported, no cpu core usage reported")
52+
}
4553
}
4654
return nil
4755
}

agent/stats/utils_unix_test.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ func TestDockerStatsToContainerStatsEmptyCpuUsageGeneratesError(t *testing.T) {
5252
jsonBytes, _ := ioutil.ReadFile(inputJsonFile)
5353
dockerStat := &types.StatsJSON{}
5454
json.Unmarshal([]byte(jsonBytes), dockerStat)
55-
// empty the PercpuUsage array
56-
dockerStat.CPUStats.CPUUsage.PercpuUsage = make([]uint64, 0)
55+
prevNumCores := numCores
56+
numCores = uint64(0)
5757
err := validateDockerStats(dockerStat)
58-
assert.Error(t, err, "expected error converting container stats with empty PercpuUsage")
58+
assert.Error(t, err, "expected error converting container stats with numCores=0")
59+
numCores = prevNumCores
5960
}

agent/taskresource/cgroup/cgroup.go

+17-12
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
apicontainer "github.com/aws/amazon-ecs-agent/agent/api/container"
2929
apicontainerstatus "github.com/aws/amazon-ecs-agent/agent/api/container/status"
3030
"github.com/aws/amazon-ecs-agent/agent/api/task/status"
31+
"github.com/aws/amazon-ecs-agent/agent/config"
3132
"github.com/aws/amazon-ecs-agent/agent/taskresource"
3233
control "github.com/aws/amazon-ecs-agent/agent/taskresource/cgroup/control"
3334
resourcestatus "github.com/aws/amazon-ecs-agent/agent/taskresource/status"
@@ -71,12 +72,14 @@ type CgroupResource struct {
7172
}
7273

7374
// NewCgroupResource is used to return an object that implements the Resource interface
74-
func NewCgroupResource(taskARN string,
75+
func NewCgroupResource(
76+
taskARN string,
7577
control control.Control,
7678
ioutil ioutilwrapper.IOUtil,
7779
cgroupRoot string,
7880
cgroupMountPath string,
79-
resourceSpec specs.LinuxResources) *CgroupResource {
81+
resourceSpec specs.LinuxResources,
82+
) *CgroupResource {
8083
c := &CgroupResource{
8184
taskARN: taskARN,
8285
control: control,
@@ -256,18 +259,17 @@ func (cgroup *CgroupResource) GetCreatedAt() time.Time {
256259
func (cgroup *CgroupResource) Create() error {
257260
err := cgroup.setupTaskCgroup()
258261
if err != nil {
259-
seelog.Criticalf("Cgroup resource [%s]: unable to setup cgroup root: %v", cgroup.taskARN, err)
262+
// this error is already formatted in setupTaskCgroup function
260263
return err
261264
}
262265
return nil
263266
}
264267

265268
func (cgroup *CgroupResource) setupTaskCgroup() error {
266269
cgroupRoot := cgroup.cgroupRoot
267-
seelog.Debugf("Cgroup resource [%s]: setting up cgroup at: %s", cgroup.taskARN, cgroupRoot)
268270

269271
if cgroup.control.Exists(cgroupRoot) {
270-
seelog.Debugf("Cgroup resource [%s]: cgroup at %s already exists, skipping creation", cgroup.taskARN, cgroupRoot)
272+
seelog.Debugf("Cgroup already exists, skipping creation taskARN=%s cgroupPath=%s cgroupV2=%v", cgroup.taskARN, cgroupRoot, config.CgroupV2)
271273
return nil
272274
}
273275

@@ -276,16 +278,19 @@ func (cgroup *CgroupResource) setupTaskCgroup() error {
276278
Specs: &cgroup.resourceSpec,
277279
}
278280

279-
_, err := cgroup.control.Create(&cgroupSpec)
281+
seelog.Infof("Creating task cgroup taskARN=%s cgroupPath=%s cgroupV2=%v", cgroup.taskARN, cgroupRoot, config.CgroupV2)
282+
err := cgroup.control.Create(&cgroupSpec)
280283
if err != nil {
281-
return fmt.Errorf("cgroup resource [%s]: setup cgroup: unable to create cgroup at %s: %w", cgroup.taskARN, cgroupRoot, err)
284+
return fmt.Errorf("cgroup resource: setup cgroup: unable to create cgroup taskARN=%s cgroupPath=%s cgroupV2=%v err=%s", cgroup.taskARN, cgroupRoot, config.CgroupV2, err)
282285
}
283286

284-
// enabling cgroup memory hierarchy by doing 'echo 1 > memory.use_hierarchy'
285-
memoryHierarchyPath := filepath.Join(cgroup.cgroupMountPath, memorySubsystem, cgroupRoot, memoryUseHierarchy)
286-
err = cgroup.ioutil.WriteFile(memoryHierarchyPath, enableMemoryHierarchy, rootReadOnlyPermissions)
287-
if err != nil {
288-
return fmt.Errorf("cgroup resource [%s]: setup cgroup: unable to set use hierarchy flag: %w", cgroup.taskARN, err)
287+
if !config.CgroupV2 {
288+
// enabling cgroup memory hierarchy by doing 'echo 1 > memory.use_hierarchy'
289+
memoryHierarchyPath := filepath.Join(cgroup.cgroupMountPath, memorySubsystem, cgroupRoot, memoryUseHierarchy)
290+
err = cgroup.ioutil.WriteFile(memoryHierarchyPath, enableMemoryHierarchy, rootReadOnlyPermissions)
291+
if err != nil {
292+
return fmt.Errorf("cgroup resource: setup cgroup: unable to set use hierarchy flag taskARN=%s cgroupPath=%s cgroupV2=%v err=%s", cgroup.taskARN, cgroupRoot, config.CgroupV2, err)
293+
}
289294
}
290295

291296
return nil

agent/taskresource/cgroup/cgroup_test.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"time"
2323

2424
cgroup "github.com/aws/amazon-ecs-agent/agent/taskresource/cgroup/control"
25-
mock_cgroups "github.com/aws/amazon-ecs-agent/agent/taskresource/cgroup/control/factory/mock"
2625
"github.com/aws/amazon-ecs-agent/agent/taskresource/cgroup/control/mock_control"
2726
resourcestatus "github.com/aws/amazon-ecs-agent/agent/taskresource/status"
2827
mock_ioutilwrapper "github.com/aws/amazon-ecs-agent/agent/utils/ioutilwrapper/mocks"
@@ -53,7 +52,7 @@ func TestCreateHappyPath(t *testing.T) {
5352

5453
gomock.InOrder(
5554
mockControl.EXPECT().Exists(gomock.Any()).Return(false),
56-
mockControl.EXPECT().Create(gomock.Any()).Return(nil, nil),
55+
mockControl.EXPECT().Create(gomock.Any()).Return(nil),
5756
mockIO.EXPECT().WriteFile(cgroupMemoryPath, gomock.Any(), gomock.Any()).Return(nil),
5857
)
5958
cgroupResource := NewCgroupResource("taskArn", mockControl, mockIO, cgroupRoot, cgroupMountPath, specs.LinuxResources{})
@@ -83,13 +82,12 @@ func TestCreateCgroupError(t *testing.T) {
8382

8483
mockControl := mock_control.NewMockControl(ctrl)
8584
mockIO := mock_ioutilwrapper.NewMockIOUtil(ctrl)
86-
mockCgroup := mock_cgroups.NewMockCgroup(ctrl)
8785

8886
cgroupRoot := fmt.Sprintf("/ecs/%s", taskID)
8987

9088
gomock.InOrder(
9189
mockControl.EXPECT().Exists(gomock.Any()).Return(false),
92-
mockControl.EXPECT().Create(gomock.Any()).Return(mockCgroup, errors.New("cgroup create error")),
90+
mockControl.EXPECT().Create(gomock.Any()).Return(errors.New("cgroup create error")),
9391
)
9492

9593
cgroupResource := NewCgroupResource("taskArn", mockControl, mockIO, cgroupRoot, cgroupMountPath, specs.LinuxResources{})

0 commit comments

Comments
 (0)