はじめに
ECSタスクのスケールイン保護をpython(boto3)で検証したので、その時のメモを残す。
背景
とある案件であるイベントが発生すると、その後ユーザーからのリクエストが急増する可能性があるため、事前にECS FargateでAutoScalingの最大値までスケールアウトをしておくということをやりたかった(Auto Scalingのポリシー自体はターゲット追跡ポリシーを使用)。
しかし単にスケールアウトを指示したのみだと、ユーザーからのアクセスが発生し始める前にスケールインが始まってしまい、効果がなかった。
そうしたところでECSタスクのスケールイン保護が発表された。これを元にスケールアウトした後にスケールイン保護をかければ、アクセス負荷が無い時でも一定時間スケールインしないようにできるのでは??ということで検証していた。
前提
スケールイン保護のやり方
上記ブログにも記載があるがスケールイン保護には以下の2つのやり方がある。
- Amazon ECS エージェントエンドポイントの使用:主にタスクが自分自身でスケールイン保護をかけるときに使用する方法。
- Amazon ECS API の使用:主にタスク外からスケールイン保護をかけるときに使用する方法。
今回要件的にECSの外のpythonプログラムから実行したいので、後者でboto3を元に実装することにした。
boto3のAPIを確認
update_task_protection
を使用する形になる。
APIを確認すると以下のようになっている。クラスター名とタスクのarnが必要となる。
response = client.update_task_protection( cluster='string', tasks=[ 'string', ], protectionEnabled=True|False, expiresInMinutes=123 )
実装
流れ
今回スケールアウトを行い、起動したタスクに一定時間スケールイン保護をかけるということをやりたいので、以下の流れで実施する。
- スケールアウトを指示
- タスクのarnをリストとして取得
- スケールイン保護を実施
1. スケールアウトを指示
update_service
を使用して指定の数にスケールアウトを指示する。
import boto3 client = boto3.client("ecs") # クラスター名、サービス名、タスクの必要数を指定してスケールアウトを指定 response = client.update_service( cluster=cluster_name, service=service_name, desiredCount=desired_count, )
2. タスクのarnをリストとして取得
スケールイン保護のAPIにはタスクのarnのリストを渡す必要があるため、list_tasks
を使用して取得する。
ただし1の直後に実行すると、早すぎてスケールアウトで追加されるタスクのarnを取得することができない。
そのため若干いまいちだが、update_service
実行後30秒程度待機してからlist_tasks
を実行すれば問題なく取得できた(タスク数が多いともっと待機時間いるかも)
※他にいいやり方あったら教えてください。
import time # 30秒待機 time.sleep(30) # list_tasksで対象のサービスのタスクのarnを取得する response = client.list_tasks( cluster=cluster_name, serviceName=service_name, ) # responseのtaskArnsからタスクのarnのリストを取得可能 ask_arns=response["taskArns"]
3. スケールイン保護を実施
2で取得したタスクのarnのリストを使用してスケールイン保護をかける。
# スケールイン保護を実施 response = client.update_task_protection( cluster=cluster_name, tasks=task_arns, # 2で取得したタスクのarnのリスト protectionEnabled=True, # Trueの場合スケールイン保護が有効 expiresInMinutes=10 # 指定時間(分)スケールイン保護が有効になる。未指定の場合120分になる。 )
上記を元に実行してみたところ、3のexpiresInMinutes
が経過するまではスケールインが発動しないよう、保護することができた。
終わりに
以上でスケールアウトさせた後も、指定時間はスケールインが行われないようにECSタスクを保護することができた。
簡単にできたが、タスクのarnのリストじゃなくてサービス名で指定して一括でスケールイン保護かけるができるとより良いと思う。