FargateSpotを使って利用料を3割にしたときのノウハウ


はじめに

こんにちは,ある企業の長期インターンシップに参加している大学4年生です.
今回インターンにて利用しているAWSのサービスの1つ「Fargate」について,安く運用したいと思ったこととその方法について書きたいと思います.

そもそもFargateとは

公式ドキュメント:
https://aws.amazon.com/jp/fargate/

コンテナ向けサーバーレスコンピューティングの一種であり,Dockerのイメージファイルを作るだけで簡単にデプロイできる便利なサービスです.

今回の課題

料金

ざっくり料金表(データ転送料+為替レートにより前後します)

vcpu メモリ(GB) 料金(円/月)
0.25 0.5 1,236円
0.5 1.0 2,473円
1.0 2.0 4,947円
2.0 4.0 9,894円

(2021年6月12日現在の為替レートで月に732時間動作させた際の表です)

現在のインターン業務ではこのタスクをかなりの数同時稼動等をしているのでまともに動かすと,
100,000円 ~ /月を余裕に超えてしまうためこのコストそのものが課題になっています.

課題解決策

FargateSpot

AWS Fargate Spotの発表 – Fargateとスポットインスタンスの統合
AWS Fargate キャパシティープロバイダー

大雑把に説明すると,価格が7割引になるFargateです.

実際に利用してみる

まずFargateを利用するクラスターを作り,作成したクラスターを選択します.
右上にクラスターの更新というボタンがあるので押します.

クラスターの更新を押すとキャパシティープロパイダー戦略という項目があるので追加し,FARGATE_SPOTを選択します.

そして実行したいタスクをクラスター内にて利用することでFargateSpotを利用することが出来ます.

唯一の弱点

FargateSpotは連続稼働を保証しておらず,ある日突然タスクが終了することがあります...
(今まで一度も終了したこと見たことないけど)

Fargate Spotが空きキャパシティを確保できるかぎり、ユーザーは指定したタスクを起動することができます。

弱点をカバーする方法

タスク終了前にsignalが送られるのでタスク内で再起動処理を行う!

スポットの中断により Fargate Spot キャパシティーを使用するタスクが停止すると、
タスクが停止する前に 2 分間の警告が送信されます。
警告は、タスク状態変更イベントとして Amazon EventBridge に送信され、
実行中のタスクに SIGTERM シグナルが送信されます。

実際にタスク終了を検知するソースコードを下記に記載します.

ソースコード

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)
        idx += 1

        time.sleep(1)

    # 正常終了時の処理を行う
    task_finish_process()


if __name__ == '__main__':
    main()

終わりに

今回,Fargateを安く利用する方法について主に書くことができました!
今後も様々なことに書いていきたいと思います!