如何解决将环境变量传递给我的 Amazon ECS 任务时出现的问题?
我想解决将环境变量传递给我的 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 Store 和 Amazon S3 所需的 VPC 端点。
如果您使用 VPC 端点,请确认以下几点:
- 您的 VPC 端点的安全组允许来自端口 443 的任务或服务的出口流量。
- 将 VPC 端点与对应的 VPC 关联。
- 启用 VPC 属性 enableDnsHostnames 和 enableDnsSupport。
如果您的 ECS 任务处于公有子网中,请确认以下几点:
- 必须为该任务激活公有 IP 地址。
- 确保您的 VPC 的安全组可以通过端口 443 对互联网进行出站访问。
- 网络 ACL 配置允许所有流量流入子网和从子网流出到互联网。
您的应用程序无法读取环境变量
要检查任务容器内是否填充了正确的环境变量,请执行以下操作:
- 列出容器内公开的所有环境变量。
- 验证此列表是否包含在任务定义或 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 官方已更新 2 年前
- AWS 官方已更新 10 个月前
- AWS 官方已更新 2 年前