使用 CloudWatch 警报自动回滚亚马逊 ECS 滚动部署

简介

Amazon ECS 现在通过使用 Amazon CloudWatch 指标警报, 为在滚动更新期间监控变化并自动做出反应提供原生支持 。这使客户能够轻松地自动发现和修复失败的部署,并最大限度地减少对性能和可用性的影响。客户可以使用熟悉的 Amazon ECS 应用程序编程接口 (API) 或从 Amazon ECS 控制台为滚动更新配置 Amazon CloudWatch 警报。在这篇文章中,我们将使用示例场景演示这项新功能的工作原理,该场景使用监控服务的平均响应延迟的 Amazon CloudWatch 警报管理服务的滚动更新。

背景

滚动更新 是 Amazon ECS 客户最常使用的部署类型,用于将其服务部署到集群。使用这种部署类型时,Amazon ECS 计划程序会滚动使用新任务替换当前正在运行的任务,直到达到所需的数量。在滚动更新期间,调度程序在服务中添加或删除的任务数量由 部署配置 控制。

默认情况下,当服务中的任务无法达到正常状态时,调度程序会应用 服务限制逻辑 来重试部署,并且在一定次数的尝试失败后需要手动干预才能取消部署。自从 Amazon ECS 部署断路器 发布 以来,客户无需手动干预即可自动回滚不健康的服务部署。您可以选择在部署配置 中使用 断 路器 ,如果部署无法达到稳定状态并将其回滚到上次完成的部署,则该断路器会使部署过渡到失败状态。

即使服务中的任务处于正常状态,也可能需要回滚部署的原因有很多。该服务可能对其代码或配置进行了更改,从而导致其性能低于给定环境中的既定基准。这可以通过使用 Amazon CloudWatch 监控从该服务收集的一组指标来检测。这些可能是系统指标,例如 CPU、内存利用率,或自定义服务指标,例如平均响应延迟。

使用 亚马逊云科技 CodeDeploy 将其服务部署 到亚马逊 ECS 的客户能够使用 亚马逊 CloudWatc h 指标警报来监控部署情况。 警报在您指定的时间段内监视单个指标,并在多个时间段内根据该指标相对于给定阈值的值进行激活(即状态从 OK 更改为 ALARM)。可以将 亚马逊云科技 CodeDeploy 配置为在激活警报时停止部署,然后回滚部署。我们宣布的新功能使客户能够使用 Amazon ECS API 本地处理此类自动化,而无需使用其他服务。

它是如何工作的?

当客户使用 JSON 字符串使用 Amazon ECS API 创建或更新服务时,他们可以在 部署配置 字段中配置一个或多个 Amazon CloudWatch 指标警报,如下所示:

"deploymentConfiguration":{
   "deploymentCircuitBreaker":{
      "enable":true,
      "rollback":true
   },
   "maximumPercent":200,
   "minimumHealthyPercent":50,
   "alarms":{
      "alarmNames":[
         "HighResponseLatencyAlarm"
      ],
      "enable":true,
      "rollback":true
   }
} 

上面的命令行界面 (CLI) 等效项,即 --deployment-con figuration 参数,如下所示:

--deployment-configuration "maximumPercent=200,minimumHealthyPercent=50,deploymentCircuitBreaker={enable=true,rollback=true},alarms={alarmNames=[HighResponseLatencyAlarm],enable=true,rollback=true}"

参照下图 1,在滚动更新期间,一旦更新服务的一个或多个任务(即这些任务现在构成部署,而先前正在运行的任务构成 主动 部署)处于运行状态(t = t2),Amazon ECS 就会开始监控已配置的 Amazon CloudWatch 警报列表。如果在未配置任何警报的情况下完成滚动更新,则当主部署运行状况良好且已达到所需数量且活动部署已缩减为 0 时,部署过程被视为已完成。图 1 中的时间轴显示了这两个事件都发生在 t = t3,但在大多数用例中,它们可能会交错排列,具体取决于目标组取消注册延迟和运行状况检查设置(如果服务使用负载均衡器)等因素。如果您配置警报,则允许部署过程继续一段额外的持续时间,称为 烘焙时间 。在此期间,主部署保持在 IN_PROGRESS 状态。此时长的长度由 Amazon ECS 根据亚马逊 CloudWatch 警报的属性(例如其 周期 和评估期 )计算得出。在此持续时间结束时(t = t4),如果所有警报均未激活且警报保持正常状态,则 Amazon ECS 认为这是一次成功的更新,并继续删除活动部署并将主部署的状态更改为 “已完成”。如果警报在 t = t4 之后的某个时候改变状态,那么它们将不会产生任何影响。

Figure 1. Deployment workflow without any rollbacks

参考下图 2,如果在 t = t2 和 t = t4 之间的任何时候激活 Amazon CloudWatch 警报(即状态从 “正常” 更改为 “警报”),则 Amazon ECS 开始回滚。通过事件总线通知客户部署失败,当前部署的状态更改为失败。此外,以前的主动部署现在变成了主部署,并已向上扩展到所需的数量。失败的部署将缩小规模并最终删除。

Figure 2. Deployment workflow with rollback triggered by CloudWatch alarm

滚动更新,警报正在运行

现在,让我们使用部署到亚马逊 ECS 集群的示例工作负载,测试滚动更新如何与 Amazon CloudWatch 警报配合使用。图 3 中的下图显示了本次测试所采用的设置。它包含一个前端服务,该服务公开了一组 REST API 并与数据存储服务进行交互,后者反过来会对 Aurora PostgreSQL 数据库的实例执行 CRUD 操作。前端服务的任务在连接到应用程序负载均衡器的目标组中注册。使用外部负载生成器向该工作负载发送稳定的请求流。Elastic Load Balancing 向亚马逊 CloudWatch 报告了多项指标,这些指标可用于验证系统是否按预期运行。在本次测试中,我们使用的是 targetResponseTim e 指标,该指标衡量请求离开负载均衡器后直到收到目标响应所经过的时间(以秒为单位)。

Figure 3. Rolling deployment with alarm-based rollbacks to a service registered with a load balancer

基于该指标创建的 Amazon CloudWatch 指标警报的详细信息如下所示。警报配置为在 10 分钟间隔内至少 5 次违反 TargetResponseTim e 指标突破 0.1 秒的阈值时激活。

Figure 4. Details of the CloudWatch metric alarm used in the deployment configuration

图 5 显示了 TargetResponseTime 指标的图表,该 指标在初始部署前端服务时平均约为 50 毫秒。

Figure 5. Graph of TargetResponseTime metric for the initial deployment

现在,随着前端服务的更新版本,滚动更新已启动。此修订版的应用代码已修改,因此该服务的响应时间超过了为 Amazon CloudWatch 指标警报配置的 0.1 秒阈值。下面的 JSON 数据显示了更新启动后某个时候主要部署和活跃部署的状态。此交叉点对应于图 2 中时间轴中的 t = t3,此时活动部署已缩减到 0,主部署已扩大到所需数量。在 JSON 数据中,任务定义 f rontendalarmTask: 3 对应于服务的初始版本,而 fr onten dalarmTask: 4 是更新版本的任务定义。

[
    {
        "id": "ecs-svc/1330173481524238954",
        "status": "PRIMARY",
        "taskDefinition": "arn:aws:ecs:us-west-2:XXX:task-definition/FrontendAlarmTask:4",
        "desiredCount": 2,
        "pendingCount": 0,
        "runningCount": 2,
        "failedTasks": 0,
        "createdAt": "2022-12-12T23:00:40.748000-05:00",
        "updatedAt": "2022-12-12T23:01:32.930000-05:00",
        "launchType": "EC2",
        "networkConfiguration": {
        },
        "rolloutState": "IN_PROGRESS",
        "rolloutStateReason": "ECS deployment ecs-svc/1330173481524238954 in progress."
    },
    {
        "id": "ecs-svc/7260558072093326498",
        "status": "ACTIVE",
        "taskDefinition": "arn:aws:ecs:us-west-2:XXX:task-definition/FrontendAlarmTask:3",
        "desiredCount": 0,
        "pendingCount": 0,
        "runningCount": 0,
        "failedTasks": 0,
        "createdAt": "2022-12-12T22:30:29.943000-05:00",
        "updatedAt": "2022-12-12T23:02:20.611000-05:00",
        "launchType": "EC2",
        "networkConfiguration": {
        },
        "rolloutState": "COMPLETED",
        "rolloutStateReason": "ECS deployment ecs-svc/7260558072093326498 completed."
    }
]

图 6 显示了部署更新后 TargetResponseTime 指标的图表。它还指出了部署烘焙时间开始以及激活警报时启动回滚的大概时刻。

Figure 6. Graph of TargetResponseTime metric for the updated deployment

下面的 JSON 数据显示了启动回滚后立即执行的主要部署和活动部署的状态以及启动回滚的原因。

[
    {
        "id": "ecs-svc/7260558072093326498",
        "status": "PRIMARY",
        "taskDefinition": "arn:aws:ecs:us-west-2:XXX:task-definition/FrontendAlarmTask:3",
        "desiredCount": 2,
        "pendingCount": 0,
        "runningCount": 2,
        "failedTasks": 0,
        "createdAt": "2022-12-12T22:30:29.943000-05:00",
        "updatedAt": "2022-12-12T23:08:22.484000-05:00",
        "launchType": "EC2",
        "networkConfiguration": {
        },
        "rolloutState": "IN_PROGRESS",
        "rolloutStateReason": "ECS deployment detected triggered alarm(s): rolling back to deploymentId ecs-svc/7260558072093326498."
    },
    {
        "id": "ecs-svc/1330173481524238954",
        "status": "ACTIVE",
        "taskDefinition": "arn:aws:ecs:us-west-2:XXX:task-definition/FrontendAlarmTask:4",
        "desiredCount": 0,
        "pendingCount": 0,
        "runningCount": 1,
        "failedTasks": 0,
        "createdAt": "2022-12-12T23:00:40.748000-05:00",
        "updatedAt": "2022-12-12T23:08:22.433000-05:00",
        "launchType": "EC2",
        "networkConfiguration": {
        },
        "rolloutState": "FAILED",
        "rolloutStateReason": "ECS deployment failed: alarm(s) detected."
    }
]

带有后端服务警报的滚动更新

对于未注册到负载均衡器目标组的后端服务(例如本示例场景中的数据存储服务),使用警报管理滚动更新的动态将非常相似。请注意,由于不会出现任何与取消目标组任务相关的延迟,因此在这些情况下,部署到达图 2 中 t = t3 对应的交汇点的速度可能会快得多。但是,由于部署烘焙时间仅从 t = t3 开始,因此如果您已在微服务中实施了可观测性最佳实践,则仍可以通过监控相应的 Amazon CloudWatch 警报来发现潜在的性能问题。

Figure 7. Rolling deployment to a backend service with alarm-based rollbacks

客户可以根据CloudWatch Container Ins ights为亚马逊 ECS 收集的任何 系统指标设置亚马逊 CloudWatch 警报。 无需为此进行其他设置。要使用自定义服务指标,有不同的选项可用。如果应用程序已使用 Prometheus 客户端库进行检测,则您可以使用 容器洞察 Prometheus 指标监控来自动发现来自 Amazon ECS 工作负载的 Prometheus 指标 ,并将其作为自定义指标引入 到 Amazon CloudWatch 中。对于使用 OpenTelemetry SDK 进行检测的应用程序,您可以使用适用于 OpenTelemetry 的 WS 发行版将应用程序指标导出到亚马逊 CloudWatch Clou dWatch。

结论

该博客讨论了使用 CloudWatch 警报自动回滚 ECS 滚动部署的详细信息。此功能现已正式上线,可通过 亚马逊云科技 CLI、亚马逊云科技 软件开发工具包或 亚马逊云科技 CloudFormation 使用。我们非常重视买家在亚马逊的反馈,因此请告诉我们这项新功能如何为您服务。我们鼓励您向 GitHub 上的容器公共路线图提交任何问题或疑问 。