Upgrade to Pro — share decks privately, control downloads, hide ads and more …

安定・安価なECS auto scalingを目指して / SRE Lounge #11

安定・安価なECS auto scalingを目指して / SRE Lounge #11

Takeshi Arabiki

October 29, 2019
Tweet

More Decks by Takeshi Arabiki

Other Decks in Technology

Transcript

  1. 安定・安価なECS auto scalingを⽬指して
    SRE Lounge #11(2019-10-29)
    Repro株式会社
    Takeshi Arabiki (@a_bicky)

    View Slide

  2. • Twitter: @a_bicky
    • Blog: あらびき⽇記
    • 所属: Repro株式会社 (2017 年 8 ⽉〜)
    • SREっぽいことをしたり
    • 分析基盤っぽいことをしたり
    • 開発環境整備をしたり
    • Railsアプリケーション触ったり
    • アーキテクチャ刷新的なことに関わったり
    ⾃⼰紹介

    View Slide

  3. • ECS auto scalingに必要な最低限の知識
    • ReproのECS auto scalingの構成
    • ECS auto scalingの課題と対処法
    • これからの話
    • まとめ
    アジェンダ

    View Slide

  4. ECS auto scalingに必要な最低限の知識

    View Slide

  5. • Task Definitions
    • 1つ以上のDockerコンテナの定義、リソースの割当などを定義するもの
    • Tasks
    • task definitionの内容を基に起動されたコンテナ郡
    • オブジェクト指向を例にすると、task definitionがクラス、taskがインスタンスみたいなもの
    • Services
    • 指定されたtask definitionのtaskを指定されたdesired countの数だけ起動するもの
    • ALB, NLBとの連携、auto scaling、デプロイの管理なども⾏える
    • Clusters
    • taskを動かすためのEC2 instancesを登録したり、servicesを登録したりするための箱
    Amazon ECSの⼤雑把な⽤語説明

    View Slide

  6. Amazon ECSの⼤雑把な⽤語説明
    tasks
    service 1
    EC2 instances (container instances)
    Cluster
    task definition 1
    desired count = 3
    tasks
    service 2
    task definition 2
    desired count = 1

    View Slide

  7. ECSのauto scalingのポイント
    • servicesのdesired countを調整する必要がある
    • desired countを増やした際の新しいtasksが起動するまでの時間は短くしたい
    • clustersを構成するinstancesの数(clustersのサイズ)を調整する必要がある
    • servicesのdesired countを変えてもinstancesの数は固定
    • clustersサイズを減らす際にはinstancesのdraining (graceful stop) が必要
    • コストを抑えるためにはinstancesにはspot instancesを使いたい

    View Slide

  8. ReproのECS auto scalingの構成

    View Slide

  9. ReproのECS auto scailngの構成
    Auto scaling group for a ECS cluster
    ECS cluster with reserved instances
    API tasks
    API service
    Worker tasks
    Worker service
    ecs_auto_scaler task
    ecs_auto_scaler service
    Auto scaling group for a ECS cluster
    ECS cluster with spot instances
    API tasks
    API service
    Auto scaling group for a ECS cluster
    ECS cluster with spot instances
    Worker tasks
    Worker service

    View Slide

  10. • clustersのサイズはauto scaling groupsで管理
    • auto scaling⽤のclustersにはspot instancesを使⽤
    • servicesのdesired countとclustersのサイズを管理するECS serviceがある
    • spot instancesのinterruption warningsを処理してdrainingするのもこのservice
    ReproのECS auto scailngの構成

    View Slide

  11. ECS scailng時の動作
    Auto scaling group for a ECS cluster
    ECS cluster with reserved instances
    API tasks
    API service
    Worker tasks
    Worker service
    ecs_auto_scaler task
    ecs_auto_scaler service
    Auto scaling group for a ECS cluster
    ECS cluster with spot instances
    API tasks
    API service
    Auto scaling group for a ECS cluster
    ECS cluster with spot instances
    Worker tasks
    Worker service
    ① Check CloudWatch alarm state

    View Slide

  12. Auto scaling group for a ECS cluster
    ECS cluster with reserved instances
    API tasks
    API service
    Worker tasks
    Worker service
    ecs_auto_scaler task
    ecs_auto_scaler service
    Auto scaling group for a ECS cluster
    ECS cluster with spot instances
    API tasks
    API service
    ② Update desired count
    ECS scailng時の動作
    Auto scaling group for a ECS cluster
    ECS cluster with spot instances
    Worker tasks
    Worker service

    View Slide

  13. Auto scaling group for a ECS cluster
    ECS cluster with reserved instances
    API tasks
    API service
    Worker tasks
    Worker service
    ecs_auto_scaler task
    ecs_auto_scaler service
    Auto scaling group for a ECS cluster
    ECS cluster with spot instances
    API tasks
    API service
    ③ Update desired capacity
    ECS scailng時の動作
    Auto scaling group for a ECS cluster
    ECS cluster with spot instances
    Worker tasks
    Worker service

    View Slide

  14. Spot instancesのinterruption時の動作
    Auto scaling group for a ECS cluster
    ECS cluster with reserved instances
    API tasks
    API service
    Worker tasks
    Worker service
    ecs_auto_scaler task
    ecs_auto_scaler service
    ① Receive interruption warnings from SQS
    Auto scaling group for a ECS cluster
    ECS cluster with spot instances
    API tasks
    API service
    Auto scaling group for a ECS cluster
    ECS cluster with spot instances
    Worker tasks
    Worker service

    View Slide

  15. Auto scaling group for a ECS cluster
    ECS cluster with reserved instances
    API tasks
    API service
    Worker tasks
    Worker service
    ecs_auto_scaler task
    ecs_auto_scaler service
    ② Drain container instances
    Auto scaling group for a ECS cluster
    ECS cluster with spot instances
    API tasks
    API service
    Spot instancesのinterruption時の動作
    Auto scaling group for a ECS cluster
    ECS cluster with spot instances
    Worker tasks
    Worker service

    View Slide

  16. Auto scaling group for a ECS cluster
    ECS cluster with reserved instances
    API tasks
    API service
    Worker tasks
    Worker service
    ecs_auto_scaler task
    ecs_auto_scaler service
    ③ Detach instances
    Auto scaling group for a ECS cluster
    ECS cluster with spot instances
    API tasks
    API service
    Spot instancesのinterruption時の動作
    Auto scaling group for a ECS cluster
    ECS cluster with spot instances
    Worker tasks
    Worker service

    View Slide

  17. • github.com/reproio/ecs_deploy で提供されているプログラム
    • service auto scalingもFargateもなかった頃に導⼊されたもの
    • CloudWatchのalarmsのstateを基にECS servicesのdesired countを増減する
    • desired countに応じてauto scaling groupのdesired capacityも更新する
    • scale-outの時間を短縮するためにinstancesを余計に確保する設定がある
    • desired countを減らす際はタスクの配置されていないinstancesを落とす
    • Spot instancesのinterruption warningsを受け取ったらdrainingする
    • 別途CloudWatch ruleとSQSの設定が必要
    • ECS_ENABLE_SPOT_INSTANCE_DRAININGパラメータを設定すれば不要
    ECS Autoscaler

    View Slide

  18. Fargate
    https://aws.amazon.com/jp/fargate/

    View Slide

  19. • reserved instances, spot instancesに⽐べるとかなり割⾼
    • パフォーマンスが低い
    • タスクの起動が遅い
    • log driverがawslogs⼀択
    • 最近FireLensが正式リリースされたのでこの問題は解消できるはず
    • Fargateの導⼊をしっかり検討するだけの開発リソースがない
    Fargateを採⽤しない理由

    View Slide

  20. ECS auto scalingの課題と対処法

    View Slide

  21. • auto scaling groupsのcapacityを減らすだけだとtasksをgraceful stopできない
    • 闇雲にdesired countを増やすとtasksの起動に5 分以上かかることがある
    • ECS servicesのscale-inが完了したタイミングを取るにはひと⼿間必要
    • availability zoneの均衡が崩れるとtasksの動いているinstancesでも落とされる
    • spot instancesがinterruptされてAZの均衡が崩れることがある
    • 起動直後のspot instancesがinterruptされる場合drainingできない
    ECS auto scalingの課題と対処法

    View Slide

  22. • auto scaling groupsのcapacityを減らすだけだとtasksをgraceful stopできない
    • 闇雲にdesired countを増やすとtasksの起動に5 分以上かかることがある
    • ECS servicesのscale-inが完了したタイミングを取るにはひと⼿間必要
    • availability zoneの均衡が崩れるとtasksの動いているinstancesでも落とされる
    • spot instancesがinterruptされてAZの均衡が崩れることがある
    • 起動直後のspot instancesがinterruptされる場合drainingできない
    ECS auto scalingの課題と対処法

    View Slide

  23. • CloudWatchのメトリクスの値を使ってECS servicesのdesired countを調整
    • ECS clustersのサイズの⾯倒は⾒ない
    • auto scaling groupsで管理してCPUReservationを基にdesired capacityを調整するのが⼀般的
    Service Auto Scaling

    View Slide

  24. Automatic Scaling with Amazon ECS
    https://aws.amazon.com/blogs/compute/automatic-scaling-with-amazon-ecs/

    View Slide

  25. Automatic Scaling with Amazon ECS
    https://aws.amazon.com/blogs/compute/automatic-scaling-with-amazon-ecs/
    capacityを減らすとタスクが強制終了させられるかもよ

    View Slide

  26. • auto scaling groupsのlifecycle hooksを利⽤してdrainingする
    • How to Automate Container Instance Draining in Amazon ECS
    • instance protectionを使ってtasksの動いているinstancesを保護する
    • EC2 Auto-ScalingでECS組んでますか?エラーレート⾼いですか?救ってあげてもいいですか?
    • ⾃前でauto scalingを実装する
    • e.g. ECS Autoscaler
    capacityを安全に減らす⽅法

    View Slide

  27. • auto scaling groupsのcapacityを減らすだけだとtasksをgraceful stopできない
    • 闇雲にdesired countを増やすとtasksの起動に5 分以上かかることがある
    • ECS servicesのscale-inが完了したタイミングを取るにはひと⼿間必要
    • availability zoneの均衡が崩れるとtasksの動いているinstancesでも落とされる
    • spot instancesがinterruptされてAZの均衡が崩れることがある
    • 起動直後のspot instancesがinterruptされる場合drainingできない
    ECS auto scalingの課題と対処法

    View Slide

  28. ある⽇のscale-out
    spot fleet requestsのhistory(当時はASGの代わりに使⽤)
    ECS servicesのevents
    インスタンスが起動してから新しいtasksが起動するまでに約6分

    View Slide

  29. リソースが⾜りない状態が続いた場合の起動時間を検証
    # (snip)
    6.times do |i|
    puts "#{i + 1}th try"
    sleep_sec = i * 10
    ecs.update_container_instances_state(
    cluster: cluster, container_instances: arns, status: 'DRAINING')
    ecs.update_service(cluster: cluster, service: svc, desired_count: 1)
    updated_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
    sleep sleep_sec
    ecs.update_container_instances_state(
    cluster: cluster, container_instances: arns, status: 'ACTIVE')
    ecs.wait_until(:services_stable, { cluster: cluster, services: [svc] },
    delay: 1, max_attempts: nil)
    elapsed_sec = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - updated_time).round
    puts "Sleep: #{sleep_sec} sec, Elapsed: #{elapsed_sec} sec"
    # (snip)

    View Slide

  30. リソースが⾜りない状態が続いた場合の起動時間を検証
    1th try
    Sleep: 0 sec, Elapsed: 12 sec
    2th try
    Sleep: 10 sec, Elapsed: 23 sec
    3th try
    Sleep: 20 sec, Elapsed: 32 sec
    4th try
    Sleep: 30 sec, Elapsed: 42 sec
    5th try
    Sleep: 40 sec, Elapsed: 51 sec
    6th try
    Sleep: 50 sec, Elapsed: 353 sec

    View Slide

  31. ECS Autoscalerの改修
    https://github.com/reproio/ecs_deploy/pull/53

    View Slide

  32. • リソースが確保できてから増やす
    desired countを増やす時のポイント

    View Slide

  33. • auto scaling groupsのcapacityを減らすだけだとtasksをgraceful stopできない
    • 闇雲にdesired countを増やすとtasksの起動に5 分以上かかることがある
    • ECS servicesのscale-inが完了したタイミングを取るにはひと⼿間必要
    • availability zoneの均衡が崩れるとtasksの動いているinstancesでも落とされる
    • spot instancesがinterruptされてAZの均衡が崩れることがある
    • 起動直後のspot instancesがinterruptされる場合drainingできない
    ECS auto scalingの課題と対処法

    View Slide

  34. 危険なコード
    # Stop all tasks and terminate all instances in the cluster
    ecs.update_service(cluster: cluster, service: svc, desired_count: 0)
    ecs.wait_until(:services_stable, cluster: cluster, services: [svc])
    ec2.terminate_instances(instance_ids: container_instance_ec2_ids)

    View Slide

  35. ECSにおけるservice stable
    https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-lifecycle.html
    {
    "expected" => true,
    "matcher" => "path",
    "state" => "success",
    "argument" => "length(services[?!(length(deployments)
    == `1` && running_count == desired_count)]) == `0`"
    }
    • desired countを減らした場合はstoppingな

    タスクがあってもstableになる
    aws-sdk-ecs/waiters.rb#L57-L111

    View Slide

  36. 安全なコード
    # Stop all tasks and terminate all instances in the cluster
    running_task_arns = ecs.list_tasks(
    cluster: cluster, service_name: svc, desired_status: 'RUNNING'
    ).flat_map(&:task_arns)
    ecs.update_service(cluster: cluster, service: svc, desired_count: 0)
    ecs.wait_until(:services_stable, cluster: cluster, services: [svc])
    stopping_task_arns = running_task_arns - ecs.list_tasks(
    cluster: cluster, service_name: service, desired_status: 'RUNNING'
    ).flat_map(&:task_arns)
    stopping_task_arns.each_slice(100) do |arns|
    ecs.wait_until(:tasks_stopped, cluster: cluster, tasks: arns)
    end
    ec2.terminate_instances(instance_ids: container_instance_ec2_ids)

    View Slide

  37. ECS Autoscalerの改修
    https://github.com/reproio/ecs_deploy/pull/50

    View Slide

  38. • service stable後、serviceから外れたtasksがstoppedになったことを確認する
    scale-inの完了を判断する⽅法

    View Slide

  39. • auto scaling groupsのcapacityを減らすだけだとtasksをgraceful stopできない
    • 闇雲にdesired countを増やすとtasksの起動に5 分以上かかることがある
    • ECS servicesのscale-inが完了したタイミングを取るにはひと⼿間必要
    • availability zoneの均衡が崩れるとtasksの動いているinstancesでも落とされる
    • spot instancesがinterruptされてAZの均衡が崩れることがある
    • 起動直後のspot instancesがinterruptされる場合drainingできない
    ECS auto scalingの課題と対処法

    View Slide

  40. ある⽇のscale-in
    auto scaling groupsのactivity history

    View Slide

  41. AZRebalance
    https://docs.aws.amazon.com/autoscaling/ec2/userguide/auto-scaling-benefits.html#AutoScalingBehavior.InstanceUsage

    View Slide

  42. AZRebalance
    https://docs.aws.amazon.com/autoscaling/ec2/userguide/auto-scaling-benefits.html#AutoScalingBehavior.InstanceUsage
    ⾃分でdetachする場合はAZのバランスを考慮しないといけない

    View Slide

  43. ECS Autoscalerの改修
    https://github.com/reproio/ecs_deploy/pull/52

    View Slide

  44. • auto scaling groupsのlifecycle hooksでinstancesをdrainingする
    • AZRelabanceをsuspendする
    • capacityを頻繁に変えていればそのうちバランスが取れるので⼤して問題にならない
    • ⾃前でdetachする場合はAZのバランスを考慮する
    • ※その他の要因でバランスが崩れた場合は対処できない
    AZRebalanceにtasksを強制終了させられない⽅法

    View Slide

  45. • auto scaling groupsのcapacityを減らすだけだとtasksをgraceful stopできない
    • 闇雲にdesired countを増やすとtasksの起動に5 分以上かかることがある
    • ECS servicesのscale-inが完了したタイミングを取るにはひと⼿間必要
    • availability zoneの均衡が崩れるとtasksの動いているinstancesでも落とされる
    • spot instancesがinterruptされてAZの均衡が崩れることがある
    • 起動直後のspot instancesがinterruptされる場合drainingできない
    ECS auto scalingの課題と対処法

    View Slide

  46. ある⽇のscale-in
    auto scaling groupsのactivity history

    View Slide

  47. • 短い間に特定AZのinsntacesが複数落とされることがある
    • AZの均衡を考慮してinterruptionするわけじゃない
    Spot Instance Interruptions

    View Slide

  48. Let's suspend AZRebalance

    View Slide

  49. • auto scaling groupsのlifecycle hooksでinstancesをdrainingする
    • AZRelabanceをsuspendする
    • capacityを頻繁に変えていればそのうちバランスが取れるので⼤して問題にならない
    • ⾃前でdetachする場合はAZのバランスを考慮する
    • ※その他の要因でバランスが崩れた場合は対処できない
    AZRebalanceにtasksを強制終了させられない⽅法(再掲)

    View Slide

  50. • auto scaling groupsのcapacityを減らすだけだとtasksをgraceful stopできない
    • 闇雲にdesired countを増やすとtasksの起動に5 分以上かかることがある
    • ECS servicesのscale-inが完了したタイミングを取るにはひと⼿間必要
    • availability zoneの均衡が崩れるとtasksの動いているinstancesでも落とされる
    • spot instancesがinterruptされてAZの均衡が崩れることがある
    • 起動直後のspot instancesがinterruptされる場合drainingできない
    ECS auto scalingの課題と対処法

    View Slide

  51. あるInstanceの情報
    Launch time: October 21, 2019 at 11:55:52 AM UTC+9
    State transition reason: Service initiated (2019-10-21 02:58:26 GMT)
    State transition reason: message Service.SpotInstanceTermination
    起動から削除までわずか2.5分

    View Slide

  52. • interruption warningsを受け取った時点では何もできない
    • 新しいinstanceが起動してからauto scaling groupsでInServiceになるのに約30秒
    • 新しいinstanceが起動してからECS clusterに登録されるのに約30秒
    起動直後のSpot Instancesをinterruptされることの問題点

    View Slide

  53. • instancesがclustersに登録されるまで待ってからdrainingする
    • instances⾃⾝がinstance metadataのinstance-actionを監視してdrainingする
    対策(未対応)

    View Slide

  54. これからの話

    View Slide

  55. • 解像度1分のCloudWatchのmetricsだとauto scalingが間に合わないことが度々
    • 平⽇・休⽇の傾向も考慮するだけでかなり良くなるはず
    • ⾼解像度のmetricsの使⽤やCloudWatchに依存しないauto scalingも良さそう
    • 明らかに異常なリクエスト数があっても許容してしまっている
    • 429を返したい
    • お客さんのサービスによって使われ⽅が全然違うので異常かどうかの判断が⾮常に難しい
    • FargateやKubernetesの検証をやれてない
    • "SRE"と呼ばれる⼈たちが機能開発やら開発環境整備やらもやっている現状
    • ⼈が!⾜り!!ない!!!!
    課題はたくさん

    View Slide

  56. まとめ

    View Slide

  57. • auto scaling groupsのcapacityを減らすだけだとtasksをgraceful stopできない
    • → lifecycle hooks, instance protectionで対処するか⾃前でauto scalingの仕組みを構築する
    • 闇雲にdesired countを増やすとtasksの起動に5 分以上かかることがある
    • → clustersのリソースを確保してからdesired countを増やすことを徹底する
    • ECS servicesのscale-inが完了したタイミングを取るにはひと⼿間必要
    • → services stable waiterだけでなくtasks stopped waiterも併⽤する
    まとめ (1/2)

    View Slide

  58. • availability zoneの均衡が崩れるとtasksの動いているinstancesでも落とされる
    • → lifecycle hooksでdrainingする、AZRebalanceをsuspendする、detachする時に頑張る
    • spot instancesがinterruptされてAZの均衡が崩れることがある
    • → lifecycle hooksでdrainingする、AZRebalanceをsuspendする
    • 起動直後のspot instancesがinterruptされる場合drainingできない
    • → clustersに登録されるまで待ってdrainingする、instance⾃⾝にdrainingさせる
    まとめ (2/2)

    View Slide