【问题标题】:How to autoscale Servers in ECS?如何在 ECS 中自动缩放服务器?
【发布时间】:2018-02-22 15:03:30
【问题描述】:

我最近开始使用 ECS。我能够在 ECR 中部署容器映像,并为我的容器创建具有 CPU/内存限制的任务定义。我的用例是每个容器都是一个长时间运行的应用程序(不需要网络服务器,不需要端口映射)。容器将根据需要一次生成 1 个,并根据需要一次删除 1 个。

我能够创建一个包含 N 个服务器实例的集群。但我希望能够让服务器实例自动扩大/缩小。例如,如果集群中没有足够的 CPU/内存,我希望创建一个新实例。

如果有一个没有容器在其中运行的实例,我希望缩小/删除该特定实例。这是为了避免在其中运行任务的服务器实例自动缩减终止。

需要哪些步骤才能实现这一目标?

【问题讨论】:

  • CPU 还是内存哪个更重要?如果 CPU 说 scale up,而 memory 说 scale down,应该怎么办?
  • 谢谢杰米。我会说我的情况的记忆。在 ECS 中,有一个仪表板显示有多少 CPU 单元/内存已分配与未分配。我认为它基于容器的任务定义。我想根据这些 ECS 指标进行扩展
  • @codeshark 我有同样的用例。你认为你可以提供更多关于你是如何做到这一点的见解吗?

标签: amazon-web-services amazon-ec2 autoscaling amazon-ecs amazon-ecr


【解决方案1】:

考虑到您已经创建了 ECS 集群,AWS 在Scaling cluster instances with CloudWatch Alarms 上提供了说明。

假设您希望根据内存预留来扩展集群,在较高级别上,您需要执行以下操作:

  1. 为您的 Auto Scaling 组创建启动配置。这个
  2. 创建一个 Auto Scaling 组,以便集群的大小可以放大和缩小。
  3. 如果内存预留超过 70%,则创建 CloudWatch 警报以扩展集群
  4. 如果内存预留低于 30%,则创建 CloudWatch 警报以缩减集群

因为这更像是我的专长,所以我写了一个示例 CloudFormation 模板,它应该可以帮助您开始大部分内容:

Parameters:
  MinInstances:
    Type: Number
  MaxInstances:
    Type: Number
  InstanceType:
    Type: String
    AllowedValues:
      - t2.nano
      - t2.micro
      - t2.small
      - t2.medium
      - t2.large
  VpcSubnetIds:
    Type: String

Mappings:
  EcsInstanceAmis:
    us-east-2:
      Ami: ami-1c002379
    us-east-1:
      Ami: ami-9eb4b1e5
    us-west-2:
      Ami: ami-1d668865
    us-west-1:
      Ami: ami-4a2c192a
    eu-west-2:
      Ami: ami-cb1101af
    eu-west-1:
      Ami: ami-8fcc32f6
    eu-central-1:
      Ami: ami-0460cb6b
    ap-northeast-1:
      Ami: ami-b743bed1
    ap-southeast-2:
      Ami: ami-c1a6bda2
    ap-southeast-1:
      Ami: ami-9d1f7efe
    ca-central-1:
      Ami: ami-b677c9d2

Resources:
  Cluster:
    Type: AWS::ECS::Cluster
  Role:
    Type: AWS::IAM::Role
    Properties:
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          -
            Effect: Allow
            Action:
              - sts:AssumeRole
            Principal:
              Service:
                - ec2.amazonaws.com    
  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref Role    
  LaunchConfiguration:
    Type: AWS::AutoScaling::LaunchConfiguration
    Properties:
      ImageId: !FindInMap [EcsInstanceAmis, !Ref "AWS::Region", Ami]
      InstanceType: !Ref InstanceType
      IamInstanceProfile: !Ref InstanceProfile
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          echo ECS_CLUSTER=${Cluster} >> /etc/ecs/ecs.config  
  AutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      MinSize: !Ref MinInstances
      MaxSize: !Ref MaxInstances
      LaunchConfigurationName: !Ref LaunchConfiguration
      HealthCheckGracePeriod: 300
      HealthCheckType: EC2
      VPCZoneIdentifier: !Split [",", !Ref VpcSubnetIds]
    ScaleUpPolicy:
      Type: AWS::AutoScaling::ScalingPolicy
      Properties:
        AdjustmentType: ChangeInCapacity
        AutoScalingGroupName: !Ref AutoScalingGroup
        Cooldown: '1'
        ScalingAdjustment: '1'
    MemoryReservationAlarmHigh:
      Type: AWS::CloudWatch::Alarm
      Properties:
        EvaluationPeriods: '2'
        Statistic: Average
        Threshold: '70'
        AlarmDescription: Alarm if Cluster Memory Reservation is to high
        Period: '60'
        AlarmActions:
        - Ref: ScaleUpPolicy
        Namespace: AWS/ECS
        Dimensions:
        - Name: ClusterName
          Value: !Ref Cluster
        ComparisonOperator: GreaterThanThreshold
        MetricName: MemoryReservation
    ScaleDownPolicy:
      Type: AWS::AutoScaling::ScalingPolicy
      Properties:
        AdjustmentType: ChangeInCapacity
        AutoScalingGroupName: !Ref AutoScalingGroup
        Cooldown: '1'
        ScalingAdjustment: '-1'
    MemoryReservationAlarmLow:
      Type: AWS::CloudWatch::Alarm
      Properties:
        EvaluationPeriods: '2'
        Statistic: Average
        Threshold: '30'
        AlarmDescription: Alarm if Cluster Memory Reservation is to Low
        Period: '60'
        AlarmActions:
        - Ref: ScaleDownPolicy
        Namespace: AWS/ECS
        Dimensions:
        - Name: ClusterName
          Value: !Ref Cluster
        ComparisonOperator: LessThanThreshold
        MetricName: MemoryReservation

这会创建一个 ECS 集群、一个启动配置、一个 AutoScaling 组以及基于 ECS 内存预留的警报。

现在我们可以进行有趣的讨论了。

为什么我们不能根据 CPU 利用率进行扩展内存预留?

简短的回答是你完全可以但是你可能会为此付出很多。 EC2 有一个已知属性,即当您创建实例时,您至少需要支付 1 小时的费用,因为部分实例小时数按完整小时数计费。为什么这很重要,假设您有多个警报。假设您有一堆当前空闲运行的服务,并且您填充了集群。 CPU 警报会缩小集群,或者内存警报会扩大集群。其中之一可能会将集群扩展到不再触发警报的程度。在冷却时间之后,另一个警报将撤消它的最后一个动作,在下一个冷却时间之后,该动作可能会被重做。因此实例被创建,然后在每隔一个冷却时间重复销毁。

想了这么多,我想出的策略是基于CPU Utilization 使用Application Autoscaling for ECS Services,基于集群使用Memory Reservation。因此,如果一个服务正在热运行,则会添加一个额外的任务来分担负载。这将慢慢填满集群内存预留容量。当内存变满时,集群会向上扩展。当服务冷却时,服务将开始关闭任务。随着集群上的内存预留下降,集群将被缩减。

可能需要根据您的任务定义试验 CloudWatch 警报的阈值。这样做的原因是,如果你将扩展阈值设置得太高,它可能不会随着内存的消耗而扩展,然后当自动扩展去放置另一个任务时,它会发现任何一个都没有足够的内存可用集群中的实例,因此无法放置另一个任务。

【讨论】:

  • EC2 实例现在按分钟计费。
  • @Jamie Starke,我使用了您的模板,但遇到了一个问题,即警报被正确触发但集群的容量没有得到扩展(增加或减少)。我可以确认尚未达到最小和最大容量。你知道可能出了什么问题吗?这是:stackoverflow.com/q/59495847/68759
【解决方案2】:

作为今年re:Invent 会议的一部分,AWS 宣布了cluster auto scaling for Amazon ECS。配置了 Auto Scaling 的集群现在可以在需要时添加更多容量并删除不必要的容量。你可以在the documentation找到更多相关信息。

但是,根据您要运行的内容,AWS Fargate 可能是更好的选择。 Fargate 允许您在不预置和管理底层基础架构的情况下运行容器;即,您不必处理任何 EC2 实例。使用 Fargate,您可以进行 API 调用来运行您的容器,容器可以运行,然后一旦容器停止运行,就没有什么需要清理的了。 Fargate 按每秒计费(最少 1 分钟),并根据分配的 CPU 和内存量定价(有关详细信息,请参阅 here)。

【讨论】:

    猜你喜欢
    • 2020-04-22
    • 1970-01-01
    • 2020-09-30
    • 2020-06-04
    • 1970-01-01
    • 2017-08-03
    • 1970-01-01
    • 2021-06-08
    • 2021-04-24
    相关资源
    最近更新 更多