Skip to content

Instantly share code, notes, and snippets.

@toyama0919
Last active January 28, 2023 06:10
Show Gist options
  • Save toyama0919/6f58e72d8f9af67fe60715b3f3ce8067 to your computer and use it in GitHub Desktop.
Save toyama0919/6f58e72d8f9af67fe60715b3f3ce8067 to your computer and use it in GitHub Desktop.

Autoscaling色々

はじめに

  • autoscaling全般についてはなします
  • terraformのコードがいっぱい出てきます

はなすこと

  • application autoscaling
  • capacity provider strategy
  • launch template

application autoscaling

autoscalingには2種類ある

  • autoscaling(無印)
    • ec2のみ
  • application autoscaling
    • ecs
    • EMR
    • ec2
    • appstream
    • dynamodb
    • rds
    • sagemaker
    • custom-resource
    • comprehend
    • lambda
    • cassandra

application autoscalingのScalableDimension

autoscalingできる対象は以下

  • ecs:service:DesiredCount
  • lambda:function:ProvisionedConcurrency
  • elasticmapreduce:instancegroup:InstanceCount
  • ec2:spot-fleet-request:TargetCapacity
  • sagemaker:variant:DesiredInstanceCount
  • dynamodb:table:ReadCapacityUnits
  • dynamodb:table:WriteCapacityUnits
  • dynamodb:index:ReadCapacityUnits
  • dynamodb:index:WriteCapacityUnits
  • rds:cluster:ReadReplicaCount
  • appstream:fleet:DesiredCapacity
  • custom-resource:ResourceType:Property
  • comprehend:document-classifier-endpoint:DesiredInferenceUnits
  • cassandra:table:ReadCapacityUnits
  • cassandra:table:WriteCapacityUnits

scaling policyのおさらい

  • Simple scaling
    • 1 つのスケーリング調整値に基づいて、グループの現在の容量を増減させます。
      • 範囲でもなくalarmをsubscribeしたらそのとおりに実行
    • application autoscalingでは使えない(無印だけ)
  • Step scaling
    • アラーム超過のサイズに応じて変動する一連のスケーリング調整値 (ステップ調整値と呼ばれる) に基づいて、グループの現在の容量を増減させます。
    • メトリクスの範囲に応じて台数を増減させる
    • 例.SQSの数が1ならworkerを+1、10なら+3, 100なら+5
  • Target tracking scaling
    • 特定のメトリクスのターゲット値に基づいて、グループの現在の容量を増減させます。
    • 例.CPU利用率のターゲット値が75なら, 75に近くなるようなscalingをする
      • CPU利用率90なら台数を増やす
      • CPU利用率60なら台数を減らす

Adjustment Type

  • ChangeInCapacity
    • 増減数を指定する
    • +1, -1など
  • ExactCapacity
    • 固定された台数の指定
    • 10台、100台など
  • PercentChangeInCapacity
    • 増減数をパーセンテージで指定
    • Desired Capacity : 4 / Scaling Adjustment : 50% の場合、2台増加する
    • Desired Capacity : 4 / Scaling Adjustment : -50% の場合、2台減らす

Simple scaling, Step scalingで指定可能

application autoscaling(dynamo DB)

resource "aws_appautoscaling_target" "dynamodb_table_read_target" {
  max_capacity       = 100
  min_capacity       = 5
  resource_id        = "table/tableName"
  scalable_dimension = "dynamodb:table:ReadCapacityUnits"
  service_namespace  = "dynamodb"
}

resource "aws_appautoscaling_policy" "dynamodb_table_read_policy" {
  name               = "DynamoDBReadCapacityUtilization:${aws_appautoscaling_target.dynamodb_table_read_target.resource_id}"
  policy_type        = "TargetTrackingScaling"
  resource_id        = aws_appautoscaling_target.dynamodb_table_read_target.resource_id
  scalable_dimension = aws_appautoscaling_target.dynamodb_table_read_target.scalable_dimension
  service_namespace  = aws_appautoscaling_target.dynamodb_table_read_target.service_namespace

  target_tracking_scaling_policy_configuration {
    predefined_metric_specification {
      predefined_metric_type = "DynamoDBReadCapacityUtilization"
    }

    target_value = 70 # DynamoDBReadCapacityUtilizationが70に近づくようにscalingする
  }
}

dynamo DBは以下に対応している

  • table:ReadCapacityUnits
  • table:WriteCapacityUnits
  • index:ReadCapacityUnits
  • index:WriteCapacityUnits

application autoscaling(Aurora)

  • RDS(Aurora)のread replicaを動的にするautoscaling
resource "aws_appautoscaling_target" "replicas" {
  service_namespace  = "rds"
  scalable_dimension = "rds:cluster:ReadReplicaCount"
  resource_id        = "cluster:${aws_rds_cluster.example.id}"
  min_capacity       = 1
  max_capacity       = 15
}

resource "aws_appautoscaling_policy" "replicas" {
  name               = "cpu-auto-scaling"
  service_namespace  = aws_appautoscaling_target.replicas.service_namespace
  scalable_dimension = aws_appautoscaling_target.replicas.scalable_dimension
  resource_id        = aws_appautoscaling_target.replicas.resource_id
  policy_type        = "TargetTrackingScaling"

  target_tracking_scaling_policy_configuration {
    predefined_metric_specification {
      predefined_metric_type = "RDSReaderAverageCPUUtilization"
    }

    target_value       = 75
    scale_in_cooldown  = 300
    scale_out_cooldown = 300
  }
}

application autoscaling(Sagemaker)

resource "aws_appautoscaling_target" "ecs_target" {
  max_capacity       = 4
  min_capacity       = 1
  resource_id        = "endpoint/my-end-point/variant/KMeansClustering"
  scalable_dimension = "sagemaker:variant:DesiredInstanceCount"
  service_namespace  = "sagemaker"
}

resource "aws_appautoscaling_policy" "sagemaker" {
  ...
}

application autoscaling(ECS)

resource "aws_appautoscaling_target" "ecs_target" {
  max_capacity       = 4
  min_capacity       = 1
  resource_id        = "service/clusterName/serviceName"
  scalable_dimension = "ecs:service:DesiredCount"
  service_namespace  = "ecs"
}

resource "aws_appautoscaling_policy" "ecs_policy" {
  name               = "scale-down"
  policy_type        = "StepScaling"
  resource_id        = aws_appautoscaling_target.ecs_target.resource_id
  scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension
  service_namespace  = aws_appautoscaling_target.ecs_target.service_namespace

  step_scaling_policy_configuration {
    adjustment_type         = "ChangeInCapacity"
    cooldown                = 60
    metric_aggregation_type = "Maximum"

    step_adjustment {
      metric_interval_upper_bound = 0
      scaling_adjustment          = -1
    }
  }
}
  • autoscalingの対象はserviceであり, task definitionではない
      resource_id        = "service/clusterName/serviceName"
      scalable_dimension = "ecs:service:DesiredCount"
    
  • serviceを使うようなweb serviceやagent型の場合に適用できる
  • ワンショットで実行するようなbatchでは使えない。

capacity provider

  • ECSにおけるタスク実行のインフラをより柔軟に設定する新しい仕組み
  • ECSのタスクを実行するインフラを決定する
    • EC2:Auto Scaling Group
    • Fargate:FARGATE, FARGATE_SPOT
  • ECSのautoscalingは以下の2段階
    • containerのautoscaling => application autoscaling
    • nodeのautoscaling => 無印autoscaling

capacity provider

img

capacity provider(Fargate)

resource "aws_ecs_cluster" "fargate" {
  name = "fargate_cluster"

  capacity_providers = [
    "FARGATE",
    "FARGATE_SPOT",
  ]

  # 100% spotで普段は0台
  default_capacity_provider_strategy {
    capacity_provider = "FARGATE_SPOT"
    base              = 0
    weight            = 1
  }
}

capacity provider(Fargate)

resource "aws_ecs_cluster" "fargate" {
  name = "fargate_cluster"

  capacity_providers = [
    "FARGATE",
    "FARGATE_SPOT",
  ]

  # 停止できないので2台はオンデマンドで立てておく
  # 残りは50%ずつの割合(weightが1:1)
  default_capacity_provider_strategy {
    capacity_provider = "FARGATE"
    base              = 2
    weight            = 1
  }
  default_capacity_provider_strategy {
    capacity_provider = "FARGATE_SPOT"
    base              = 0
    weight            = 1
  }
}

capacity provider(Fargate)

img

capacity provider(EC2)

  • EC2の場合はautoscaling groupと紐付けて使う
# clusterがcapacity providerを複数指定
# run-taskの引数としても指定可能なのでその際にfargateかec2を選択する事もできる
resource "aws_ecs_cluster" "this" {
  name = "my-cluster"

  capacity_providers = [aws_ecs_capacity_provider.this.name]

  # default_capacity_provider_strategyで指定されなかった場合のcapacity_providerを決められる
  default_capacity_provider_strategy {
    capacity_provider = aws_ecs_capacity_provider.this.name
    base              = 0
    weight            = 1
  }
}

# capacity_providerでautoscaling groupを指定する
resource "aws_ecs_capacity_provider" "this" {
  name = "my-capacity-provider"
  auto_scaling_group_provider {
    auto_scaling_group_arn = aws_autoscaling_group.this.arn
    managed_scaling {
      minimum_scaling_step_size = 1
      maximum_scaling_step_size = 1
      status                    = "ENABLED"
    }
  }
}

resource "aws_autoscaling_group" "this" {
  ...
}

capacity providerがない世界線(ec2の場合)

  • podをscaleさせる前にかならずinstanceをscaleさせる必要がある
  • instanceがない状態でrun-task(containerを起動)してもエラー

capacity providerがある世界線

  • instanceが0台で起動していない状態でrun-taskすると、
    1. containerがpendingになる
    2. capacity providerがautoscaling groupにresourceを要求
    3. intanceが起動
    4. containerもrunningになる

autoscaling groupのweighted_capacity

  • 2019年末に出た機能
  • インスタンスタイプの重み付けができるようになった
  • 要求スペックに近い状態が維持しやすくなり、コストが抑えやすい
resource "aws_autoscaling_group" "this" {
  name                = "my-autoscaling"
  min_size            = 10
  max_size            = 100
  vpc_zone_identifier = ["subnet-xxxxxxxxx"]

  mixed_instances_policy {
    launch_template {
      launch_template_specification {
        # launch templateのIDを指定
        # ここでsubnetを指定していても、autoscalingのsubnetが使われる
        launch_template_id = "lt-xxxxxxxxxxxxx"
      }

      instances_distribution {
        # オンデマンドで作る絶対数
        # この場合ベースラインのインスタンス台数は0台
        on_demand_base_capacity = 0
        # オンデマンドの比率
        # 0ならオンデマンド:spotが0:100になるのでspotでしか起動しない
        on_demand_percentage_above_base_capacity = 0
      }

      # c5.xlargeはインスタンス1台とみなされる
      override {
        instance_type     = "c5.xlarge"
        weighted_capacity = "1"
      }

      # c5.2xlargeはインスタンス2台とみなされる
      override {
        instance_type     = "c5.2xlarge"
        weighted_capacity = "2"
      }

      # c5.4xlargeはインスタンス4台とみなされる
      override {
        instance_type     = "c5.4xlarge"
        weighted_capacity = "4"
      }
    }
  }
}

autoscaling groupのweighted_capacity

この場合、c5.12xlargeを多めにしたほうがトータルコストは安くなる

インスタンスタイプ us-east-1a AZでのスポットインスタンス料金 重み 1重みあたりのコスト
c5.xlarge $0.090 1 $0.090
c5.2xlarge $0.180 2 $0.090
c5.4xlarge $0.341 4 $0.085
c5.12xlarge $0.779 12 $0.065
c5.18xlarge $1.207 18 $0.067
c5.24xlarge $1.555 24 $0.065

launch templateとは

  • instanceを起動するための設定を詰め込んだtemplate
  • ただのtemplateでしかないので課金はされない

launch templateのユースケース

  • 予めterraformなどでtemplateを用意しておき、開発者に起動してもらう
    • 起動させる詳細情報などを入れておき、開発者に細かい起動optionを意識させない事ができる
      • AMIのID
      • subnet
      • security group
      • IAM Role
    • 普通にrun-instanceさせると誤起動の可能性がある
      • SGフル開放のinstance起動しちゃったり、、
      • iam roleがなくて何もアクセスできないinstanceが起動したり
  • autoscaling groupに使う

launch template

run-instance(ec2の起動)にも使える

$ aws ec2 run-instances \
    --launch-template LaunchTemplateName=ubuntu18-base

パラメータの上書きもできる

$ aws ec2 run-instances \
    --launch-template LaunchTemplateName=ubuntu18-base \
    --instance-type m6g.medium

うまく上書きできないoptionもあるので注意。

launch template

autoscalingに使えるlaunch templateの制限

  • networkの設定が1つ(1subnet)
  • ondemand起動(spotではない)

他にもあるかも

launch template

terraformだとこんな感じ

resource "aws_launch_template" "ubuntu18-base" {
  name = "ubuntu18-base"

  block_device_mappings {
    device_name = "/dev/sda1"

    ebs {
      encrypted             = false
      delete_on_termination = true
      volume_type           = "gp2"
      volume_size = 20
    }
  }

  disable_api_termination = false

  iam_instance_profile {
    name = "test"
  }

  image_id = "ami-xxxxxxxx"

  instance_market_options {
    market_type = "spot"
  }

  instance_type = "t2.micro"

  key_name = "test"

  monitoring {
    enabled = true
  }

  network_interfaces {
    subnet_id                   = "subnet-xxxxxxxxx"
    delete_on_termination       = true
    associate_public_ip_address = false
    security_groups = ["sg-12345678"]
  }

  tag_specifications {
    resource_type = "instance"

    tags = {
      Service = "foo"
      Roles = "ubuntu18:base"
    }
  }

  user_data = filebase64("${path.module}/provisioning.sh")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment