如何解决将环境变量传递给我的 Amazon ECS 任务时出现的问题?

3 分钟阅读
0

我想解决将环境变量传递给我的 Amazon Elastic Container Service(Amazon ECS)任务时出现的问题。

简短描述

您可以通过以下方式之一在您的 Amazon ECS 任务中传递环境变量:

  • 将该变量作为 environmentFiles 对象传递到 Amazon Simple Storage Service(Amazon S3)桶中。
  • 将变量存储在 AWS Systems Manager Parameter Store 中。
  • 将变量存储在您的 ECS 任务定义中。
  • 将变量存储在 AWS Secrets Manager 中。

**注意:**使用 Parameter Store 或 Secrets Manager 将敏感数据存储为环境变量是一种安全最佳实践。使用以上方法传递环境变量时,可能会出现以下错误:

Parameter Store

“从区域中的 SSM Parameter Store 中获取机密数据: AccessDeniedException: 用户:arn:aws:sts::123456789:assumed-role/ecsExecutionRole/f512996041234a63ac354214 未获得授权,无法对以下资源执行 ssm:GetParameters:arn:aws:ssm:ap-south-1:12345678:parameter/状态代码: 400,请求 ID:e46b40ee-0a38-46da-aedd-05f23a41e861”

-或者-

“ResourceInitializationError:无法提取密钥或注册表身份验证:执行资源检索失败:无法从 asm 检索密钥:服务调用已重试 5 次: 请求已取消”

Secrets Manager

“ResourceInitializationError 错误”

-或者-

“Amazon Elastic Compute Cloud(Amazon EC2)出现 AccessDenied 错误”

要解决这些错误,请参阅如何解决 Amazon ECS 中存在的 AWS Secrets Manager 密钥相关问题?

Amazon S3

“ResourceInitializationError:无法下载 env 文件:文件下载命令:非空错误流”

在将环境变量传递给 Amazon ECS 任务时,可能会因为以下原因而遇到问题:

  • 您的 Amazon ECS 任务执行角色没有所需的 AWS Identity and Management(IAM)权限。
  • 您的网络配置有问题。
  • 您的应用程序无法读取环境变量。
  • 容器定义中的变量格式不正确。
  • 环境变量不会自动刷新。

若要对导致 Amazon ECS 任务无法启动的错误进行故障排除,请使用 AWSSupport-TroubleshootECSTaskFailedToStart 运行手册。请参照相关步骤,解决您遇到的问题。

解决方法

重要事项:

  • 在与您的 ECS 集群资源所在的同一 AWS 区域内使用 AWSSupport-TroubleshootECSTaskFailedToStart 运行手册。
  • 使用运行手册时,必须提供最近一次失败的任务的 ID。如果失败的任务是 Amazon ECS 服务的一部分,则在服务中使用最近一次失败的任务。在自动化执行期间,失败任务必须在 ECS:DescribeTasks 中可见。默认情况下,已停止的 ECS 任务在进入已停止状态后的 1 小时内保持可见。使用最近一次失败的任务的 ID 可避免在自动化过程中因为任务状态清理功能导致分析中断。

有关如何启动运行手册的说明,请参阅 AWSSupport-TroubleshootECSTaskFailedToStart。根据自动化的输出,从以下手动排查步骤中选择一种进行操作。

您的 Amazon ECS 任务执行角色没有所需的 IAM 权限

如果您在 Parameter Store 或 Secrets Manage 中使用环境变量,请查看 AWS CloudTrail 事件是否使用了以下 API 调用:

GetParameters(适用于 Parameter Store)

-或者-

GetSecretValue(适用于 Secrets Manager)

如果您注意到 CloudTrail 事件中的任务执行角色出现 AccessDenied 错误,请手动将所需权限作为内联策略添加到您的 ECS 任务执行 IAM 角色。您还可以创建客户管理型策略,并将该策略添加到您的 ECS 任务执行角色中。

如果您使用的是 Secrets Manager,请为您的任务执行角色添加以下权限:

{  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetSecretValue",
        "kms:Decrypt"
      ],
      "Resource": [
        "arn:aws:secretsmanager:example-region:11112222333344445555:secret:example-secret",
        "arn:aws:kms:example-region:1111222233334444:key/example-key-id"
      ]
    }
  ]
}

如果您使用的是 Parameter Store,请为您的任务执行角色提供以下权限:

{  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ssm:GetParameters",
        "secretsmanager:GetSecretValue",
        "kms:Decrypt"
      ],
      "Resource": [
        "arn:aws:ssm:example-region:1111222233334444:parameter/example-parameter",
        "arn:aws:secretsmanager:example-region:1111222233334444:secret:example-secret",
        "arn:aws:kms:example-region:1111222233334444:key/example-key-id"
      ]
    }
  ]
}

您可以使用 S3 桶将环境变量存储为 .env 文件。但是,您必须手动将以下权限作为内联策略添加到任务执行角色:

{  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject"
      ],
      "Resource": [
        "arn:aws:s3:::example-bucket/example-folder/example-env-file"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetBucketLocation"
      ],
      "Resource": [
        "arn:aws:s3:::example-bucket"
      ]
    }
  ]
}

您的网络配置有问题

如果您的 ECS 任务处于私有子网中,请确认以下几点:

  • 确保任务或服务的安全组允许端口 443 上的出口流量。
  • 如果您使用 VPC 端点,请确保网络访问控制列表(ACL)允许端口 443 上的出口流量。
  • 验证与 Systems Manager/Secrets Manager 和 Amazon S3 端点的连接。要执行此操作,请使用 telnet 命令。
  • 如果您使用 NAT 网关,请确保您的任务具有指向 NAT 网关的默认路由。
  • 为您的任务定义 VPC 端点。确认您拥有 Secrets Manager/Systems Manager Parameter StoreAmazon S3 所需的 VPC 端点。

如果您使用 VPC 端点,请确认以下几点:

  • 您的 VPC 端点的安全组允许来自端口 443 的任务或服务的出口流量。
  • 将 VPC 端点与对应的 VPC 关联。
  • 启用 VPC 属性 enableDnsHostnamesenableDnsSupport

如果您的 ECS 任务处于公有子网中,请确认以下几点:

  • 必须为该任务激活公有 IP 地址。
  • 确保您的 VPC 的安全组可以通过端口 443 对互联网进行出站访问。
  • 网络 ACL 配置允许所有流量流入子网和从子网流出到互联网。

您的应用程序无法读取环境变量

要检查任务容器内是否填充了正确的环境变量,请执行以下操作:

  1. 列出容器内公开的所有环境变量。
  2. 验证此列表是否包含在任务定义或 S3 的 .env 文件中定义的环境变量。

如果您使用的是 Amazon EC2 或 AWS Fargate 启动类型,那么最佳实践是使用 ECS Exec 功能。您可以使用此功能在运行在 Amazon EC2 实例或 Fargate 上的容器中运行命令或获取 Shell。启用此功能后,运行以下命令与您的容器进行交互:

aws ecs execute-command --cluster example-cluster \--task example-task-id \
--container example-container \
--interactive \
--command "/bin/sh"

如果您使用 Amazon EC2 启动类型,那么您也可以使用 Docker exec 命令与您的容器进行交互。此时,请完成以下步骤: 连接到正在运行任务的容器实例。然后,运行以下 Docker 命令来查找任务容器的容器 ID:

docker container ps

要与容器交互,请运行以下命令

docker exec -it example-container-id bash

**注意:**根据容器默认 Shell 选择相应 Shell。

与容器建立连接后,在容器上运行 env 命令以获取完整的环境变量列表。查看此列表,确保存在您在任务定义或 .env 文件中定义的环境变量。

容器定义中的变量格式不正确

在容器定义中定义环境变量时,将环境变量定义为 KeyValuePair 对象:

"environment": [{    "name": "foo",
    "value": "bar"
}]

.env 文件中定义环境变量时,请务必使用这种格式。

环境变量不会自动刷新

更新 .env 文件中的环境变量时,该变量不会在正在运行的容器中自动刷新。
要在任务中注入环境变量的更新值,请运行以下命令更新服务:

aws ecs update-service --cluster example-cluster --service example-service --force-new-deployment

如果您在容器定义中使用环境变量,则必须创建新的任务定义以刷新更新的环境变量。使用这一新的任务定义,可以创建新任务或更新 ECS 服务:

`aws ecs update-service --cluster example-cluster --service example-service --task-definition <family:revision>`;

**注意:**将环境变量传递给任务时,请记住以下几点:

  • 如果您在容器定义中使用 environment 参数指定环境变量,则这些环境变量优先于环境文件中包含的变量。
  • 如果您指定多个环境文件并且它们包含相同的变量,则它们按输入顺序进行处理。使用变量的第一个值,后续的重复变量值将被忽略。最佳做法是使用独一无二的变量名。
  • 如果您将环境文件指定为容器覆盖,则使用该文件。容器定义中指定的任何其他环境文件都将被忽略。
  • 环境变量可供来自文件 /proc/1/environ 的容器中的 PID 1 进程使用。如果容器运行了多个进程或 init 进程(例如包装器脚本或 supervisord),则环境变量对非 PID 1 进程不可用。

相关信息

将环境变量传递给容器

AWS 官方
AWS 官方已更新 1 年前