Amazon ECS 托管实例耗尽 - Amazon Elastic Container Service
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

Amazon ECS 托管实例耗尽

托管实例耗尽有助于优雅终止 Amazon EC2 实例。这使您的工作负载可以安全停止并重新安排到非终止实例。执行基础设施维护和更新时无需担心工作负载中断。通过使用托管实例耗尽功能,您可以简化需要更换 Amazon EC2 实例的基础设施管理工作流程,同时确保应用程序的恢复能力和可用性。

Amazon ECS 托管实例耗尽与自动扩缩组实例替换配合使用。根据实例刷新和最长实例生命周期,客户可以确保其容量符合最新的操作系统和安全规定。

托管实例耗尽只能与 Amazon ECS 容量提供程序一起使用,并且在使用 Amazon ECS 控制台、Amazon CLI 或 SDK 创建或更新自动扩缩组容量提供程序时启用。

Amazon ECS 托管实例耗尽涵盖了以下事件。

  • 自动扩缩组实例刷新 – 使用实例刷新来滚动替换自动扩缩组中的 Amazon EC2 实例,而不是手动批量替换。当您需要替换大量实例时,这非常有用。实例刷新是通过 Amazon EC2 控制台或 StartInstanceRefresh API 启动的。如果您使用托管终止保护,则请确保在调用 StartInstanceRefresh 时为横向缩减保护选择 Replace

  • 最长实例生命周期 – 在替换自动扩缩组实例时,您可以定义最长生命周期。这有助于根据内部安全策略或合规性安排替换实例。

  • 自动扩缩组横向缩减 – 根据扩缩策略和计划的扩缩操作,自动扩缩组支持自动扩缩实例。通过将自动扩缩组与 Amazon ECS 容量提供程序配合使用(这有助于集群自动扩缩),您可以在自动扩缩组实例中没有任务运行时横向缩减这些实例。

  • 自动扩缩组运行状况检查 –自动扩缩组支持许多运行状况检查,以管理运行不正常的实例的终止。

  • Amazon CloudFormation 堆栈更新 – 您可以向 Amazon CloudFormation 添加 UpdatePolicy 属性,以便在组更改时执行滚动更新。

  • 竞价型容量再平衡 –自动扩缩组尝试根据 Amazon EC2 容量再平衡通知主动替换中断风险较高的竞价型实例。替换实例启动且正常运行后,自动扩缩组会终止旧实例。Amazon ECS 托管实例耗尽会耗尽正在终止的竞价型实例,就像耗尽非竞价型实例一样。

  • Spot 中断 – 竞价型实例将在通知两分钟后终止。Amazon ECS 托管实例耗尽会将实例置于耗尽状态作为响应。

Amazon EC2 Auto Scaling 生命周期挂钩(托管实例耗尽)

自动扩缩组生命周期挂钩使客户能够创建由实例生命周期中的特定事件触发的解决方案,并在该特定事件发生时执行自定义操作。一个自动扩缩组最多允许 50 个挂钩。可存在多个终止挂钩并可并行执行,自动扩缩组会等待所有挂钩完成后再终止实例。

除了 Amazon ECS 托管挂钩终止外,您还可以配置自己的生命周期终止挂钩。生命周期挂钩有 default action,建议将 continue 设置为默认操作,以确保其他挂钩(例如 Amazon ECS 托管的挂钩)不会受到自定义挂钩的任何错误的影响。

如果您已经配置了自动扩缩组终止生命周期挂钩并启用了 Amazon ECS 托管的实例耗尽功能,则两个生命周期挂钩都将执行。但不能保证相对时间。生命周期挂钩有一个 default action 设置,用于指定超时过后要采取的操作。如果失败,则建议使用 continue 作为自定义挂钩中的默认结果。这样可以确保其他挂钩(尤其是 Amazon ECS 托管的挂钩)不会受到自定义生命周期挂钩中任何错误的影响。abandon 的替代结果会导致跳过所有其他挂钩,因此应避免使用。

任务和托管实例耗尽

Amazon ECS 托管实例耗尽使用容器实例中现有的耗尽功能。容器实例耗尽功能对属于 Amazon ECS 服务的副本任务执行替换和停止。处于 pendingrunning 状态的独立任务(如由 RunTask 调用的任务)将不受影响。您必须等待这些任务完成或手动停止这些任务。容器实例将保持 draining 状态,直到所有任务均已停止或经过 48 小时。进程守护程序任务是在所有副本任务停止后最后停止的任务。

托管实例耗尽和托管终止保护

由于 Amazon ECS 托管实例耗尽有助于正常耗尽 Amazon EC2 实例,因此其可以防止您的应用程序因任何终止事件而中断。即使禁用了托管终止,托管实例耗尽也有助于正常关闭横向缩减的实例的 Amazon ECS 服务任务。

下表总结了托管终止和托管耗尽不同组合的行为。

托管终止

托管耗尽

结果

已启用

已启用 Amazon ECS 可保护正在运行任务的 Amazon EC2 实例不被横向缩减事件终止。任何正在终止的实例(例如未设置终止保护、已收到 Spot 中断或因实例刷新而强制终止的实例)都将正常地耗尽。

已禁用

已启用 Amazon ECS 无法保护运行任务的 Amazon EC2 实例免于横向缩减。但是,任何正在终止的实例都会正常地耗尽。

已启用

已禁用 Amazon ECS 可保护正在运行任务的 Amazon EC2 实例不被横向缩减事件终止。但是,实例仍可能因 Spot 中断、强制实例刷新或其未运行任何任务而终止。Amazon ECS 不会对这些实例执行正常耗尽,并在其停止后启动替换服务任务。

已禁用

已禁用 Amazon EC2 实例可以随时进行横向缩减或终止,即使其正在运行 Amazon ECS 任务。Amazon ECS 将在替换服务任务停止后启动这些任务。
托管实例耗尽和竞价型实例耗尽

当 Amazon ECS 竞价型实例耗尽时,您可以在 Amazon ECS 代理上设置环境变量 ECS_ENABLE_SPOT_INSTANCE_DRAINING,这样 Amazon ECS 就可以将实例置于耗尽状态,以应对两分钟的 Spot 中断。Amazon ECS 托管实例耗尽有助于正常关闭因多种原因而正在终止的 Amazon EC2 实例,而不仅仅是 Spot 中断。例如,您可以使用 Amazon EC2 Auto Scaling 容量再平衡来主动替换中断风险较高的竞价型实例,托管实例耗尽会正常关闭替换的竞价型实例。使用托管实例耗尽时,您无需单独启用竞价型实例耗尽,因此 ASG 用户数据中的 ECS_ENABLE_SPOT_INSTANCE_DRAINING 是冗余的。

Amazon ECS 托管实例耗尽问题排查

Amazon ECS 托管实例耗尽事件会发布到 Amazon EventBridge,并且 Amazon ECS 会在您账户的默认总线中创建 EventBridge 托管规则以支持托管实例耗尽。您可以将这些事件筛选到 Lambda、Amazon SNS 和 Amazon SQS 等其他 Amazon 服务,以进行监控和问题排查。

  • Amazon EC2 Auto Scaling 在调用生命周期挂钩时向 EventBridge 发送事件。

  • Spot 中断通知已发布到 EventBridge。

  • 如果在预置托管实例耗尽资源时出现任何故障,则 Amazon ECS 会生成错误消息,这些消息可在 Amazon ECS 控制台和 API 上检索。

  • EventBridge 内置了重试机制,可以缓解临时故障。

使用 Amazon ECS 托管实例耗尽

使用 Amazon ECS 控制台和 Amazon CLI 创建或更新自动扩缩组容量提供程序时,您可以启用托管实例耗尽功能。

注意

创建容量提供程序时,默认情况下,托管实例耗尽已启用。

以下是使用 Amazon CLI 创建启用托管实例耗尽功能的容量提供程序,以及为集群的现有容量提供程序启用托管实例耗尽功能的示例。

创建启用托管实例耗尽功能的容量提供程序

要创建启用托管实例耗尽功能的容量提供程序,请使用 create-capacity-provider 命令。

aws ecs create-capacity-provider \ --name capacity-provider \ --auto-scaling-group-provider '{ "autoScalingGroupArn": "asg-arn", "managedScaling": { "status": "ENABLED", "targetCapacity": 100, "minimumScalingStepSize": 1, "maximumScalingStepSize": 1 }, "managedDraining": "ENABLED", "managedTerminationProtection": "ENABLED", }'

响应:

{ "capacityProvider": { "capacityProviderArn": "capacity-provider-arn", "name": "capacity-provider", "status": "ACTIVE", "autoScalingGroupProvider": { "autoScalingGroupArn": "asg-arn", "managedScaling": { "status": "ENABLED", "targetCapacity": 100, "minimumScalingStepSize": 1, "maximumScalingStepSize": 1 }, "managedTerminationProtection": "ENABLED" "managedDraining": "ENABLED" } } }
为集群的现有容量提供程序启用托管实例耗尽功能

使用 update-capacity-provider 命令为集群的现有容量提供程序启用托管实例耗尽功能。您会看到 managedDraining 目前显示为 DISABLEDupdateStatus 显示为 UPDATE_IN_PROGRESS

aws ecs update-capacity-provider \ --name cp-draining \ --auto-scaling-group-provider '{ "managedDraining": "ENABLED" }

响应:

{ "capacityProvider": { "capacityProviderArn": "cp-draining-arn", "name": "cp-draining", "status": "ACTIVE", "autoScalingGroupProvider": { "autoScalingGroupArn": "asg-draining-arn", "managedScaling": { "status": "ENABLED", "targetCapacity": 100, "minimumScalingStepSize": 1, "maximumScalingStepSize": 1, "instanceWarmupPeriod": 300 }, "managedTerminationProtection": "DISABLED", "managedDraining": "DISABLED" // before update }, "updateStatus": "UPDATE_IN_PROGRESS", // in progress and need describe again to find out the result "tags": [ ] } }

使用 describe-clusters 命令并包含 ATTACHMENTS。托管实例耗尽 attachment 的 statusPRECREATED,总体 attachmentsStatusUPDATING

aws ecs describe-clusters --clusters cluster-name --include ATTACHMENTS

响应:

{ "clusters": [ { ... "capacityProviders": [ "cp-draining" ], "defaultCapacityProviderStrategy": [], "attachments": [ # new precreated managed draining attachment { "id": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111", "type": "managed_draining", "status": "PRECREATED", "details": [ { "name": "capacityProviderName", "value": "cp-draining" }, { "name": "autoScalingLifecycleHookName", "value": "ecs-managed-draining-termination-hook" } ] }, ... ], "attachmentsStatus": "UPDATING" } ], "failures": [] }

更新完成后,使用 describe-capacity-providers,您将看到 managedDraining 现在为 ENABLED

aws ecs describe-capacity-providers --capacity-providers cp-draining

响应:

{ "capacityProviders": [ { "capacityProviderArn": "cp-draining-arn", "name": "cp-draining", "status": "ACTIVE", "autoScalingGroupProvider": { "autoScalingGroupArn": "asg-draning-arn", "managedScaling": { "status": "ENABLED", "targetCapacity": 100, "minimumScalingStepSize": 1, "maximumScalingStepSize": 1, "instanceWarmupPeriod": 300 }, "managedTerminationProtection": "DISABLED", "managedDraining": "ENABLED" // successfully update }, "updateStatus": "UPDATE_COMPLETE", "tags": [] } ] }