web-dev-qa-db-ja.com

ECSでサーバーを自動スケーリングする方法は?

最近ECSを使い始めました。 ECRにコンテナイメージをデプロイし、CPU /メモリ制限を使用してコンテナのタスク定義を作成することができました。私のユースケースは、各コンテナーが長時間実行されるアプリになることです(Webサーバーやポートマッピングは必要ありません)。コンテナは一度に1つずつオンデマンドで生成され、一度に1つずつ削除されます。

N個のサーバーインスタンスでクラスターを作成できます。ただし、サーバーインスタンスを自動的にスケールアップ/スケールダウンできるようにしたいと思います。たとえば、クラスターに十分なCPU /メモリがない場合は、新しいインスタンスを作成したいと思います。

また、コンテナが実行されていないインスタンスがある場合は、その特定のインスタンスを縮小/削除したいと思います。これは、実行中のタスクが含まれているサーバーインスタンスの自動スケールダウン終了を回避するためです。

これを達成するにはどのような手順が必要ですか?

12
codeshark

すでにECSクラスターが作成されていることを考慮して、AWSは CloudWatchアラームを使用したクラスターインスタンスのスケーリング に関する手順を提供します。

メモリ予約に基づいてクラスターを高レベルでスケーリングする場合は、次の手順を実行する必要があります。

  1. AutoScalingグループの起動構成を作成します。この
  2. Auto Scaling Groupを作成して、クラスターのサイズを拡大および縮小できるようにします。
  3. CloudWatchアラームを作成して、メモリ予約が70%を超えている場合にクラスターをスケールアップします
  4. CloudWatchアラームを作成して、メモリ予約が30%未満の場合にクラスターをスケールダウンします

それは私の専門分野であるため、例を作成しました 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時間支払うという既知のプロパティがあります。これは、インスタンスの一部の時間が1時間として課金されるためです。それが関係する理由は、複数のアラームがあると想像してください。現在アイドル状態で実行されている多数のサービスがあり、クラスターがいっぱいになったとします。 CPUアラームがクラスターをスケールダウンするか、メモリアラームがクラスターをスケールアップします。これらの1つは、アラームがトリガーされなくなるまでクラスターをスケーリングする可能性があります。クールダウン期間の後、他のアラームは最後のアクションを元に戻します。次のクールダウンの後、アクションはおそらくやり直されます。したがって、インスタンスは作成され、1つおきのクールダウンで繰り返し破棄されます。

これについてたくさん考えた後、私が思いついた戦略は、CPU使用率に基づいて ECSサービスのアプリケーション自動スケーリング を使用し、クラスターに基づいてメモリ予約を使用することでした。したがって、1つのサービスがホットで実行されている場合、負荷を共有するために追加のタスクが追加されます。これにより、クラスターメモリの予約容量が徐々にいっぱいになります。メモリがいっぱいになると、クラスターがスケールアップします。サービスがクールダウンすると、サービスはタスクのシャットダウンを開始します。クラスタのメモリ予約が減少すると、クラスタは縮小されます。

タスク定義に基づいて、CloudWatchアラームのしきい値を試す必要がある場合があります。これは、スケールアップのしきい値を高くしすぎると、メモリが消費されてもスケールアップしない可能性があり、自動スケーリングで別のタスクを配置すると、使用可能なメモリが不足していることがわかるためです。クラスタ内のインスタンスであるため、別のタスクを配置できません。

4
Jamie Starke