

# 更新 Amazon ECS 服务参数
<a name="update-service-parameters"></a>

创建服务后，有时可能需要更新服务参数，例如任务数。

当服务计划程序启动新任务时，它会使用以下逻辑确定集群中的任务置放。
+ 确定集群中的哪些容器实例可支持服务的任务定义。例如，它们具有所需的 CPU、内存、端口和容器实例属性。
+ 默认情况下，即使您可以选择不同的置放策略，服务计划程序也会尝试以这种方式在可用区之间平衡任务。
  + 按与实例位于同一可用区中具有此服务运行的任务数最少的顺序对有效容器实例进行排序。例如，如果 A 区有一个正在运行的服务任务，B 区和 C 区都没有正在运行的服务任务，则认为在 B 区或 C 区中的有效容器实例中最适合放置任务。
  + 将新的服务任务放在最佳可用区中的有效容器实例上（基于之前的步骤），并优先使用具有此服务的最小数量的运行任务的容器实例。

当服务计划程序停止运行任务时，它将尝试使用以下逻辑在集群的可用区之间保持均衡：
+ 按与实例位于同一可用区中具有此服务运行的任务数最多的顺序对容器实例进行排序。例如，如果 A 区有 1 个正在运行的服务任务，B 区和 C 区各有 2 个正在运行的服务任务，则认为 B 区或 C 区中的容器实例最适合终止任务。
+ 在最佳可用区中的容器实例上停止任务（基于之前的步骤），并优先使用具有此服务的最大数量的运行任务的容器实例。

使用列表来确定是否可以更改服务参数。

**可用区再平衡**  
指示是否对服务使用可用区域重新平衡。  
您可以更改此参数以进行滚动部署。

**容量提供程序策略**  
容量提供程序策略的详细信息。您可以在创建集群、运行任务或更新服务时设置容量提供程序。  
使用 Fargate 时，容量提供程序为 `FARGATE` 或 `FARGATE_SPOT`。  
当您使用 Amazon EC2 时，容量提供程序为自动扩缩组。  
您可以更改容量提供程序以进行滚动部署和蓝绿部署。  
以下列表提供了有效的转换：  
+ 将 Fargate 更新为自动扩缩组容量提供程序。
+ 将 EC2 更新为 Fargate 容量提供程序。
+ 将 Fargate 容量提供程序更新为自动扩缩组容量提供程序。
+ 将 Amazon EC2 容量提供程序更新为 Fargate 容量提供程序。
+ 将自动扩缩组或 Fargate 容量提供程序更新回启动类型。使用 CLI 或 API 时，您将在 `capacityProviderStrategy` 参数中传递一个空列表。

**集群**  
您无法更改集群名称。

**部署配置**  
部署配置包括 CloudWatch 警报、用于检测故障的断路器以及所需的配置。  
部署断路器属性确定如果服务无法达到稳定状态，服务部署是否会失败。如果使用部署断路器，服务部署将转变为失败状态并停止启动新任务。如果使用回滚选项，当服务部署失败时，服务将回滚到成功完成的最后一个部署。  
当您更新使用 Amazon ECS 断路器的服务时，Amazon ECS 会创建服务部署和服务修订。这些资源允许您查看有关服务历史记录的详细信息。有关更多信息，请参阅 [使用 Amazon ECS 服务部署查看服务历史记录](service-deployment.md)。  
服务计划程序将使用最小正常百分比和最大百分比参数（在服务的部署配置中）确定部署策略。  
如果服务使用滚动更新（`ECS`）部署类型，**最小正常百分比**以预期任务数的百分比形式表示部署期间必须保持在 `RUNNING` 状态的服务中的任务数的下限（向上取整到最近的整数）。如果服务包含使用 EC2 的任务，则在任何容器实例处于 `DRAINING` 状态时，此参数也适用。可以使用此参数进行部署，而无需使用额外的集群容量。例如，如果您的服务的预期任务数为 4，最小正常百分比为 50%，则计划程序可能在开始两个新任务之前停止两个现有任务以释放集群容量。如果未使用负载均衡器的服务状态为 `RUNNING`，则服务认为任务正常运行。如果使用负载均衡器的服务任务处于 `RUNNING` 状态，并且该负载均衡器将其报告为正常，则服务认为这些任务正常运行。最小正常百分比的默认值为 100%。  
如果服务使用滚动更新（`ECS`）部署类型，则**最大百分比**参数将以预期任务数的百分比形式表示部署期间允许处于 `PENDING`、`RUNNING` 或 `STOPPING` 状态的服务中任务数的上限（向下取整到最近的整数）。如果服务包含使用 EC2 的任务，则在任何容器实例处于 `DRAINING` 状态时，此参数也适用。可以使用此参数定义部署批次大小。例如，如果您的服务的预期任务数为 4，最大百分比值为 200%，则计划程序可能在停止 4 个旧任务之前开始 4 个新任务。这样做的前提是具有执行此操作所需的集群资源。最大百分比的默认值为 200%。  
当服务计划程序在更新期间替换某个任务时，服务首先会从负载均衡器（如果使用了）中删除此任务并等待连接耗尽。然后，将向此任务中运行的容器发出 **docker stop** 的等效项。这将产生 `SIGTERM` 信号和 30 秒的超时，此后，将发送 `SIGKILL` 并强制停止容器。如果容器正常处理了 `SIGTERM` 信号并在收到信号后的 30 秒内退出，则不会发送任何 `SIGKILL` 信号。服务计划程序将启动并停止您的最小正常百分比和最大百分比设置定义的任务。  
在容器运行状况检查或负载均衡器目标组运行状况检查失败后，服务计划程序还会替换被确定为运行状况不佳的任务。此替换取决于 `maximumPercent` 和 `desiredCount` 服务定义参数。如果任务被标记为运行状况不佳，则服务计划程序将首先启动替换任务。然后会发生以下情况。  
+ 如果替换任务的运行状况为 `HEALTHY`，则服务计划程序将停止运行不正常的任务
+ 如果替换任务的运行状况为 `UNHEALTHY`，则计划程序将停止运行状况不佳的替换任务或现有的运行状况不佳任务，以使任务总数等于 `desiredCount`。
如果 `maximumPercent` 参数限制计划程序先启动替换任务，则计划程序将一次随机停止一个运行状况不佳的任务以释放容量，然后启动替换任务。启动和停止过程将继续，直到所有运行状况不佳的任务都被运行状况正常的任务所替换。替换了所有运行状况不佳的任务并且只有运行正常的任务后，如果任务总数超过 `desiredCount`，则会随机停止运行状况正常的任务，直到任务总数等于 `desiredCount`。有关 `maximumPercent` 和 `desiredCount` 的更多信息，请参阅[服务定义参数](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service_definition_parameters.html)。

**部署控制器**  
要用于该服务的部署控制器。部署控制器有三种类型：  
+ `ECS`
+ `EXTERNAL`
+ `CODE_DEPLOY`
更新服务时，可以更新其使用的部署控制器。以下列表提供了有效的转换：  
+ 从 CodeDeploy 蓝绿部署（`CODE_DEPLOY`）更新为 ECS 滚动部署或蓝绿部署（`ECS`）。
+ 从 CodeDeploy 蓝绿部署（`CODE_DEPLOY`）更新为外部部署（`EXTERNAL`）。
+ 从 ECS 滚动部署或蓝绿部署（`ECS`）更新为外部部署（`EXTERNAL`）。
+ 从外部部署（`EXTERNAL`）更新为 ECS 滚动部署或蓝绿部署（`ECS`）。
更新服务的部署控制器时，请考虑以下事项：  
+ 如果服务使用的是 VPC Lattice 或 Amazon ECS Service Connect，则无法将其部署控制器从 `ECS` 更新为任何其他控制器。
+ 如果服务有正在进行的服务部署，则无法更新其部署控制器。
+ 如果服务上没有负载均衡器，则无法将其部署控制器更新为 `CODE_DEPLOY`。
+ 如果 `deploymentConfiguration` 包含警报、部署断路器或 `BLUE_GREEN` 部署策略，则无法将服务的部署控制器从 `ECS` 更新为任何其他控制器。有关更多信息，请参阅 [Amazon ECS 服务部署控制器和策略](ecs_service-options.md)。
+ 如果将服务的部署控制器从 `ECS` 更新为任何其他控制器，Amazon ECS 将不会使用容器定义中为 `versionConsistency` 指定的值。
+ 如果将服务的部署控制器从 `ECS` 更新为任何其他控制器，`UpdateService` 和 `DescribeService` API 响应仍将返回 `deployments` 而非 `taskSets`。有关 `UpdateService` 和 `CreateService` 的更多信息，请参阅《Amazon ECS API 参考》**中的 [UpdateService](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_Service.html) 和 [CreateService](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_Service.html)。
+ 如果服务使用滚动更新部署策略，将部署控制器从 `ECS` 更新为任何其他控制器将改变 `deploymentConfiguration` 中 `maximumPercent` 值的使用方式。`maximumPercent` 不再仅用作滚动更新部署中总任务的上限，而是用于替换运行状况不佳的任务。有关计划程序如何替换运行状况不佳的任务的更多信息，请参阅 [Amazon ECS 服务](ecs_services.md)。
+ 如果将服务的部署控制器从 `ECS` 更新为任何其他部署控制器，则在负载均衡器配置中指定的任何 `advancedConfiguration` 都将被忽略。有关更多信息，请参阅《Amazon ECS API 参考》**中的 [LoadBalancer](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LoadBalancer.html) 和 [AdvancedConfiguration](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_AdvancedConfiguration.html)。
使用 CloudFormation 更新服务的部署控制器时，请根据所执行的迁移类型考虑以下事项。  
+ 如果 CloudFormation 模板包含 `EXTERNAL` 部署控制器信息以及 `TaskSet` 和 `PrimaryTaskSet` 资源，并且在从 `EXTERNAL` 更新到 `ECS` 时从模板中删除了任务集资源，则在部署控制器更新为 `ECS` 之后，`DescribeTaskSet` 和 `DeleteTaskSet` API 调用将返回 400 错误。这会导致 CloudFormation 任务集资源删除失败，即使 CloudFormation 堆栈转换为 `UPDATE_COMPLETE` 状态，也会失败。有关更多信息，请参阅《AWS CloudFormation 用户指南》中的[资源已从堆栈中移除但未删除](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/troubleshooting.html#troubleshooting-errors-resource-removed-not-deleted)。要解决此问题，请使用 Amazon ECS `DeleteTaskSet` API 直接删除任务集。有关如何删除任务集的更多信息，请参阅《Amazon Elastic Container Service API 参考****》中的 [DeleteTaskSet](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_DeleteTaskSet.html)。
+ 如果使用新任务定义从 `CODE_DEPLOY` 迁移到 `ECS`，并且 CloudFormation 执行回滚操作，则 Amazon ECS `UpdateService` 请求将失败并出现以下错误：

  ```
  Resource handler returned message: "Invalid request provided: Unable to update 
  task definition on services with a CODE_DEPLOY deployment controller. Use AWS 
  CodeDeploy to trigger a new deployment. (Service: Ecs, Status Code: 400, 
  Request ID: 0abda1e2-f7b3-4e96-b6e9-c8bc585181ac) (SDK Attempt Count: 1)" 
  (RequestToken: ba8767eb-c99e-efed-6ec8-25011d9473f0, HandlerErrorCode: InvalidRequest)
  ```
+ 从 `ECS` 成功迁移到 `EXTERNAL` 部署控制器后，需要手动删除 `ACTIVE` 任务集，因为 Amazon ECS 将不再管理该部署。有关如何删除任务集的信息，请参阅《Amazon Elastic Container Service API 参考**》中的 [DeleteTaskSet](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_DeleteTaskSet.html)。

**预期任务计数**  
在您的服务中置放并保持运行的实例化任务数量。  
如果要暂时停止服务，请将该值设置为 0。然后，当您准备好启动服务时，请使用原始值更新该服务。  
您可以更改此参数以进行滚动部署和蓝绿部署。

**启用托管标签**  
确定是否要为该服务中的任务启用 Amazon ECS 托管标签。  
只有在更新后启动的任务才会反映更新。要更新所有任务的标签，请使用强制部署选项。  
您可以更改此参数以进行滚动部署和蓝绿部署。

**启用 ECS Exec**  
确定是否使用 Amazon ECS Exec。  
如果您不想覆盖创建服务时设置的值，则可以在执行此操作时将其设置为空。  
您可以更改此参数以进行滚动部署。

**运行状况检查宽限期**  
任务首次启动后的一段时间（以秒为单位），在此段时间内，Amazon ECS 服务计划程序将忽略未正常运行的 Elastic Load Balancing、VPC Lattice 和容器运行状况检查。如果没有指定运行状况检查宽限期值，则使用默认值 `0`。如果不使用任何运行状况检查，则未使用 `healthCheckGracePeriodSeconds`。  
如果服务的任务需要一段时间才能启动和响应运行状况检查，则您可以指定最长 2147483647 秒（大约 69 年）的运行状况检查宽限期。在此期间，Amazon ECS 服务计划程序忽略运行状况检查状态。此宽限期可防止服务计划程序将由于时间不足尚未启动的任务标记为不正常并停止它们。  
您可以更改此参数以进行滚动部署和蓝绿部署。

**负载均衡器**  
更新负载均衡器时，必须使用服务相关角色。  
Elastic Load Balancing 负载均衡器对象列表。它包含负载均衡器名称、容器名称和要从负载均衡器访问的容器端口。容器名称与在容器定义中显示的名称相同。  
Amazon ECS 不会自动更新与 Elastic Load Balancing 负载均衡器或 Amazon ECS 容器实例关联的安全组。  
当您添加、更新或删除负载均衡器配置时，Amazon ECS 会使用更新后的 Elastic Load Balancing 配置启动新任务，然后在新任务运行时停止旧任务。  
对于使用滚动更新的服务，您可以添加、更新或删除 Elastic Load Balancing 目标组。您可以从单个目标组更新为多个目标组，也可以从多个目标组更新为单个目标组。  
对于使用蓝绿部署的服务，您可以通过 CodeDeploy 使用 `[CreateDeployment](https://docs.aws.amazon.com/codedeploy/latest/APIReference/API_CreateDeployment.html)` 更新 Elastic Load Balancing 目标组。请注意，蓝绿部署不支持多个目标组。有关详细信息，请参阅[向服务注册多个目标组](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/register-multiple-targetgroups.html)。  
对于使用外部部署控制器的服务，您可以使用 [CreateTaskSet](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_CreateTaskSet.html) 添加、更新或删除负载均衡器。请注意，外部部署不支持多个目标组。有关详细信息，请参阅[向服务注册多个目标组](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/register-multiple-targetgroups.html)。  
传递一个空列表以删除负载均衡器。  
您可以更改此参数以进行滚动部署。

**网络配置**  
服务网络配置。  
您可以更改此参数以进行滚动部署。

**置放约束**  
用于更新要使用的服务的任务置放约束对象数组。如果未指定任何值，则服务的现有置放约束将保持不变。如果指定了该值，它将覆盖为服务定义的所有现有置放约束。要删除所有现有置放约束，请指定空数组。  
您可以为每个任务指定最多 10 个约束。此限制包括任务定义中的约束以及在运行时指定的约束。  
您可以更改此参数以进行滚动部署和蓝绿部署。

**置放策略**  
用于更新要使用的服务的任务置放策略对象。如果未指定任何值，则服务的现有置放策略将保持不变。如果指定了该值，则它将覆盖为服务定义的现有置放策略。要删除现有的置放策略，请指定一个空对象。  
您可以更改此参数以进行滚动部署和蓝绿部署。

**平台版本**  
运行您的服务的 Fargate 平台版本。  
使用 Linux 平台版本的服务无法更新为使用 Windows 平台版本，反之亦然。  
您可以更改此参数以进行滚动部署。

**传播标签**  
确定是否要将标签从任务定义或服务传播到任务。如果未指定任何值，则不会传播标签。  
只有在更新后启动的任务才会反映更新。要更新所有任务的标签，请将 `forceNewDeployment` 设置为 `true`，以便 Amazon ECS 使用更新的标签启动新任务。  
您可以更改此参数以进行滚动部署和蓝绿部署。

**Service Connect 配置**  
Amazon ECS Service Connect 的配置。此参数决定服务如何连接到应用程序中的其他服务。  
您可以更改此参数以进行滚动部署。

**服务注册表**  
更新服务注册表时，必须使用服务相关角色。  
要分配给此服务的服务发现注册表的详细信息。有关更多信息，请参阅[服务发现](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-discovery.html)。  
当您添加、更新或删除服务注册表配置时，Amazon ECS 会使用更新后的服务注册表配置启动新任务，然后在新任务运行时停止旧任务。  
传递一个空列表以删除服务注册表。  
您可以更改此参数以进行滚动部署。

**任务定义**  
用于服务的任务定义和修订。  
如果要在任务定义中更改容器使用的端口，您可能需要更新容器实例的安全组以使用更新后的端口。  
如果您更新服务的任务定义，则在负载均衡器中指定的容器名称和容器端口必须保留在任务定义中。  
容器映像拉取行为因计算选项而异。有关更多信息，请参阅以下任一文档：  
+ [面向 Amazon ECS 的 AWS Fargate 架构](AWS_Fargate.md)
+ [Amazon ECS 的 EC2 容量架构](launch-type-ec2.md)
+ [Amazon ECS 的外部（Amazon ECS Anywhere）](launch-type-external.md)
您可以更改此参数以进行滚动部署。

**卷配置**  
为 `configuredAtLaunch` 的卷的详细信息。当任务定义中的 `configuredAtLaunch` 设置为 `true` 时，此服务参数会为服务中的每个任务配置一个 Amazon EBS 卷，该卷将在部署期间创建并附加。您可以在 [ServiceManagedEBSVolumeConfiguration](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ServiceManagedEBSVolumeConfiguration.html) 中配置大小、卷类型、IOPS、吞吐量、快照和加密。卷的 `name` 必须与任务定义中的 `name` 相匹配。如果设置为空，则不会触发任何新部署。否则，如果此配置与现有配置不同，则会触发新的部署。  
您可以更改此参数以进行滚动部署。

**VPC Lattice 配置**  
服务的 VPC Lattice 配置。这定义了您的服务如何与 VPC Lattice 集成以进行服务间通信。  
您可以更改此参数以进行滚动部署。

## AWS CDK 注意事项
<a name="cdk-considerations"></a>

AWS CDK 不跟踪资源状态。它不知道您是在创建还是更新服务。客户应使用转义孵化直接访问 ecs `Service` L1 构造。

有关转义孵化的信息，请参阅《AWS Cloud Development Kit (AWS CDK) v2 开发人员指南》**中的[自定义 AWS 构造库中的构造](https://docs.aws.amazon.com/cdk/v2/guide/cfn-layer.html#develop-customize-escape)。

要将现有服务迁移到 `ecs.Service` 构造中，请执行以下操作：

1. 使用转义孵化访问 `Service` L1 构造。

1. 在 `Service` L1 构造中手动设置以下属性。

   如果您的服务使用 Amazon EC2 容量：
   + `daemon?`
   + `placementConstraints?`
   + `placementStrategies?`
   + 如果使用 `awsvpc` 网络模式，则需要设置 `vpcSubnets?` 和 `securityGroups?` 构造。

   如果您的服务使用 Fargate：
   + `FargatePlatformVersion`
   + `vpcSubnets?` 和 `securityGroups?` 构造。

1. 按如下方式设置 `launchType`：

   ```
   const cfnEcsService = service.node.findChild('Service') as ecs.CfnService;
   cfnEcsService.launchType = "FARGATE";
   ```

要从启动类型迁移到容量提供程序，请执行以下操作：

1. 使用转义孵化访问 `Service` L1 构造。

1. 添加 `capacityProviderStrategies?` 构造。

1. 部署服务。