📌
CircleCIでデプロイ時にAWSのECSタスクの稼働数を変更した
弊社ではCircleCIを利用してAWS上に構築したECS(Fargate)にアプリケーションをデプロイしています。
また、アプリケーションのレスポンスはCloudFrontでキャッシュしている為、デプロイ時のジョブでCloudFrontのキャッシュを削除する様にしています。
invalidate-cloudfront-cache
- run:
name: CloudFrontキャッシュを削除
command: aws cloudfront create-invalidation --distribution-id << parameters.cloudfront-id >> --paths "/*"
その際に問題となったのがECSタスクの稼働数です。リクエストの大部分がCloudFrontでキャッシュされるようになっており、オリジン(ECS)までリクエストが転送されることがないので、普段ECSのタスク数は最低稼働台数としている2台の状態ですが、アプリケーションをデプロイした際に、キャッシュをクリアすることで、一時的にオリジンへの負荷が高まり、オートスケーリングで稼働台数が増加していました。
この状態ですと、デプロイする度に一時的に負荷が高まるので、スケーリングされるまではユーザーのレスポンスが遅くなってしまう事が課題となっていました。
この問題を解決する為に考えた方法が、CloudFrontのキャッシュを削除するジョブの前後で、ECSの最低稼働台数を調節する事です。
CircleCIのデプロイフロー
具体的な処理は以下になります。
api-ecs-task-scale-out-production
#!/bin/bash
set -xeuo pipefail
set -u
###########################################################
# バックエンドのECSタスク数をスケールアウトします.
###########################################################
case $ENV in
"stg")
ecs_task_min_capacity_count=4
ecs_task_max_capacity_count=10
ecs_cluster_name="stg-hogehoge-ecs-cluster"
ecs_service_name="stg-hogehoge-ecs-service"
;;
"prd")
ecs_task_min_capacity_count=4
ecs_task_max_capacity_count=20
ecs_cluster_name="prd-hogehoge-ecs-cluster"
ecs_service_name="prd-hogehoge-ecs-service"
;;
esac
# タスクの最低稼働数を更新
echo "Start updating tasks."
aws application-autoscaling register-scalable-target \
--service-namespace ecs \
--resource-id service/$ecs_cluster_name/$ecs_service_name \
--scalable-dimension ecs:service:DesiredCount \
--min-capacity $ecs_task_min_capacity_count \
--max-capacity $ecs_task_max_capacity_count
# 指定したタスク数の稼働が確認出来るまで待機する
while [ "$(aws ecs describe-services \
--cluster $ecs_cluster_name \
--services $ecs_service_name \
| jq '.services[].runningCount')" -lt $(($ecs_task_min_capacity_count)) ]
do
echo "Updating. Please wait a moment."
sleep 10s
done
echo "Complete task update."
api-ecs-task-scale-in-production
#!/bin/bash
set -xeuo pipefail
set -u
###########################################################
# バックエンドのECSタスク数をスケールインします.
###########################################################
case $ENV in
"stg")
ecs_task_min_capacity_count=2
ecs_task_max_capacity_count=10
ecs_cluster_name="stg-hogehoge-ecs-cluster"
ecs_service_name="stg-hogehoge-ecs-service"
;;
"prd")
ecs_task_min_capacity_count=2
ecs_task_max_capacity_count=20
ecs_cluster_name="prd-hogehoge-ecs-cluster"
ecs_service_name="prd-hogehoge-ecs-service"
;;
esac
# タスクの最低稼働数を更新
echo "Start updating tasks."
aws application-autoscaling register-scalable-target \
--service-namespace ecs \
--resource-id service/$ecs_cluster_name/$ecs_service_name \
--scalable-dimension ecs:service:DesiredCount \
--min-capacity $ecs_task_min_capacity_count \
--max-capacity $ecs_task_max_capacity_count
echo "Complete task update."
こうすることで、キャッシュが削除されたタイミングでは、キャッシュがなくても耐えられる台数が稼働しており、必要がなくなったら元の最低稼働台数まで勝手に戻るので、コスト面でも無駄なく対応が出来ました。
もっと良い方法がありましたらご指摘お願いいたします。
Discussion