如何對 Amazon ECS 中出現的 OutOfMemory 錯誤進行疑難排解?

上次更新日期:2022 年 9 月 16 日

我想對 Amazon Elastic Container Service (Amazon ECS) 任務中出現的記憶體用量問題進行疑難排解。

-或-

由於 OutOfMemory 錯誤,我的 Amazon ECS 任務中的容器正在退出。

簡短描述

依預設,容器沒有資源限制,並且可使用主機內核排程器允許的資源。使用 Docker,您可以控制容器使用的記憶體量。請務必不要允許運行中容器佔用主機的大部分記憶體。在 Linux 主機上,當內核偵測到記憶體不足,無法執行重要的系統功能時,會引發 OutOfMemory 異常狀況,並開始結束進程以釋放記憶體。

透過 Docker,您可以使用以下任一選項:

  • 硬記憶體限制,允許容器使用不超過一定量的使用者或系統記憶體
  • 軟限制,允許容器視需使用盡可能多的記憶體,除非發生某些情況 (如記憶體不足或主機上的爭用)

當 Amazon ECS 任務因 OutOfMemory 問題而結束時,您可能會收到以下錯誤訊息:

OutOfMemoryError: Container killed due to memory usage

當任務中的容器退出時,您會出現此錯誤,因為容器中的進程取用的記憶體超過任務定義中分配的量。

解決方案

若要解決 Amazon ECS 任務中的 OutOfMemory 錯誤,請執行以下操作:

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 統計資料檢查容器的記憶體使用情況。
  • 確保應用程式僅在具有足夠資源的主機上執行。
  • 限制容器可使用的記憶體量。您可以為容器設定適當的硬限制和軟限制值,來完成此操作。Amazon ECS 使用幾項參數來將記憶體分配給任務:memoryReservation 用於軟限制,memory 用於硬限制。指定這些值後,將會從容器所在的容器執行個體可用記憶體資源中減去這些值。
    注意:Windows 容器不支援 memoryReservation 參數。
  • 您可以為具有較高暫時性記憶體需求的容器開啟 swap (交換) 功能。這樣做可以減少容器在較高負載下出現 OutOfMemory 錯誤的機率。
    注意:如果您使用的任務採用 AWS Fargate 啟動類型,則不支援 maxSwapsharedMemorySize 參數。
    重要提示:在 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."

此文章是否有幫助?


Precisa de ajuda com faturamento ou suporte técnico?