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. 5.

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

    が一対一対応 - スポットインスタンスは Spot Fleet - ECS クラスタと Spot Fleet が一対一対応 - オンデマンド・スポット比: 1:4
  2. 6.

    Fargate? - 一部では Fargate も使っているが、基本は自前管理のインスタンス - スポットインスタンスを使ったほうが安い - Fargate だと起動が遅い、起動までの時間が安定しない

    - Web アプリではそこまで困らない - そこそこの頻度で起動するバッチジョブだとつらい - Fargate を使うケース - ECS クラスタ自体を操作するジョブ (ECS クラスタのオートスケーリング等 ) - 特別に大きな CPU、メモリリソースを必要とするジョブ
  3. 7.

    オンデマンドクラスタ - 全クラスタで共通の AMI から起動 (※GPU クラスタを除く) - オートスケールは自前 (後述)

    - AutoScaling Group の役割 - 「desired capacity を上下するだけで ECS クラスタの増減ができる」状態にする - インスタンス障害からのオートヒール
  4. 9.

    スポットクラスタ - オンデマンド同様、共通の Ubuntu ベースの AMI から起動 - Spot Fleet

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

    Spot Fleet でのサービスアウト - Spot Fleet の target capacity を下げてスケールインするときも、スポット価格上

    昇で terminate されるときと同じように interruption notice が通知される - interruption notice を CloudWatch Events から SQS キュー経由で受け取り、 デーモンがサービスアウト処理を行う
  6. 11.

    Spot Fleet でのサービスアウト - AutoScaling Group とは異なり、通知がきてから2分以内にサービスアウトしき る必要がある - バッチジョブは諦めて

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

    Spot Fleet でのサービスアウト - 先に自前で ELB の target group から

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

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

    StopTask 2. UpdateContainerInstancesState (DRAINING) 3. DeregisterTargets 4. DescribeTargetHealth
  10. 16.

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

    Fleet の target capacity を調整するかの違いだけ - 3種類のスケールアウトと1種類のスケールイン
  11. 17.

    スケールアウト - クラスタの CPUReservation、MemoryReservation を見て閾値を超えてたらス ケールアウト - 各 service の

    desired_count、running_count、pending_count を チェックして足りてなさそうだったらスケールアウト - hako oneshot (バッチジョブの起動) がリソース不足で RunTask に失敗した らスケールアウト
  12. 19.

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

    running_count + pending_count となっていたらリソースが足りずにデプロイが停滞している可 能性があるので、スケールアウトする
  13. 20.

    スケールアウト (3) - hako oneshot (バッチジョブの起動) がリソース不足で RunTask に失敗した ときに

    SNS トピックに通知するので、それを SQS 経由で受け取ってスケールア ウト
  14. 21.
  15. 23.
  16. 24.

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

    logging driver から fluentd を経由 して Amazon S3 に保存し、Amazon Athena で簡易検索できるようにしている
  17. 25.

    CloudWatch Logs? - マネージドなログの保存、検索、閲覧サービス - しかしログの量が膨大すぎてピークタイムでは CloudWatch Logs にリアルタイ ムに入りきらない

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

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

    各コンテナインスタンスから fluentd の集約ノードへと転送する - 集約ノードには大量のログが送信されてくる - fluentd v1.0 からは複数プロセスで処理できるようになっているので、それを利用してがんばっ て処理しきる - https://docs.fluentd.org/v1.0/articles/multi-process-workers
  19. 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
  20. 35.

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

    で起動した場合はメトリクスが一切存在しない - アプリケーション開発者にとって、主に見たいのはアプリケーションコンテナだけ のメトリクス - サイドカーとして起動している fluentd や Envoy 等は要らない
  21. 36.

    モニタリング - cAdvisor でメトリクスを取得し、Prometheus からそれを scrape し、Grafana で 可視化することにした -

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

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

    - モニタリング - 今回話さなかったトピック - ECS API の rate limit を回避するための工夫 - コンテナインスタンス側の問題を調査するためのロギング