FargateSpotを使って利用料を70%削減した時のノウハウ
備考
この記事は Qiita にて投稿した記事を少し記載を加えたものです.
はじめに
今回業務にて利用している AWS のサービスの 1 つ「Fargate」を利用した際の課題とその解決策について記します.
そもそも Fargate とは
公式ドキュメント:
https://aws.amazon.com/jp/fargate/
コンテナ向けサーバーレスコンピューティングの一種であり,Docker のイメージファイルを作るだけで簡単にデプロイできる便利なサービスです.
今回の課題
料金
料金表
vcpu | メモリ(GB) | 料金(円/月) |
---|---|---|
0.25 | 0.5 | 1,521 円 |
0.5 | 1.0 | 3,042 円 |
1.0 | 2.0 | 6,084 円 |
2.0 | 4.0 | 12,168 円 |
(2023 年 2 月 28 日現在で月に 732 時間動作させた場合)
(データ転送料+為替レートにより前後します)
現在の業務ではかなりの数 Fargate を同時稼動にて動かしているので通常のFargateを動かすと高コストになってしまいます.このコストそのものが課題になりました.
課題解決策
FargateSpot
AWS Fargate Spot の発表 – Fargate とスポットインスタンスの統合
AWS Fargate キャパシティープロバイダー
簡単に説明すると,価格が 70%割引になる Fargate です.
実際に利用してみる
まず Fargate を利用するクラスターを作り,作成したクラスターを選択します.
右上にクラスターの更新というボタンがあるので押します.
クラスターの更新を押すとキャパシティープロパイダー戦略という項目があるので追加し,FARGATE_SPOTを選択します.
そして実行したいタスクをクラスター内にて利用することでFargateSpotを利用することが出来ます.
弱点
FargateSpot は連続稼働を保証しておらず,ある日突然タスクが終了するリスクを抱えています.
Fargate Spot が空きキャパシティを確保できるかぎり、ユーザーは指定したタスクを起動することができます。
弱点をカバーする方法
タスク終了前に 終了を通知する signal が送られるのでタスク内で正常に終了させる処理、もしくは再起動させる処理を行う必要があります.
スポットの中断により Fargate Spot キャパシティーを使用するタスクが停止すると、
タスクが停止する前に 2 分間の警告が送信されます。
警告は、タスク状態変更イベントとして Amazon EventBridge に送信され、
実行中のタスクに SIGTERM シグナルが送信されます。
実際にタスク終了を検知するソースコードの例を下記に記載します.
ソースコード例
Python
import signal
import sys
import time
import random
import pprint
# 何かしらの処理を行い最終的に出力する変数
# 配列・辞書等...
response_data = []
def signal_receive_process(sig, frame):
"""SIGTERMシグナルを受け取った際に行う処理を書く"""
print("SIGTERM!!")
# 正常終了時の処理を行う
task_finish_process()
# タスクを終わらせる
sys.exit(0)
def task_finish_process():
"""タスクが終了する際に行う処理を書く"""
# 今回は単に表示させるだけ
pprint.pprint(response_data[0:20])
def main():
"""何かしらの処理(web・machine_running etc...)を書く"""
# SIGTERMを検知する
signal.signal(signal.SIGTERM, signal_receive_process)
for idx in range(100):
print(idx)
# 何かしらの処理を行う
append_data = idx * random.random()
# データを格納する
response_data.append(append_data)
time.sleep(1)
# 正常終了時の処理を行う
task_finish_process()
if __name__ == '__main__':
main()
TypeScript
const response_data: Array<number> = [];
const task_finish_process = () => {
// 今回は単純に表示させるだけ
console.log(response_data);
};
const main = () => {
/* 何かしらの処理をかく */
process.on("SIGTERM", () => {
console.log("SIGTERM!!");
// 正常処理時の動作を行う
task_finish_process();
process.exit(0);
});
for (let idx = 0; idx < 100; idx++) {
console.log(idx);
// 何かしらの処理を行う
const append_data = idx * Math.random();
// データを格納する
response_data.push(append_data);
}
// 正常終了時の処理を行う
task_finish_process();
};
main();
まとめ
突然発生する終了処理をきちんと考える必要はありますが,FargateSpotを使えば通常のFargateを利用するより料金を70%削減することができます.
Discussion