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

cod*_*ark 9 amazon-ec2 amazon-web-services amazon-ecs autoscaling amazon-ecr

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

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

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

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

Jam*_*rke 6

考虑到您已经创建了 ECS 集群,AWS 提供了有关使用 CloudWatch 警报扩展集群实例的说明。

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

  1. 为您的 Auto Scaling 组创建启动配置。这个
  2. 创建一个 Auto Scaling Group,以便集群的大小可以扩展和缩减。
  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
Run Code Online (Sandbox Code Playgroud)

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

现在我们可以开始有趣的讨论了。

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

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

想了想,我想到的策略是基于CPU利用率的ECS服务应用自动伸缩,基于集群的内存预留。因此,如果一项服务正在运行,则会添加一个额外的任务来分担负载。这将慢慢填满集群内存预留容量。当内存已满时,集群会向上扩展。当服务冷却时,服务将开始关闭任务。随着集群上的内存预留下降,集群将缩小。

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

  • EC2 实例现在按分钟计费。 (4认同)