

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 自定义 Amazon GameLift Servers 容器实例集
<a name="containers-design-fleet"></a>

本节主题介绍了 Amazon GameLift Servers 托管式容器的一些可选功能。您可以选择使用其中任意一项或全部功能。

**Topics**
+ [设置资源限制](#containers-design-fleet-limits)
+ [了解容器舰队的内存分配](#containers-design-fleet-memory-allocation)
+ [配置 NVMe 云端硬盘访问权限](#containers-design-fleet-nvme)
+ [指定必备容器](#containers-design-fleet-essential)
+ [配置网络连接](#containers-custom-network)
+ [为容器设置运行状况检查](#containers-design-fleet-health)
+ [设置容器依赖关系](#containers-design-fleet-dependencies)
+ [配置容器实例集](#containers-design-fleet-config)

## 设置资源限制
<a name="containers-design-fleet-limits"></a>

对于每个容器组，您可以确定容器组运行其软件所需的内存和计算能力。Amazon GameLift Servers 依靠这些信息来管理整个容器组的资源。它还使用这些信息来计算实例集映像可以容纳的游戏服务器容器组数量。此外，您也可以为各个容器设置限制。

您可以为容器组设置内存和计算能力的最大限制。默认情况下，这些资源由组内的所有容器共享。您可以通过为单个容器设置限制来进一步自定义资源管理。

**为单个容器设置可选限制**  
通过设置容器特定的资源限制，您可以更好地控制各个容器如何使用组内资源。如果未设置特定于容器的限制，则组内所有容器将共享组资源。这种共享方式能够更灵活地按需分配资源，但也可能导致进程间资源竞争，进而引发容器故障。  
可为任何容器设置以下任一 `ContainerDefinition` 属性。  
+ `MemoryHardLimitMebibytes`：为容器设置最大内存限制。如果容器超过此限制，则会重启。
+ `Vcpu` limit：保留最低数量的 vCPU 资源供容器专用。容器始终拥有该预留资源。如果有其他资源可用，其使用量可随时超过此最低限额。（1024 个 CPU 单位相当于 1 个 vCPU。）

**为容器组设置总资源限制**  
如果您为单个容器设置了限制，则可能需要修改容器组所需的内存和 vCPU 资源。目标是分配足够的资源来优化游戏服务器性能。Amazon GameLift Servers 使用这些限制来计算如何在实例集实例上打包游戏服务器容器组。此外，在为容器实例集选择实例类型时，也需要参考这些限制。  
计算容器组所需的总内存和 vCPU。请考虑以下事项：  
+ 容器组内所有容器运行的全部进程有哪些？ 将这些过程所需的资源累加起来。注意任何特定于容器的限制。
+ 您计划在每个容器组中运行多少个并发游戏服务器进程？ 您可以在游戏服务器容器映像中确定这一数量。
根据您对容器组需求的估计，设置以下 `ContainerGroupDefinition` 属性：  
+ `TotalMemoryLimitMebibytes`：为容器组设置最大内存限制。组中的所有容器共享分配的内存。如果已设置单个容器限制，则总内存限制必须等于或大于容器特定的最高内存限制。
+ `TotalVcpuLimit`：为容器组设置最大 vCPU 限制。组中的所有容器共享分配的 CPU 资源。如果已设置单个容器限制，则总 CPU 限制必须等于或大于所有容器特定 CPU 限制的总和。作为最佳实践，建议将此值设置为容器 CPU 限制之和的两倍。

**示例方案**  
假设我们要定义一个包含以下三个容器的游戏服务器容器组：  
+ 容器 A 为游戏服务器容器。一台游戏服务器的资源需求预估为 512 MiB 内存和 1024 个 CPU 单位。我们计划让容器运行 1 个服务器进程。由于此容器运行最关键的软件，我们没有设置内存限制或 vCPU 预留限制。
+ 容器 B 是一个支持容器，其资源需求估计为 1024 MiB 内存和 1536 个 CPU 单位。我们将内存限制设置为 2048 MiB，CPU 预留限制为 1024 个 CPU 单位。
+ 容器 C 是另一个支持容器。我们将硬性内存限制设置为 512 MiB，将 CPU 预留限制设置为 512 个 CPU 单位。
使用这些信息，我们为容器组设置了以下总限制：  
+ 总内存限制：7680 MiB。此值超过了最高内存限制（1024 MiB）。
+ CPU 总限制：13312 个 CPU 单位。此值超过了 CPU 限制的总和（1024\$1512 CPU）。

## 了解容器舰队的内存分配
<a name="containers-design-fleet-memory-allocation"></a>

在队列实例上Amazon GameLift Servers部署容器组时，并非该实例的所有内存都可用于您的容器。 Amazon GameLift Servers为操作系统、Amazon ECS 代理和其他支持服务保留一部分实例内存。预留内存量因实例类型的总内存而异。了解这一开销有助于您配置容器组定义以充分利用可用资源。

### 内存开销公式
<a name="containers-design-fleet-memory-formula"></a>

Amazon GameLift Servers使用以下步骤计算容器组的可用内存：

1. **确定内存缓冲区百分比。** Amazon GameLift Servers根据以下等级预留实例总内存的一定百分比：    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/gameliftservers/latest/developerguide/containers-design-fleet.html)

1. **计算可用内存。**从实例总内存中减去预留内存：

   `AvailableMemory = InstanceMemory - round(InstanceMemory × BufferPercentage)`

1. **减去每个实例的容器组内存。**如果您的队列使用每个实例的容器组，请`TotalMemoryLimitMebibytes`从可用内存中减去该容器组。每个队列实例上运行一个每个实例的容器组。

   `AvailableMemory = AvailableMemory - PerInstanceCGD.TotalMemoryLimitMebibytes`

1. **考虑日志路由器开销。**如果队列启用了日志记录，则每个游戏服务器容器组为日志路由器额外Amazon GameLift Servers预留 50 MiB。

1. **计算最大游戏服务器容器组。**按内存容纳在实例上的游戏服务器容器组的最大数量为：

   `MaxGroupsByMemory = floor(AvailableMemory / (GameServerCGD.TotalMemoryLimitMebibytes + LogRouterMemory))`

   如果启用了日志记录，则`LogRouterMemory`为 50 MiB；如果禁用了日志记录，则为 0。

**注意**  
内存只是决定一个实例上可容纳多少个游戏服务器容器组的因素之一。 Amazon GameLift Servers还会考虑 vCPU 容量和可用连接端口，并使用所有三种计算中的最低值。

### 内存计算示例
<a name="containers-design-fleet-memory-example"></a>

假设队列使用启用了日志`c5.xlarge`记录的实例（总内存 8,192 MiB）：

1. 实例内存为 8,192 MiB，属于 5,000—9,999 层（缓冲区为 6%）

1. 预留内存 = 回合 (8,192 × 0.06) = 492 MiB

1. 可用内存 = 8,192-492 = 7,700 MiB

1. 如果使用的每实例容器组为 512：可用内存 = 7,700-512 = 7,188 MiB `TotalMemoryLimitMebibytes`

1. 如果每个游戏服务器容器组有 `TotalMemoryLimitMebibytes` 1,024 个： MaxGroupsByMemory = 下限 (7,188/(1,024 \$1 50)) = 下限 (7,188/1,074) = 6

### 按实例类型划分的可用内存
<a name="containers-design-fleet-memory-reference"></a>

下表显示了常用实例类型的总内存和可用内存（Amazon GameLift Servers缓冲区之后）。配置容器组定义时，请使用这些值作为起点。*可用内存*列显示实例上所有容器组的可用内存，然后再减去每个实例的容器组或日志路由器的开销。


| 实例类型 | 总内存 (MiB) | 缓冲区百分比 | 可用内存 (MiB) | 
| --- | --- | --- | --- | 
| c5.large | 4,096 | 8% | 3,768 | 
| c5.xlarge | 8192 | 6% | 7,700 | 
| c5.2xlarge | 16,384 | 5% | 15,565 | 
| c5.4xlarge | 32,768 | 5% | 31,130 | 
| c5.9xlarge | 73,728 | 5% | 70,042 | 
| c5.12xlarge | 98,304 | 4% | 94,372 | 
| c5.18xlarge | 147,456 | 4% | 141,558 | 
| c5.24xlarge | 196,608 | 4% | 188,744 | 
| m5.large | 8192 | 6% | 7,700 | 
| m5.xlarge | 16,384 | 5% | 15,565 | 
| m5.2xlarge | 32,768 | 5% | 31,130 | 
| m5.4xlarge | 65,536 | 5% | 62,259 | 
| m5.8xlarge | 131,072 | 4% | 125,829 | 
| m5.12xlarge | 196,608 | 4% | 188,744 | 
| r5.large | 16,384 | 5% | 15,565 | 
| r5.xlarge | 32,768 | 5% | 31,130 | 
| r5.2xlarge | 65,536 | 5% | 62,259 | 
| r5.4xlarge | 131,072 | 4% | 125,829 | 
| c6i.large | 4,096 | 8% | 3,768 | 
| c6i.xlarge | 8192 | 6% | 7,700 | 
| c6i.2xlarge | 16,384 | 5% | 15,565 | 
| c6i.4xlarge | 32,768 | 5% | 31,130 | 
| c6i.8xlarge | 65,536 | 5% | 62,259 | 
| c7i.large | 4,096 | 8% | 3,768 | 
| c7i.xlarge | 8192 | 6% | 7,700 | 
| c7i.2xlarge | 16,384 | 5% | 15,565 | 
| c7i.4xlarge | 32,768 | 5% | 31,130 | 
| c7i.8xlarge | 65,536 | 5% | 62,259 | 
| m7i.large | 8192 | 6% | 7,700 | 
| m7i.xlarge | 16,384 | 5% | 15,565 | 
| m7i.2xlarge | 32,768 | 5% | 31,130 | 
| m7i.4xlarge | 65,536 | 5% | 62,259 | 
| m7i.8xlarge | 131,072 | 4% | 125,829 | 
| m7i.12xlarge | 196,608 | 4% | 188,744 | 
| r7i.large | 16,384 | 5% | 15,565 | 
| r7i.xlarge | 32,768 | 5% | 31,130 | 
| r7i.2xlarge | 65,536 | 5% | 62,259 | 
| r7i.4xlarge | 131,072 | 4% | 125,829 | 

对于此处未列出的实例类型，您可以使用上述公式计算可用内存。查看 [Amazon EC2 实例类型文档](https://docs.aws.amazon.com/ec2/latest/instancetypes/ec2-instance-type-specifications.html)，了解所选实例类型的总内存。

## 配置 NVMe 云端硬盘访问权限
<a name="containers-design-fleet-nvme"></a>

在 d 型实例上， NVMe 驱动器会在主机启动期间自动装载到`/data`目录中。要使容器能够访问 SSD 存储，请设置以下`ContainerGroupDefinition`属性`MountPoints`：
+ `InstancePath`— 设置为`/data`以引用主机实例上自动装载的 NVMe 驱动器。
+ `AccessLevel`— 根据容器的需求选择适当的访问级别（例如 READ\$1ONLY 或 READ\$1WRITE）。
+ `ContainerPath`—（可选）指定将实例路径挂载到容器内的路径。如果未指定，则默认为实例路径。

有关挂载点的更多信息，请参阅 Amazon GameLift 服务器 API 参考[ContainerMountPoint](https://docs.aws.amazon.com/gameliftservers/latest/apireference/API_ContainerMountPoint.html)中的。

## 指定必备容器
<a name="containers-design-fleet-essential"></a>

对于每个实例容器组，需将每个容器指定为必备容器或非必备容器。每个实例容器组必须具有至少一个必备支持容器。必备容器负责容器组的关键工作，需始终保持运行状态。若其发生故障，整个容器组将重启。

将每个容器的 `ContainerDefinition` 属性 `Essential` 设置为 true 或 false。

## 配置网络连接
<a name="containers-custom-network"></a>

您可以自定义网络访问权限以允许外部流量连接到容器实例集中的任何容器。例如，您必须与运行游戏服务器进程的容器建立网络连接，以便游戏客户端能够接入并参与游戏。游戏客户端使用端口和 IP 地址连接到游戏服务器。

在容器实例集中，客户端与服务器之间并非直接连接。在内部，容器中的进程会监听*容器端口*。在外部，传入流量使用*连接端口*连接到实例集实例。Amazon GameLift Servers 维护内部容器端口和面向外部的连接端口之间的映射，以便将传入流量路由到实例上的正确进程。

Amazon GameLift Servers 为您的网络连接提供了额外一层控制。每个容器实例集都有*入站权限*设置，允许您控制对每个面向外部的连接端口的访问。例如，您可以移除所有连接端口的权限，以关闭对实例集容器的所有访问权限。

您可以更新实例集的入站权限、连接端口和容器端口。

**警告**  
如果您提供自定义 InstanceConnectionPortRange 或 InstanceInboundPermissions，则Amazon GameLift Servers将不再为您的队列管理任一值。您必须同时设置这两个字段，以避免出现未定义行为。

**设置容器端口范围**  
容器端口范围需作为每个容器定义的一部分进行配置。这是容器组定义的必填参数。您需要配置足够的端口，以容纳所有需要外部访问的并发运行的进程。有些容器不需要任何端口。  
运行游戏服务器的游戏服务器容器需要一个端口，用于每个并发运行的游戏服务器进程。游戏服务器进程会监听分配的端口并将其报告给 Amazon GameLift Servers。

**设置连接端口范围**  
为容器实例集配置一组连接端口。连接端口提供对运行容器的实例集实例的外部访问权限。Amazon GameLift Servers 会根据需要分配连接端口，并将其映射到容器端口。  
默认情况下，Amazon GameLift Servers 会计算所有容器组所需的端口数，并设置相应的端口范围以满足需求。我们强烈建议您使用 Amazon GameLift Servers 的计算值，该值会在您部署容器组定义更新时自动更新。如果您确实需要自定义连接端口范围，请使用以下指南。  
创建容器队列时，请定义连接端口范围（请参阅[ ContainerFleet:InstanceConnectionPortRange](https://docs.aws.amazon.com/gameliftservers/latest/apireference/API_ContainerFleet.html)）。确保该范围有足够的端口，可以映射到在实例集中两个容器组内所有容器中定义的每个容器端口。要计算所需的最小连接端口数，请使用以下公式：  
`[Total number of container ports defined for containers in the game server container group] * [Number of game server container groups per instance] + [Total number of container ports defined for containers in the per-instance container group]`  
最佳实践是，将最小连接端口数量翻倍。  
连接端口的数量可能会限制每个实例的游戏服务器容器组的数量。如果实例集的连接端口仅足以满足每个实例部署一个游戏服务器容器组的需求，则即使实例的计算资源足以承载多个游戏服务器容器组，Amazon GameLift Servers 仍只会部署一个游戏服务器容器组。

**设置入站权限**  
入站权限通过指定允许传入流量访问的连接端口，来控制对容器实例集的外部访问。您可以使用此设置，根据需要开启和关闭实例集的网络访问权限。  
默认情况下，Amazon GameLift Servers 会计算所有容器组所需的端口数，并设置相应的端口范围以满足需求。我们强烈建议您使用 Amazon GameLift Servers 的计算值，该值会在您部署容器组定义更新时自动更新。如果您确实需要自定义连接端口范围，请使用以下指南。  
创建容器队列时，请定义一组入站权限（请参阅[ ContainerFleet:InstanceInboundPermissions](https://docs.aws.amazon.com/gameliftservers/latest/apireference/API_ContainerFleet.html)）。入站许可端口应与实例集的连接端口范围相匹配。  
由于容器端口是从中随机选择的 InstanceConnectionPortRange，因此为了保证可以建立会话连接，因此中的所有端口都 InstanceConnectionPortRange 应被中的端口覆盖 InstanceInboundPermissions

**示例方案**  
此示例说明了如何设置所有三个网络连接属性。  
+ 我们实例集的游戏服务器容器组有 1 个容器，其中运行 1 个游戏服务器进程。

  在游戏服务器容器组定义中，我们按如下方式设置该容器的 `PortConfiguration` 参数：

  ```
  "PortConfiguration": {
    "ContainerPortRanges": [ { "FromPort": 10, "ToPort": 20, "Protocol": "TCP"} ]  }
  ```
+ 我们的实例集还有一个每个实例容器组，其中包含 1 个容器。它有 1 个需要网络访问的进程。在每个实例的容器定义中，我们按如下方式设置此容器的 `PortConfiguration` 参数：

  ```
  "PortConfiguration": {
    "ContainerPortRanges": [ { "FromPort": 25, "ToPort": 25, "Protocol": "TCP"} ]  }
  ```
+ 我们的实例集为每个实例集实例配置 20 个游戏服务器容器组。有了这些信息，我们可以使用以下公式来计算需要的连接端口数：
  + 最少：**21 个端口** [1 个游戏服务器容器端口 \$1 每个实例 20 个游戏服务器容器组 \$1 1 个每个实例容器端口]
  + 最佳实践：**42 个端口** [最少端口 \$1 2]

  在创建容器实例集时，我们按如下方式设置 `InstanceConnectionPortRange` 参数：

  ```
  "InstanceConnectionPortRange": { "FromPort": 1010, "ToPort": 1071 }
  ```
+ 我们希望允许访问所有可用的连接端口。在创建容器实例集时，我们按如下方式设置 `InstanceInboundPermissions` 参数：

  ```
  "InstanceInboundPermissions": [ 
    {"FromPort": 1010, "ToPort": 1071, "IpRange": "10.24.34.0/23", "Protocol": "TCP"} ]
  ```

## 为容器设置运行状况检查
<a name="containers-design-fleet-health"></a>

如果容器遇到终端故障并停止运行，它会自动重启。如果容器标记为必备容器，它会提示整个容器组重新启动。

所有游戏服务器容器都自动被视为是必备容器。可以将支持容器指定为必备容器，但它们需要有报告运行状况的机制。您也可以为非必备支持容器设置运行状况检查。

您可以定义其他自定义标准来衡量容器运行状况，并使用运行状况检查来测试该标准。要设置容器运行状况检查，可以在 Docker 容器映像或容器定义中对其进行定义。如果您在容器定义中设置了运行状况检查，它将覆盖容器映像中的所有设置。

为容器运行状况检查设置以下 `SupportContainerDefinition` 属性：
+ `Command`：提供一个命令来检查容器运行状况的某些方面。您可以决定使用什么标准来衡量运行状况。该命令的退出值必须为 1（不正常）或 0（正常）。
+ `StartPeriod`：指定在开始统计运行状况检查失败次数前的初始延迟时间。此延迟为容器提供启动内部进程的时间。
+ `Interval`：决定执行运行状况检查命令的频率。您希望以多快的速度检测和解决容器故障？
+ `Timeout`：决定在重试运行状况检查命令之前等待成功或失败的时间。运行状况检查命令需要多长时间才能完成？
+ `Retries`：在判定为失败前，运行状况检查命令应重试多少次？

## 设置容器依赖关系
<a name="containers-design-fleet-dependencies"></a>

在每个容器组中，您可以根据容器状态设置容器之间的依赖关系。依赖关系会根据另一容器的状态，影响依赖容器的启动或关闭时机。

依赖关系的一个关键使用案例是为容器组创建启动和关闭序列。

例如，您可能希望容器 A 先启动并成功完成，然后再启动容器 B 和 C。要实现这一点，首先要在容器 A 上为容器 B 创建一个依赖关系，条件是容器 A 必须成功完成。然后在容器 A 上为容器 C 创建具有相同条件的依赖关系。启动顺序与关机顺序相反。

## 配置容器实例集
<a name="containers-design-fleet-config"></a>

在创建容器实例集时，请考虑以下决策点。这些要点大多取决于容器架构和配置。

**确定要部署实例集的位置**  
通常，您应将实例集部署在靠近玩家的地理位置，以最大限度地减少延迟。您可以将您的集装箱舰队部署到任何 AWS 区域 Amazon GameLift Servers支持的集装箱舰队。如果您想将同一台游戏服务器部署到其他地理位置，则可以将远程位置添加到队列中，包括 AWS 区域 和 Local Zones。对于多位置实例集，您可以单独调整每个实例集位置的容量。有关支持的实例集位置的更多信息，请参阅[Amazon GameLift Servers 服务位置](gamelift-regions.md)。  
建议使用 [UDP ping 信标](reference-udp-ping-beacons.md)来收集不同地理位置的网络延迟数据，以预测玩家设备和潜在实例集位置之间的延迟。这些特殊端点接受 UDP 消息，而不是传统的 ICMP ping 消息，同时提供准确的延迟测量，有助于您选择最佳实例集位置。

**为实例集选择实例类型和规格**  
Amazon GameLift Servers 支持多种 Amazon EC2 实例类型，所有这些类型都可用于容器实例集。实例类型的可用性和价格因位置而异。您可以在 Amazon GameLift Servers 控制台（在**“资源”、“实例”和“服务配额**”下）中查看按位置筛选的支持实例类型列表。  
选择实例类型时，首先要考虑实例系列。不同实例系列提供不同的 CPU、内存、存储和网络功能组合。了解有关 [EC2 实例系列](https://aws.amazon.com/ec2/instance-types/)的更多信息。每个实例系列下均提供多种实例规格供您选择。选择实例规格时，需考虑以下问题：  
+ 支持您的工作负载所需的最小实例规格是什么？ 利用该信息排除所有规格过小的实例类型。
+ 哪些实例规格适合您的容器架构？ 理想情况下，应选择能够容纳多个游戏服务器容器组副本且资源浪费最少的规格。
+ 哪种扩缩粒度适合您的游戏？ 扩缩实例集容量涉及添加或删除实例，每个实例都代表托管特定数量的游戏会话的能力。需考虑每次添加或移除实例时希望调整的容量大小。如果玩家需求每分钟波动有数千之多，则使用可承载数百或数千个游戏会话的超大型实例可能更为合理；相反，若需要更精细的扩缩控制，则可选择小型实例类型。
+ 是否可通过规格选择节省成本？ 部分实例类型的价格可能因地区可用性不同而存在差异，您可据此寻找成本优化空间。

**设置其他可选实例集设置**  
在配置容器实例集时，可以使用以下可选功能：  
+ 设置游戏服务器以访问其他 AWS 资源。请参阅[将您的Amazon GameLift Servers托管游戏服务器连接到其他 AWS 资源](gamelift-sdk-server-resources.md)。
+ 保护存在活跃玩家的游戏会话，防止在缩减事件期间过早终止。
+ 限制单个玩家在有限的时间范围内可在实例集上创建的游戏会话数。