如何自动缩放ECS中的服务器?

时间:2017-09-13 19:23:28

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

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

我能够创建一个包含N个服务器实例的集群。但我希望服务器实例能够自动向上/向下扩展。例如,如果群集中没有足够的CPU /内存,我想要创建一个新实例。

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

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

2 个答案:

答案 0 :(得分:2)

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

假设您希望根据内存预留来扩展群集,则需要执行以下操作:

  1. 为Auto Scaling组创建启动配置。这个
  2. 创建Auto Scaling组,以便可以扩大和缩小群集的大小。
  3. 如果内存预留超过70%
  4. ,请创建CloudWatch警报以扩展群集
  5. 如果内存预留低于30%
  6. ,请创建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利用率使用Application Autoscaling for ECS Services,基于群集使用内存预留。因此,如果一个服务正在运行,则将添加一个额外的任务来共享负载。这将慢慢填满群集内存预留容量。当内存已满时,群集会扩展。当服务冷却时,服务将开始关闭任务。随着群集上的内存预留量下降,群集将按比例缩小。

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

答案 1 :(得分:1)

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

但是,根据您要运行的内容,AWS Fargate可能是一个更好的选择。 Fargate使您无需配置和管理基础架构即可运行容器。也就是说,您不必处理任何EC2实例。使用Fargate,您可以进行API调用来运行容器,容器可以运行,一旦容器停止运行,便无需清理任何内容。 Fargate每秒计费(最少1分钟),并根据分配的CPU和内存量进行定价(有关详细信息,请参见here