如何解决 Amazon ECS 中的“OutOfMemory”问题?
我想解决我的 Amazon Elastic Container Service (Amazon ECS) 任务中的内存使用问题。或者,由于“OutOfMemory”错误,Amazon ECS 任务中的容器退出了。
简短描述
默认情况下,容器没有资源限制,并且可以使用主机的内核调度器允许的任意数量的资源。使用 Docker 可以控制容器使用的内存量。切勿让正在运行的容器消耗主机的大部分内存。在 Linux 主机上,当内核检测到内存不足以执行重要的系统功能时,便会抛出 OutOfMemory 异常。然后,内核将结束进程以释放内存。
在 Docker 中,您可以使用以下任一内存限制:
- 硬内存限制:允许容器使用不超过一定数量的用户或系统内存
- 软限制:允许容器使用必要的内存,除非出现某些情况,例如内存不足或主机争用
当 Amazon ECS 任务因 OutOfMemory 错误而结束时,Amazon ECS 控制台可能会显示以下错误消息。要查看消息,请选择任务 ID,然后参阅详细信息部分以查看容器的详细信息:
OutOfMemoryError: Container killed due to memory usage
在这种情况下,任务中的容器会退出,因为容器的进程消耗的内存超过了任务定义中分配的内存量。
解决方法
要排除 Amazon ECS 任务中的“OutOfMemory”错误,请完成以下步骤:
- 在 Amazon ECS 控制台中检查已停止的任务是否存在错误。在停止原因字段中查看是否显示错误代码 OutOfMemory。
- 打开任务的 Amazon CloudWatch Logs,以调试由于内存使用情况而出现的应用程序级别问题。
- 在 Amazon ECS 控制台或 CloudWatch 控制台中查看服务的内存使用情况。
- 使用 CloudWatch Container Insights 监控内存使用情况。要查看某个容器在特定时间段内的内存使用情况,请使用类似于以下示例的查询:
stats max(MemoryUtilized) as mem, max(MemoryReserved ) as memreserved by bin (5m) as period, TaskId, ContainerName| sort period desc | filter ContainerName like "example-container-name" | filter TaskId = "example-task-id"
要降低由于 OutOfMemory 错误导致任务不稳定的风险,请完成以下步骤:
- 在将应用程序投入生产之前,执行测试以了解应用程序的内存需求。您可以在主机或服务器内的容器上执行负载测试。然后,使用 docker stats(从 Docker Docs 网站)检查容器的内存使用情况。
- 确保仅在资源充足的主机上运行应用程序。
- 限制容器可以使用的内存量。为容器的硬限制和软限制设置适当的值。Amazon ECS 使用多个参数为任务分配内存:memoryReservation 用于软限制,memory 用于硬限制。指定这些值后,容器所在容器实例的可用内存资源便会扣除相应数量。**注意:**Windows 容器不支持 memoryReservation 参数。
- 您可以为具有高瞬态内存需求的容器启用交换功能。这样做可以降低容器处于高负载状态时出现 OutOfMemory 错误的几率。**注意:**如果所用任务使用 AWS Fargate 启动类型,则不支持参数 maxSwap 和 sharedMemorySize。**重要事项:**在 Docker 主机上配置交换功能时需谨慎。启用交换功能可能会减慢应用程序的速度并降低其性能。但是,此功能可防止应用程序耗尽系统内存。
要检测因 OutOfMemory 事件而结束的 Amazon ECS 任务,请使用以下 AWS CloudFormation 模板。使用此模板可以创建 Amazon EventBridge 规则、Amazon Simple Notification Service (Amazon SNS) 主题和 Amazon SNS 主题策略。运行模板时,模板会要求提供电子邮件列表、主题名称和用于开启或关闭监控的标记:
AWSTemplateFormatVersion: 2010-09-09 Description: > - Monitor OOM Stopped Tasks with EventBridge rules with AWS CloudFormation. Parameters: EmailList: Type: String Description: "Email to notify!" AllowedPattern: '[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[a-zA-Z]+' Default: "mail@example.com" SNSTopicName: Type: String Description: "Name for the notification topic." AllowedPattern: '[a-zA-Z0-9_-]+' Default: "oom-monitoring-topic" MonitorStatus: Type: String Description: "Enable / Disable monitor." AllowedValues: - ENABLED - DISABLED Default: ENABLED Resources: SNSMonitoringTopic: Type: AWS::SNS::Topic Properties: Subscription: - Endpoint: !Ref EmailList Protocol: email TopicName: !Sub ${AWS::StackName}-${SNSTopicName} SNSMonitoringTopicTopicPolicy: Type: AWS::SNS::TopicPolicy Properties: Topics: - !Ref SNSMonitoringTopic PolicyDocument: Version: '2012-10-17' Statement: - Sid: SnsOOMTopicPolicy Effect: Allow Principal: Service: events.amazonaws.com Action: [ 'sns:Publish' ] Resource: !Ref SNSMonitoringTopic - Sid: AllowAccessToTopicOwner Effect: Allow Principal: AWS: '*' Action: [ 'sns:GetTopicAttributes', 'sns:SetTopicAttributes', 'sns:AddPermission', 'sns:RemovePermission', 'sns:DeleteTopic', 'sns:Subscribe', 'sns:ListSubscriptionsByTopic', 'sns:Publish', 'sns:Receive' ] Resource: !Ref SNSMonitoringTopic Condition: StringEquals: 'AWS:SourceOwner': !Ref 'AWS::AccountId' EventRule: Type: AWS::Events::Rule Properties: Name: ECSStoppedTasksEvent Description: Triggered when an Amazon ECS Task is stopped EventPattern: source: - aws.ecs detail-type: - ECS Task State Change detail: desiredStatus: - STOPPED lastStatus: - STOPPED containers: reason: - prefix: "OutOfMemory" State: !Ref MonitorStatus Targets: - Arn: !Ref SNSMonitoringTopic Id: ECSOOMStoppedTasks InputTransformer: InputPathsMap: taskArn: $.detail.taskArn InputTemplate: > "Task '<taskArn>' was stopped due to OutOfMemory."
创建 CloudFormation 堆栈后,验证电子邮件以确认订阅。任务因 OutOfMemory 问题而结束后,系统会向您发送一封电子邮件,其中包含类似于以下示例的消息:
"Task 'arn:aws:ecs:eu-west-1:555555555555:task/ECSFargate/0123456789abcdef0123456789abcdef' was stopped due to OutOfMemory."
相关信息
相关内容
- AWS 官方已更新 3 年前
- AWS 官方已更新 4 年前