From f546d83d3ae20da75a5ed82fddc80184bcd26c02 Mon Sep 17 00:00:00 2001 From: Prateek Chaudhry Date: Thu, 22 Feb 2024 12:14:07 -0800 Subject: [PATCH] Use ECS_EBSTA_SUPPORTED env variable to add EBSTA capabilities (#4091) --- README.md | 1 + agent/app/agent_capability.go | 6 ++++-- agent/config/config.go | 1 + agent/config/types.go | 5 +++++ ecs-init/docker/docker.go | 8 ++++++++ ecs-init/engine/engine.go | 4 +++- 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1e9eb67a658..0f5cd1bd403 100644 --- a/README.md +++ b/README.md @@ -258,6 +258,7 @@ additional details on each available environment variable. | `CREDENTIALS_FETCHER_SECRET_NAME_FOR_DOMAINLESS_GMSA` | `secretmanager-secretname` | Used to support scaling option for gMSA on Linux [credentials-fetcher daemon](https://github.com/aws/credentials-fetcher). If user is configuring gMSA on a non-domain joined instance, they need to create an Active Directory user with access to retrieve principals for the gMSA account and store it in secrets manager | `secretmanager-secretname` | Not Applicable | | `ECS_DYNAMIC_HOST_PORT_RANGE` | `100-200` | This specifies the dynamic host port range that the agent uses to assign host ports from, for container ports mapping. If there are no available ports in the range for containers, including customer containers and Service Connect Agent containers (if Service Connect is enabled), service deployments would fail. | Defined by `/proc/sys/net/ipv4/ip_local_port_range` | `49152-65535` | | `ECS_TASK_PIDS_LIMIT` | `100` | Specifies the per-task pids limit cgroup setting for each task launched on the container instance. This setting maps to the pids.max cgroup setting at the ECS task level. See https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html#pid. If unset, pids will be unlimited. Min value is 1 and max value is 4194304 (4*1024*1024) | `unset` | Not Supported on Windows | +| `ECS_EBSTA_SUPPORTED` | `true` | Whether to use the container instance with EBS Task Attach support. ecs-init sets this variable for the ECS Agent if the instance can support mounting EBS volumes or not. ECS only schedules EBSTA tasks if this feature is supported by the platform type | `true` | `true` | Additionally, the following environment variable(s) can be used to configure the behavior of the ecs-init service. When using ECS-Init, all env variables, including the ECS Agent variables above, are read from path `/etc/ecs/ecs.config`: | Environment Variable Name | Example Value(s) | Description | Default value | diff --git a/agent/app/agent_capability.go b/agent/app/agent_capability.go index aef94844aad..69fe173d3a4 100644 --- a/agent/app/agent_capability.go +++ b/agent/app/agent_capability.go @@ -295,8 +295,10 @@ func (agent *ecsAgent) capabilities() ([]*ecs.Attribute, error) { // add service-connect capabilities if applicable capabilities = agent.appendServiceConnectCapabilities(capabilities) - // add ebs-task-attach attribute if applicable - capabilities = agent.appendEBSTaskAttachCapabilities(capabilities) + if agent.cfg.EBSTASupportEnabled { + // add ebs-task-attach attribute if applicable + capabilities = agent.appendEBSTaskAttachCapabilities(capabilities) + } if agent.cfg.External.Enabled() { // Add external specific capability; remove external unsupported capabilities. diff --git a/agent/config/config.go b/agent/config/config.go index 9350c04909f..97737c9ef7b 100644 --- a/agent/config/config.go +++ b/agent/config/config.go @@ -582,6 +582,7 @@ func environmentConfig() (Config, error) { PollingMetricsWaitDuration: parseEnvVariableDuration("ECS_POLLING_METRICS_WAIT_DURATION"), DisableDockerHealthCheck: parseBooleanDefaultFalseConfig("ECS_DISABLE_DOCKER_HEALTH_CHECK"), GPUSupportEnabled: utils.ParseBool(os.Getenv("ECS_ENABLE_GPU_SUPPORT"), false), + EBSTASupportEnabled: utils.ParseBool(os.Getenv("ECS_EBSTA_SUPPORTED"), true), InferentiaSupportEnabled: utils.ParseBool(os.Getenv("ECS_ENABLE_INF_SUPPORT"), false), NvidiaRuntime: os.Getenv("ECS_NVIDIA_RUNTIME"), TaskMetadataAZDisabled: utils.ParseBool(os.Getenv("ECS_DISABLE_TASK_METADATA_AZ"), false), diff --git a/agent/config/types.go b/agent/config/types.go index ced906727c5..03fe9d2d8d4 100644 --- a/agent/config/types.go +++ b/agent/config/types.go @@ -301,6 +301,11 @@ type Config struct { // GPUSupportEnabled specifies if the Agent is capable of launching GPU tasks GPUSupportEnabled bool + + // EBSTASupportEnabled specifies if the Agent can support tasks needing EBS Task Attach, set in ecs-init + // Initially Agent always advertised EBSTA capability. This defaults to true to make it compatible with older ecs-init + EBSTASupportEnabled bool + // InferentiaSupportEnabled specifies whether the built-in support for inferentia task is enabled. InferentiaSupportEnabled bool diff --git a/ecs-init/docker/docker.go b/ecs-init/docker/docker.go index 423e6ec063a..a2d836795b4 100644 --- a/ecs-init/docker/docker.go +++ b/ecs-init/docker/docker.go @@ -290,6 +290,7 @@ func (c *client) getContainerConfig(envVarsFromFiles map[string]string) *godocke "ECS_AVAILABLE_LOGGING_DRIVERS": `["json-file","syslog","awslogs","fluentd","none"]`, "ECS_ENABLE_TASK_IAM_ROLE": "true", "ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST": "true", + "ECS_EBSTA_SUPPORTED": "true", "ECS_AGENT_LABELS": "", "ECS_VOLUME_PLUGIN_CAPABILITIES": `["efsAuth"]`, } @@ -327,6 +328,13 @@ func (c *client) getContainerConfig(envVarsFromFiles map[string]string) *godocke envVariables["ECS_ENABLE_TASK_ENI"] = "false" } + if !isPathValid(config.MountDirectoryEBS(), true) { + // EBS Task Attach (EBSTA) is not supported for external instances + // If EBS mount directory fails to get created, tasks requiring EBSTA can not be supported + // Disable EBSTA Support for these cases + envVariables["ECS_EBSTA_SUPPORTED"] = "false" + } + var env []string for envKey, envValue := range envVariables { env = append(env, envKey+"="+envValue) diff --git a/ecs-init/engine/engine.go b/ecs-init/engine/engine.go index cdaa7d19d28..df667a68bb8 100644 --- a/ecs-init/engine/engine.go +++ b/ecs-init/engine/engine.go @@ -145,7 +145,9 @@ func (e *Engine) PreStart() error { // Add the EBS Task Attach host mount point err = os.MkdirAll(config.MountDirectoryEBS(), mountFilePermission) if err != nil { - return engineError("could not create EBS mount directory", err) + // Log error and continue + // If directory creation fails, set ECS_EBSTA_SUPPORTED=false in docker/docker.go + log.Error("could not create EBS mount directory", err) } docker, err := getDockerClient()