

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

# 设计您的应用程序以妥善处理实例终止
<a name="gracefully-handle-instance-termination"></a>

 本主题介绍可用于防止 Amazon EC2 Auto Scaling 组终止尚未准备好终止的 Amazon EC2 实例的功能。默认情况下，Auto Scaling 无法查看您的实例上运行的应用程序。它可以在您的应用程序能够正常关闭或完成分配的任务之前终止实例。这些功能让您的应用程序有时间在实例终止之前完成正在进行的工作、传输状态或执行清理。您可以根据应用程序的要求单独使用或组合使用它们。

 这些功能对于有状态的工作负载特别有用，在这种工作负载中，队列中的每个实例都与其他实例保存不同的数据、任务或状态。在不正常关闭的情况下终止有状态实例可能会导致长时间运行的作业从一开始就重新启动，减少数据冗余或数据丢失，并中断正在进行的事务或计算。要优雅地关闭有状态实例，应将其工作负载耗尽（完成当前分配的所有作业）或转移其工作负载（将作业、数据或配置移至另一个活动实例）。

**Topics**
+ [终止生命周期挂钩](#gracefully-handle-instance-termination-lifecycle-hooks)
+ [横向缩减保护实例](#gracefully-handle-instance-termination-scale-in-protection)
+ [自定义终止策略](#gracefully-handle-instance-termination-custom-termination-policy)
+ [实例生命周期策略](#gracefully-handle-instance-termination-instance-lifecycle-policy)
+ [完全暂停终止](#gracefully-handle-instance-termination-suspend-terminate)
+ [限制](#gracefully-handle-instance-termination-limitations)
+ [应用场景示例](#gracefully-handle-instance-termination-examples)

## 终止生命周期挂钩
<a name="gracefully-handle-instance-termination-lifecycle-hooks"></a>

 终止生命周期挂钩可延长已选择终止的 Amazon EC2 实例的使用寿命。它提供了额外的时间来完成当前分配给实例的正在进行的工作，或者保存进度并将工作转移到另一个实例。

 对于许多工作负载，终止生命周期挂钩可能足以优雅地关闭选定终止的实例上的应用程序。这是一种尽力而为的方法，不能用于在放弃终止生命周期操作时防止终止。如果您的工作负载对终止生命周期操作失败的容忍度较低，请结合终止[生命周期挂钩配置实例生命周期策略](https://docs.amazonaws.cn/autoscaling/ec2/userguide/instance-lifecycle-policy.html)以保留实例。

 要使用终止生命周期挂钩，您需要知道何时选择终止实例。有两种方法可以知道这一点：


| 选项 | 描述 | 最适合用于 | 指向文档的链接 | 
| --- | --- | --- | --- | 
| 在实例之内 |  实例元数据服务 (IMDS) 是一个安全端点，您可以通过它来直接从实例中轮询实例的状态。如果元数据随之返回 Terminated，则您的实例将按计划终止。 |  在实例终止之前必须对实例执行操作的应用程序。 |  [检索目标生命周期状态](https://docs.amazonaws.cn/autoscaling/ec2/userguide/retrieving-target-lifecycle-state-through-imds.html)  | 
| 在实例之外 |  当实例终止时，会生成事件通知。您可以使用亚马逊 EventBridge、亚马逊 SQS、Amazon SNS 创建规则， Amazon Lambda 也可以捕获这些事件并调用响应，例如使用 Lambda 函数。 |  需要在实例之外进行操作的应用程序。 |  [配置通知目标](https://docs.amazonaws.cn/autoscaling/ec2/userguide/prepare-for-lifecycle-notifications.html#lifecycle-hook-notification-target)  | 

 要使用生命周期挂钩，您还需要知道您的实例何时准备好完全被终止。Amazon EC2 Auto Scaling 在接收 [ CompleteLifecycleAction](https://docs.amazonaws.cn/autoscaling/ec2/APIReference/API_CompleteLifecycleAction.html)API 调用或超时过后（以先发生者为准）之前不会终止该实例。

 默认情况下，由于终止生命周期挂钩的存在，实例可以继续运行一小时（检测信号超时）。如果一小时的时间不足以完成生命周期操作，则可以配置默认超时。当生命周期操作正在进行时，您可以通过 [ RecordLifecycleActionHeartbeat](https://docs.amazonaws.cn/autoscaling/ec2/APIReference/API_RecordLifecycleActionHeartbeat.html)API 调用延长超时时间。

 有关更多信息，请参阅 [Amazon EC2 Auto Scaling 生命周期钩子](lifecycle-hooks.md)。

## 横向缩减保护实例
<a name="gracefully-handle-instance-termination-scale-in-protection"></a>

 您可以使用实例缩减保护来控制在缩容事件期间选择终止哪些实例，特别是为了防止正在积极处理长时间运行的作业的实例被终止。例如，在运行容器化工作负载时，通常希望保护所有实例，只取消对没有当前或计划任务的实例的保护。实例可以继续轮询新作业，并在分配了新任务时重新启用保护。

 您可以在 Auto Scaling 组级别和实例级别启用缩减保护。当您在 Auto Scaling 组级别启用缩小保护时，只有新实例在创建时才会受到保护。对于现有实例，您可以单独启用保护。

 应用程序可以设置来自实例本身的保护，也可以从管理每个实例是否可终止的集中控制平面设置保护。对于大型队列或需要经常切换保护时，我们建议使用集中式方法，因为它允许您批量调用[ SetInstanceProtection](https://docs.amazonaws.cn/autoscaling/ec2/APIReference/API_SetInstanceProtection.html)并避免 API 限制问题。

 有关更多信息，请参阅 [使用实例横向缩减保护以控制实例终止](ec2-auto-scaling-instance-protection.md)。

## 自定义终止策略
<a name="gracefully-handle-instance-termination-custom-termination-policy"></a>

 与实例缩减保护一样，自定义终止策略可帮助您防止 Amazon EC2 Auto Scaling 组终止特定的 EC2 实例。无论您的自定义终止策略如何，仍可以终止运行状况不佳的实例。

 您的 Auto Scaling 组使用默认终止策略来确定它首先终止哪些 Amazon EC2 实例。如果您想更好地控制哪些实例首先终止，可以使用 Lambda 函数实现自定义终止策略。每当需要选择要终止的实例时，Auto Scaling 都会调用此函数，并且只会终止该函数返回的实例。如果函数出错、超时或返回空列表，则除非实例运行状况不佳，否则 Auto Scaling 不会终止任何实例。

 当您的应用程序可以识别哪些实例处于空闲状态或可以安全终止时，自定义终止策略非常有用。这通常需要一个控制平面来跟踪整个组的工作负载。

 有关更多信息，请参阅 [了解使用 Lambda 创建自定义终止策略。](lambda-custom-termination-policy.md)。

## 实例生命周期策略
<a name="gracefully-handle-instance-termination-instance-lifecycle-policy"></a>

 实例生命周期策略提供保护，防止在终止生命周期操作被放弃时 Amazon EC2 Auto Scaling 终止。与单独的生命周期挂钩不同，实例生命周期策略旨在确保在正常关闭过程未成功完成时，实例会进入保留状态。

 当 Auto Scaling 选择要终止的实例时，将调用您配置的终止生命周期挂钩，您的应用程序将开始正常关闭过程。如果终止生命周期操作成功完成`CONTINUE`，则实例将正常终止。但是，如果出于任何原因放弃了终止生命周期操作，则实例生命周期策略会将实例移至保留状态，而不是将其终止。保留的实例不计入您的 Auto Scaling 组的所需容量，因此替换实例会自动启动。在您使用 [ TerminateInstanceInAutoScalingGroup](https://docs.amazonaws.cn/autoscaling/ec2/APIReference/API_TerminateInstanceInAutoScalingGroup.html)API 手动终止保留的实例之前，您将为保留的实例及其替换实例支付标准的 Amazon EC2 费用。

 要使用此功能，您必须同时配置将`TerminateHookAbandon`保留触发器设置为的实例生命周期策略`retain`，以及至少一个终止生命周期挂钩。由于保留的实例会产生持续的 Amazon EC2 成本，并且需要手动操作，因此监控至关重要。您应该启用诸如 CloudWatch 此类的指标`GroupTerminatingRetainedInstances`并创建 CloudWatch 警报，以便在实例进入保留状态时提醒您。

 有关更多信息，请参阅 [使用实例生命周期策略控制实例保留](instance-lifecycle-policy.md)。

## 完全暂停终止
<a name="gracefully-handle-instance-termination-suspend-terminate"></a>

 如果您需要完全控制您的 Amazon EC2 Auto Scaling 组中的所有 EC2 实例终止，请暂停该`Terminate`流程。仅当上述选项无法为您提供服务所需的控制时，我们才建议您使用此选项。通过调[ SuspendProcesses](https://docs.amazonaws.cn/autoscaling/ec2/APIReference/API_SuspendProcesses.html)用暂停`Terminate`进程，可以防止 Auto Scaling 出于任何原因尝试终止，但用户向 [ TerminateInstanceInAutoScalingGroup](https://docs.amazonaws.cn/autoscaling/ec2/APIReference/API_TerminateInstanceInAutoScalingGroup.html)API 发出请求所启动的除外。

 有关更多信息，请参阅 [暂停和恢复 Amazon EC2 Auto Scaling 进程](as-suspend-resume-processes.md)。

## 限制
<a name="gracefully-handle-instance-termination-limitations"></a>

**重要**  
 在 Amazon EC2 Auto Scaling 上设计应用程序以优雅地处理实例终止时，请记住以下限制。

### 不健康的实例会绕过某些保护
<a name="gracefully-handle-instance-termination-unhealthy-bypass"></a>

 如果实例运行状况不佳，即使您有自定义终止策略或缩减保护，Amazon EC2 Auto Scaling 也会开始终止该实例。防止 Auto Scaling 替换运行状况不佳的实例的唯一方法是暂停`HealthCheck``ReplaceUnhealthy`、或`Terminate`进程。您可以使用生命周期挂钩和实例生命周期策略来允许应用程序正常关闭，或者在运行状况不佳的实例终止之前复制需要恢复的任何数据。


| 功能 | 控制运行正常的实例 | 控制运行状况不佳的实例 | 
| --- | --- | --- | 
| 自定义终止政策 | ![\[alt text not found\]](http://docs.amazonaws.cn/autoscaling/ec2/userguide/images/success_icon.png) 是 | ![\[alt text not found\]](http://docs.amazonaws.cn/autoscaling/ec2/userguide/images/negative_icon.png)没有 | 
| 横向缩减保护 | ![\[alt text not found\]](http://docs.amazonaws.cn/autoscaling/ec2/userguide/images/success_icon.png) 是 | ![\[alt text not found\]](http://docs.amazonaws.cn/autoscaling/ec2/userguide/images/negative_icon.png)没有 | 
|  暂停HealthCheckReplaceUnhealthy、或Terminate处理  | ![\[alt text not found\]](http://docs.amazonaws.cn/autoscaling/ec2/userguide/images/success_icon.png) 是 | ![\[alt text not found\]](http://docs.amazonaws.cn/autoscaling/ec2/userguide/images/success_icon.png) 是 | 
| 生命周期钩子 | ![\[alt text not found\]](http://docs.amazonaws.cn/autoscaling/ec2/userguide/images/success_icon.png) 是 | ![\[alt text not found\]](http://docs.amazonaws.cn/autoscaling/ec2/userguide/images/success_icon.png) 是 | 
| 实例生命周期策略 | ![\[alt text not found\]](http://docs.amazonaws.cn/autoscaling/ec2/userguide/images/success_icon.png) 是 | ![\[alt text not found\]](http://docs.amazonaws.cn/autoscaling/ec2/userguide/images/success_icon.png) 是 | 

### 仅靠生命周期挂钩并不能保证正常关闭
<a name="gracefully-handle-instance-termination-hooks-no-guarantee"></a>

 默认情况下，终止生命周期挂钩在尽力而为的基础上运行。如果终止生命周期操作被放弃，Amazon EC2 Auto Scaling 会立即终止该实例。您可以将终止生命周期挂钩与实例生命周期策略相结合，以便在放弃终止生命周期操作时保留实例。有了这个组合：
+  在 Auto Scaling 触发实例终止并且所有已配置的 Elastic Load Balancing 负载均衡器的耗尽完成后，您的终止生命周期挂钩会尝试优雅地关闭您的应用程序。
+  如果出于任何原因放弃了终止生命周期操作，则实例将变为保留状态，而不是被终止。
+  保留的实例保持其当前的 Amazon EC2 状态，允许您手动完成关闭程序或调查故障。
+  完成必要操作后，您可以通过调用 [ TerminateInstanceInAutoScalingGroup](https://docs.amazonaws.cn/autoscaling/ec2/APIReference/API_TerminateInstanceInAutoScalingGroup.html)API 来手动终止保留的实例。

 有关更多信息，请参阅 [使用实例生命周期策略控制实例保留](instance-lifecycle-policy.md)。

### 某些实例市场期权可能会在有限的通知下中断
<a name="gracefully-handle-instance-termination-spot-interruptions"></a>

 如果您在 Auto Scaling 组中使用竞价型实例和可中断容量预留等实例市场选项，Amazon EC2 可以随时中断和回收您的实例。这些中断绕过了所有 Amazon EC2 Auto Scaling 保护机制，包括：
+ 终止生命周期挂钩
+ 横向缩减保护实例
+ 自定义终止政策
+ 实例生命周期策略
+ 已暂停的进程

 当竞价型实例收到中断通知时，您大约有两分钟的时间来执行正常关闭任务。虽然您可以使用终止生命周期挂钩来响应竞价型实例的中断，但即使生命周期挂钩仍在进行中，实例也将在两分钟窗口结束时被强制终止。实例生命周期策略也无法防止 Spot 实例中断。

 有关处理竞价型实例中断的更多信息，请参阅 Amazon EC2 *用户*指南中的[竞价型实例中断](https://docs.amazonaws.cn/AWSEC2/latest/UserGuide/spot-interruptions.html)和 [Amazon EC2 竞价最佳实践](https://docs.amazonaws.cn/AWSEC2/latest/UserGuide/spot-best-practices.html)。

### 直接终止 Amazon EC2 会绕过所有保护措施
<a name="gracefully-handle-instance-termination-direct-ec2-api"></a>

 如果您直接使用 Amazon EC2 [ TerminateInstances](https://docs.amazonaws.cn/AWSEC2/latest/APIReference/API_TerminateInstances.html)API 终止 Auto Scaling 组中的实例，则终止将绕过所有 Amazon EC2 Auto Scaling 保护机制。

 要在遵守您配置的保护措施的情况下终止 Auto Scaling 组中的实例，请改用 [ TerminateInstanceInAutoScalingGroup](https://docs.amazonaws.cn/autoscaling/ec2/APIReference/API_TerminateInstanceInAutoScalingGroup.html)API。

## 应用场景示例
<a name="gracefully-handle-instance-termination-examples"></a>

 在使用 Amazon EC2 Auto Scaling 时，您可以选择 Auto Scaling 代表您处理的队列管理量，以及您对 EC2 实例终止决策保留多少直接控制权。您的工作负载对实例终止越敏感，您可能想要保留的控制权就越多。以下示例描述了具有不同容差级别的工作负载和推荐的配置：

### 示例 1：分布式数据库节点（容忍度低）
<a name="gracefully-handle-instance-termination-example-database"></a>

 您运行一个分布式数据库，其中每个 EC2 实例都有一个重复因子为 3 的数据分区。丢失包含同一分区副本的多个实例可能会导致数据丢失或使该分区不可用。

 **挑战：**Auto Scaling 终止实例的速度可能快于将数据重新复制到其他节点的速度，而终止可能会使您的容量低于维持复制因子所需的容量。

考虑以下配置：
+  在所有数据库[实例上启用实例缩小保护；只有在](https://docs.amazonaws.cn/autoscaling/ec2/userguide/ec2-auto-scaling-instance-protection.html)确认数据已安全复制到其他地方之后，才能以编程方式将其删除。
+  配置具有延长超时的[终止生命周期挂钩](https://docs.amazonaws.cn/autoscaling/ec2/userguide/lifecycle-hooks.html)以及实例生命周期策略，以允许数据传输完成。
+  设置[实例维护策略](https://docs.amazonaws.cn/autoscaling/ec2/userguide/ec2-auto-scaling-instance-maintenance-policy.html)，最低健康百分比为 100%，以保持所需的容量。

### 示例 2：长时间运行的作业处理（中等容差）
<a name="gracefully-handle-instance-termination-example-job-processing"></a>

 您有一个 Amazon SQS 队列，用于收集长时间运行的任务的传入消息。当新消息到达时，EC2 实例会检索该消息并启动一个需要 3 小时才能处理的任务。随着队列的增长，Auto Scaling 会根据您的扩展策略添加实例。随着队列的缩小，Auto Scaling 会终止实例。

 **挑战：**Auto Scaling 可能会终止处理任务 3 小时的实例，而不是空闲的实例。可以在另一个实例上重新启动该作业，但会丢失显著的进度。

考虑以下配置：
+  配置[自定义终止策略](https://docs.amazonaws.cn/autoscaling/ec2/userguide/lambda-custom-termination-policy.html)，优先考虑终止空闲实例。
+  使用[终止生命周期挂钩](https://docs.amazonaws.cn/autoscaling/ec2/userguide/lifecycle-hooks.html)允许正在进行的任务完成。
+  当[实例启动任务时，以编程方式启用实例缩减保护](https://docs.amazonaws.cn/autoscaling/ec2/userguide/ec2-auto-scaling-instance-protection.html)，并在任务完成时将其删除。

### 示例 3：测试环境的工作队列（高容忍度）
<a name="gracefully-handle-instance-termination-example-test"></a>

 您运行一组 EC2 实例，用于执行自动测试、 CI/CD 管道任务或开发工作负载。这些工作程序实例从队列中提取任务，如果作业失败，则可以重新生成测试结果。

 **挑战：**在缩小规模事件期间，测试作业可能会中断，但由于可以在不影响的情况下重试测试，因此您需要针对成本和简单性进行优化，而不是零中断可用性。

考虑以下配置：
+  使用[终止生命周期挂钩](https://docs.amazonaws.cn/autoscaling/ec2/userguide/lifecycle-hooks.html)允许正在进行的请求完成。
+  考虑使用具有容量优化分配策略的[竞价型实例](https://docs.amazonaws.cn/AWSEC2/latest/UserGuide/using-spot-instances.html)以进一步降低成本。