Cookpad Tech Kitchen #20 Amazon ECS の安定運用 / Building a steady ECS infrastructure

Eec11c7d221770d15a4b16104f3cf07e?s=47 Kohei Suzuki
November 28, 2018

Cookpad Tech Kitchen #20 Amazon ECS の安定運用 / Building a steady ECS infrastructure

Eec11c7d221770d15a4b16104f3cf07e?s=128

Kohei Suzuki

November 28, 2018
Tweet

Transcript

  1. Amazon ECS の安定運用 Kohei Suzuki

  2. アウトライン - コンテナインスタンスの管理 - スポットインスタンス対応 - コンテナインスタンスのオートスケーリング - ログ -

    配送、保存、検索 - モニタリング
  3. 規模感 - ほとんどのアプリケーションが ECS 上で動いている - hako (自作ツール) を使ってデプロイやバッチジョブの起動を行っている -

    ECS クラスタ数: 40 - 合計 ECS サービス数: 500 - 1日あたりの RunTask 数: 80,000
  4. コンテナインスタンスの管理

  5. コンテナインスタンスの管理 - オンデマンドインスタンスは AutoScaling Group - ECS クラスタと AutoScaling Group

    が一対一対応 - スポットインスタンスは Spot Fleet - ECS クラスタと Spot Fleet が一対一対応 - オンデマンド・スポット比: 1:4
  6. Fargate? - 一部では Fargate も使っているが、基本は自前管理のインスタンス - スポットインスタンスを使ったほうが安い - Fargate だと起動が遅い、起動までの時間が安定しない

    - Web アプリではそこまで困らない - そこそこの頻度で起動するバッチジョブだとつらい - Fargate を使うケース - ECS クラスタ自体を操作するジョブ (ECS クラスタのオートスケーリング等 ) - 特別に大きな CPU、メモリリソースを必要とするジョブ
  7. オンデマンドクラスタ - 全クラスタで共通の AMI から起動 (※GPU クラスタを除く) - オートスケールは自前 (後述)

    - AutoScaling Group の役割 - 「desired capacity を上下するだけで ECS クラスタの増減ができる」状態にする - インスタンス障害からのオートヒール
  8. AutoScaling Group でのサービスアウト - スケールアウトは簡単だが、スケールインをするには事前にサービスアウトして おく必要がある - lifecycle hook の

    Terminating:Wait の間にコンテナインスタンスを DRAINING 状態にしてサービスアウト
  9. スポットクラスタ - オンデマンド同様、共通の Ubuntu ベースの AMI から起動 - Spot Fleet

    で管理 - こちらもオートスケールは自前 (後述) - Spot Fleet の役割 - 「target capacity を上下するだけで ECS クラスタの増減ができる」状態にする - スポット価格上昇やインスタンス障害からのオートヒール
  10. Spot Fleet でのサービスアウト - Spot Fleet の target capacity を下げてスケールインするときも、スポット価格上

    昇で terminate されるときと同じように interruption notice が通知される - interruption notice を CloudWatch Events から SQS キュー経由で受け取り、 デーモンがサービスアウト処理を行う
  11. Spot Fleet でのサービスアウト - AutoScaling Group とは異なり、通知がきてから2分以内にサービスアウトしき る必要がある - バッチジョブは諦めて

    StopTask API で止める - スポットクラスタでバッチジョブを動かすときはアプリケーション側に冪等性を要求する - DRAINING 状態にして ECS に任せるだけでは間に合わない可能性がある
  12. Spot Fleet でのサービスアウト - 先に自前で ELB の target group から

    deregister する - 先に DeregisterTargets してしまえば新規のリクエストはそのタスクにはこなくなる - DeregisterTargets し終わったら StopTask で止める - ECS や ELB に邪魔されないように deregistration_delay.timeout_seconds を一定 以上にしておく - 突然一部のタスクが停止しても問題無いようにやや過剰なキャパシティを常に 確保しておく - そうしてもスポットインスタンスのほうが安い
  13. Spot Fleet でのサービスアウト (w/o ELB) 1. interruption notice Terminator 3.

    StopTask 2. UpdateContainerInstancesState (DRAINING)
  14. Spot Fleet でのサービスアウト (w/ ELB) 1. interruption notice Terminator 5.

    StopTask 2. UpdateContainerInstancesState (DRAINING) 3. DeregisterTargets 4. DescribeTargetHealth
  15. オートスケーリング

  16. オートスケーリング - オンデマンドクラスタとスポットクラスタの間で戦略に差は無い - AutoScaling Group の desired capacity を調整するか、Spot

    Fleet の target capacity を調整するかの違いだけ - 3種類のスケールアウトと1種類のスケールイン
  17. スケールアウト - クラスタの CPUReservation、MemoryReservation を見て閾値を超えてたらス ケールアウト - 各 service の

    desired_count、running_count、pending_count を チェックして足りてなさそうだったらスケールアウト - hako oneshot (バッチジョブの起動) がリソース不足で RunTask に失敗した らスケールアウト
  18. スケールアウト (1) - CloudWatch に入っている CPUReservation、MemoryReservation を定期的に チェックして、閾値を超えていたらスケールアウト - スポットクラスタの場合はオンデマンドクラスタより閾値を低くしている

  19. スケールアウト (2) - 各 service の desired_count、running_count、pending_count を定 期的にチェックして、desired_count >

    running_count + pending_count となっていたらリソースが足りずにデプロイが停滞している可 能性があるので、スケールアウトする
  20. スケールアウト (3) - hako oneshot (バッチジョブの起動) がリソース不足で RunTask に失敗した ときに

    SNS トピックに通知するので、それを SQS 経由で受け取ってスケールア ウト
  21. スケールアウト (3) AutoScaler Hako 1. RunTask (failed) 2. Publish 3.

    ModifySpotFleetRequest 3. SetDesiredCapacity
  22. スケールイン - クラスタの CPUReservation、MemoryReservation を見て閾値を下回っていた らスケールイン - スポットクラスタの場合はオンデマンドクラスタより閾値を低くしている

  23. ログ

  24. ログ - コンテナの stdout/stderr に出たログをどこにどう保存するか - 現在のクックパッドでは Docker の fluentd

    logging driver から fluentd を経由 して Amazon S3 に保存し、Amazon Athena で簡易検索できるようにしている
  25. CloudWatch Logs? - マネージドなログの保存、検索、閲覧サービス - しかしログの量が膨大すぎてピークタイムでは CloudWatch Logs にリアルタイ ムに入りきらない

    - 入っても検索したり取り出したりするのが遅い - ログを入れるときの料金 (ingestion) だけでもかなり高価に - 閲覧できるまでのラグや検索の柔軟性をやや犠牲にして、スケーラブルで安価 な S3 をログストレージとして選択
  26. ログ配送 Container instances service logs task logs S3 Event ecs-logs-router

    fluentd aggregator
  27. ログ配送 Container instances service logs task logs S3 Event ecs-logs-router

    fluentd aggregator
  28. ログ配送 - コンテナインスタンスのホスト側に fluentd を起動し、Docker の logging driver の設定でそこへ送信 -

    各コンテナインスタンスから fluentd の集約ノードへと転送する - 集約ノードには大量のログが送信されてくる - fluentd v1.0 からは複数プロセスで処理できるようになっているので、それを利用してがんばっ て処理しきる - https://docs.fluentd.org/v1.0/articles/multi-process-workers
  29. ログ配送 Container instances service logs task logs S3 Event ecs-logs-router

    fluentd aggregator
  30. ログ配送 - 集約ノードの fluentd が1分毎に s3://service-logs/${task_definition_family}/${container _name}/%Y/%m/%d/%Y%m%d%H%M_%{index}_%{flush_uuid}.gz に ログを出力する -

    タスクを横断して、service 毎 (task definition 毎) に閲覧するためのログ
  31. ログ配送 Container instances service logs task logs S3 Event ecs-logs-router

    fluentd aggregator
  32. ログ配送 - s3://service-logs に置かれたログを ecs-logs-router がタスク ID 毎に分 解して s3://task-logs/${task_definition_family}/${container_na

    me}/${task_id}/ 以下に置く - タスク単位で閲覧するためのログ
  33. ログ検索 - Amazon Athena で検索できるように、AWS Glue でカタログを日次で更新して いる - ${task_definition_family}_${container_name}

    というテーブル名 - 日付でパーティションを切っている - 例: my-awesome-app の app コンテナの今日のログから ERROR を探す - select time, log from "my_awesome_app_app" where year = 2018 and month = 11 and day = 28 and log like '%ERROR%' order by time
  34. モニタリング

  35. モニタリング - CloudWatch に service 単位のメトリクスは存在しているが、タスク単位、コンテ ナ単位でのメトリクスは存在していない - したがって RunTask

    で起動した場合はメトリクスが一切存在しない - アプリケーション開発者にとって、主に見たいのはアプリケーションコンテナだけ のメトリクス - サイドカーとして起動している fluentd や Envoy 等は要らない
  36. モニタリング - cAdvisor でメトリクスを取得し、Prometheus からそれを scrape し、Grafana で 可視化することにした -

    cAdvisor 自体に Prometheus 用のメトリクスを返すエンドポイントがあるので、 これが一番簡単そうだった - cAdvisor は ECS の daemon scheduling を使って各コンテナインスタンスに配 置した
  37. モニタリング

  38. モニタリング

  39. まとめ

  40. まとめ - ECS で様々なサービスを動かすためにやってることの一部を紹介した - オンデマンドインスタンス管理、スポットインスタンス対応 - オートスケーリング戦略 - ログ配送

    - モニタリング - 今回話さなかったトピック - ECS API の rate limit を回避するための工夫 - コンテナインスタンス側の問題を調査するためのロギング
  41. 今後 - センシティブな値を環境変数に入れる機能がついにきたので移行したい - https://aws.amazon.com/about-aws/whats-new/2018/11/aws-launches-secrets-support-f or-amazon-elastic-container-servic/ - AutoScaling Group でスポットインスタンスを管理できるようになったので移行し

    たい - https://aws.amazon.com/jp/blogs/aws/new-ec2-auto-scaling-groups-with-multiple-instan ce-types-purchase-options/