

# 预留 Amazon ECS Linux 容器实例内存
<a name="memory-management"></a>

当 Amazon ECS 容器代理将容器实例注册到集群中时，代理必须确定容器实例可为任务预留的内存量。由于平台内存开销和系统内核占用的内存，此数量不同于 Amazon EC2 实例所标示的已安装内存量。例如，`m4.large` 实例具有 8GiB 的已安装内存。但是，当容器实例注册时，这并不总是转换为可用于任务的 8192MiB 内存。

## ECS 托管实例内存资源确定
<a name="ecs-mi-memory-calculation"></a>

Amazon ECS 托管实例采用分层方法来确定任务的内存资源要求。与依赖 Docker 内存自省的 ECS on EC2 不同，ECS 托管实例在调度决策期间直接从任务有效载荷计算内存需求。

当 ECS 托管实例代理收到任务时，它会按照以下优先级顺序计算内存需求：

1. **任务级内存（最高优先级）**：如果在任务定义中指定了任务级内存，则代理直接使用此值。这优先于所有容器级内存设置。

1. **容器级内存总和（回退）**：如果未指定任务级内存（或为 0），代理会对任务中所有容器的内存需求进行求和。对于每个容器，它使用：

   1. *内存预留（软限制）*：如果容器在其配置中指定了 `memoryReservation`，则代理会使用此值。

   1. *容器内存（硬限制）*：如果未指定 `memoryReservation`，则 代理将使用容器的 `memory` 字段。

**Example 指定的任务级内存**  
当指定任务级内存时，其优先级高于容器级设置：  

```
{
  "family": "my-task",
  "memory": "2048",
  "containerDefinitions": [
    {
      "name": "container1",
      "memory": 1024,
      "memoryReservation": 512
    }
  ]
}
```
代理预留 2048 MiB（任务级内存优先）。

**Example 具有预留的容器级内存**  
当未指定任务级内存时，代理会计算容器内存需求的总和：  

```
{
  "family": "my-task",
  "containerDefinitions": [
    {
      "name": "container1",
      "memory": 1024,
      "memoryReservation": 512
    },
    {
      "name": "container2",
      "memory": 512
    }
  ]
}
```
代理预留 512 MiB（容器 1 预留）\$1 512 MiB（容器 2 内存）= 总计 1024 MiB。

ECS 托管实例代理分三个阶段执行内存计算：

1. **任务接收**：当来自 ECS 控制面板的任务有效载荷到达时，代理会立即计算所需的内存。

1. **资源存储**：计算出的内存需求存储在任务模型中，以便稍后在资源核算操作中使用。

1. **计划决策**：在接受任务之前，代理会检查是否有足够的内存可用。如果可用内存不足，则任务将被拒绝，并保留在 ECS 服务队列中，直到资源可用为止。

**注意**  
与 ECS on EC2 不同，ECS 托管实例不使用 `ECS_RESERVED_MEMORY` 配置变量。系统进程的内存预留通过底层平台的资源管理处理，代理根据任务定义执行准确的资源核算。

 对于 ECS on EC2，Amazon ECS 容器代理提供配置变量 `ECS_RESERVED_MEMORY`，您可以使用该变量从分配给您任务的池中移除指定 MiB 数的内存。这可以有效地为关键系统进程预留该内存。

如果您的任务占用容器实例上的所有内存，则您的任务可能会与关键系统进程争夺内存，并可能引起系统故障。

例如，如果您在容器代理配置文件中指定 `ECS_RESERVED_MEMORY=256`，则代理会为该实例注册总内存减去 256 MiB 后得到的内存量，这 256 MiB 内存无法由 ECS 任务分配。有关代理配置变量以及如何设置这些变量的更多信息，请参阅[Amazon ECS 容器代理配置](ecs-agent-config.md)和[引导启动 Amazon ECS Linux 容器实例以传递数据](bootstrap_container_instance.md)。

如果为任务指定 8192 MiB，并且没有任何容器实例具有 8192 MiB 或以上的可用内存来满足此要求，则任务无法放置在您的集群中。如果使用托管计算环境，则 AWS Batch 必须启动更大的实例类型来满足该要求。

Amazon ECS 容器代理使用 Docker `ReadMemInfo()` 函数来查询可用于操作系统的总内存。Linux 和 Windows 都提供了用来确定总内存的命令行实用程序。

**Example ：确定 Linux 总内存**  
**free** 命令可返回操作系统识别的总内存。  

```
$ free -b
```
运行经 Amazon ECS 优化的 Amazon Linux AMI 的 `m4.large` 实例的示例输出。  

```
             total       used       free     shared    buffers     cached
Mem:    8373026816  348180480 8024846336      90112   25534464  205418496
-/+ buffers/cache:  117227520 8255799296
```
此实例具有 8373026816 字节的总内存，这表示有 7985MiB 内存可用于任务。

**Example ：确定 Windows 总内存**  
**wmic** 命令可返回操作系统识别的总内存。  

```
C:\> wmic ComputerSystem get TotalPhysicalMemory
```
运行经 Amazon ECS 优化的 Windows Server AMI 的 `m4.large` 实例的示例输出。  

```
TotalPhysicalMemory
8589524992
```
此实例具有 8589524992 字节的总内存，这表示有 8191MiB 内存可用于任务。

## 查看容器实例内存
<a name="viewing-memory"></a>

您可以在 Amazon ECS 控制台中（或使用 [DescribeContainerInstances](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_DescribeContainerInstances.html) API 操作）查看容器实例注册的内存量。如果您试图通过为特定实例类型的任务提供尽可能多的内存来最大限度地提高资源利用率，则可以观察容器实例的可用内存，然后为您的任务分配足够的内存。

**查看容器实例内存**

1. 在 [https://console.aws.amazon.com/ecs/v2](https://console.aws.amazon.com/ecs/v2) 打开控制台。

1. 在导航窗格中，选择**集群**，然后选择托管您的容器实例的集群。

1. 选择**基础设施**，然后在容器实例下选择容器实例。

1. **资源**部分显示了容器实例的已注册内存和可用内存。

   **注册的**内存值是容器实例首次启动时向 Amazon ECS 注册的值，**可用**内存值是尚未分配给任务的值。