今日は会社で管理しているOSSの一つ、ecs_deployに関連する話をECSの復習がてらします。
TL;DR
ecs_deploygemでは、ECSへのデプロイに関するCapistranoタスクの定義とECSのオートスケーリングを行うスクリプトが入っている- ECSのオートスケーリングはAutoScaling Groupのdesiredの設定でクラスタ内のコンテナインスタンスの数を、ECSのサービスのdesired countの設定でタスクの数を調整する
reproio/ecs_deploy のgemについて
ecs_deploy の gem は、各言語で作成されているECSへのデプロイを助けるスクリプト群*1の一つで、特徴としてはECSのデプロイをCapistranoのタスクとして記述させるアプローチを取っていることだと思います。
ecs_deploy のgemの中身はおおまかにいって
- ECSへのデプロイに関するCapistranoタスクの定義
- 上記Capistranoのタスクの中で利用されるRubyのコード
があって、今回自分が仕事で触ったのは ecs_auto_scalerr の方なので、 ecs_auto_scaler についてもう少し説明していきます。
また、ややこしいので、この記事ではAWSが提供しているECSのService AutoScalingを「AWSによるECSのオートスケーリング」、ecs_deployに含まれるecs_auto_saclerによるオートスケーリングは 「ecs_auto_scaler のオートスケーリング」と記載することにします。
ECSのオートスケーリングのために、ECS ServiceとAutoScaling Groupの設定をいじる必要がある
ecs_auto_scaler はひらたくいうと、ECSのAutoScalingを行うスクリプトです。
このスクリプトが書かれたのは2016年1月には、まだAWSによるECSのオートスケーリングがありませんでした*2が、この二種類のオートスケーリングが行なっていることをおおまかにまとめると
ということをやっています。
Amazon Web Services ブログ > Amazon ECSでAuto Scalingによると、AWSによるECSのオートスケーリングの場合、
- ECSのサービスのタスク数の調整には、ECS ServiceのScaling Policy
- ECSのクラスターのコンテナ数の調整には、コンテナインスタンスが属するAutoScaling GroupのScaling Policy
を用いています。一方、ecs_auto_scaler のオートスケーリングは
しています。
何が言いたいかというと、2つのオートスケーリングで利用している設定やAPIに多少違いはありますが、ECSのオートスケーリングは、ECSのサービスとクラスターのAutoScaling Groupの2つのレイヤーの設定を管理して行う必要があるわけです。
AWSによるECSのオートスケーリングとecs_auto_scaler のオートスケーリングの違い
それでは、この2つのオートスケーリングの方法の違いで一体どういう事態が生じるのでしょうか。
じつは、AWSによるECSのオートスケーリングでは、ECS ServiceのScaling PolicyとAutoScaling GroupのScaling Policyがそれぞれ独立して動いていて、AutoScaling GroupのScaling Policyによりまだタスクが動作しているコンテナインスタンスが停止となりエラーが発生することがあります。
この問題に対応するため、 ecs_auto_scaler ではスケールイン時はECSインスタンス上のタスクの状態をしらべ必要なタスクが動いていないことを確認してから、AutoScaling Groupの設定の調整を行うようになっています*5。
AWSによるECSのオートスケーリングを使っている場合でもこの問題の対応は可能ですが*6、ecs_auto_scalerを利用するメリットとしては、ecs_deployの EcsDeploy::EcsAutoScaler を利用する場合、ECSインスタンス上のプロセスのチェックを含めたオートスケーリングの処理を 管理対象クラスタの外部のホストで行う*7ため、監視される側のインスタンスには特別な設定をしなくていい点でしょうか。
そのかわり、オートスケーリングのためにネットワークを経由してAWSのAPIを叩くので、AWSのAPIの回数制限*8を超えるような規模のクラスタ、たとえば200台くらいのコンテナインスタンスが存在するような大規模なクラスタの管理は難しそうです*9。
書ける、と思ってたら割とかけなくて焦りました。。現場からは以上です。
*1:たとえば、pythonだと https://github.com/fabfuel/ecs-deploy , シェルスクリプト: https://github.com/silinternational/ecs-deploy/blob/develop/ecs-deploy, JSだと https://www.npmjs.com/package/ecs-deploy など
*2:https://aws.amazon.com/jp/blogs/news/automatic-scaling-with-amazon-ecs/ AWSによるECSのオートスケーリングがアナウンスされたのは2016年5月
*3:正確には少し違っていて、後発のターゲット追跡スケーリングポリシーはCloudWatchのアラートではなく、CloudWatchの特定のメトリクスを見て、その値が一定値に近づくようにする https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/service-autoscaling-targettracking.html
*4:MinやMaxなども増減させていますが、詳しくは https://dev.classmethod.jp/cloud/aws/comprehend-auto-scaling-desired-capacity/
*5:詳しくは https://github.com/reproio/ecs_deploy/blob/master/lib/ecs_deploy/auto_scaler.rb#L350-L356 あたり
*6:https://developers.cyberagent.co.jp/blog/archives/14664/
*7:ことが前提になっている、おそらく。
*8:ECSのAPIは1時間に1000回くらい叩くとエラーを返してくるようになるとかなんとか...
*9:なんとなく、200台超えてきたらインスタンスタイプ変えることの方を先に検討しそうな気もするけどAWS詳しくない...