EC2のスポットフリートについて軽く調べて触ってみる

今さらながら前回以下の記事でEC2のスポットインスタンスの起動などに関して軽く触ってみたのですが、本記事ではスポットフリート機能関係に関して軽く調べたり手動で触ったりして備忘録として雑に記事にまとめておこうと思います。

前回の記事 :

https://qiita.com/simonritchie/items/46ff05d076878852fb50

:::note warn
インフラ・クラウド回りは初心者なので知識が荒い点などはご容赦ください。
:::
:::note info
Auto ScalingやCloudFormationを絡めたものなどは本記事では扱わずに機会があれば別の記事で試そうと思います。本記事ではマネジメントコンソール上での操作のみ扱うためEC2フリートも扱いません。
:::


# スポットフリートとは

※スポットフリートに似た機能としてEC2フリートと呼ばれる機能があるようです。ただしほとんどのスポットフリートの機能はEC2フリート側にある？ようなのと今後の機能追加はEC2フリート側にされていくといった旨が公式ドキュメントに書かれていたので、とりあえずCloudFormationなどで管理するならEC2フリート側を優先していればOKそう？ではあります。

> スポットフリートを使用することも可能ですが、推奨されていません。計画的な投資がないレガシー API だからです。ただし、既にスポットフリートを使用している場合は、引き続き使用できます。スポットフリートと EC2 フリートは同じコア機能を提供します。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/Fleets.html

ただ、マネジメントコンソール上ではスポットフリートの画面しかなさそうな模様で、EC2フリートを利用するには本記事執筆時点ではCLIやCloudFormationなどを利用する必要がありそうです（初見の際にマネジメントコンソール上でEC2フリートを探しましたがなかったのでドキュメントを読んでいたらCloudFormationなどが必要との旨が・・・）。

> EC2 フリートは、Amazon EC2 API、AWS CLI、AWS SDK、およびAWS CloudFormation のみで利用可能です。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-fleet.html

スポットフリートとEC2フリートですが、軽く調べた感じではスポットインスタンス用の機能で以下のような特徴を持っているようです。EC2フリートの方が細かく設定できたりと機能が多くなっています（以下に列挙したものはEC2フリート側にのみある機能も存在します）。

- 複数のAZ・複数のインスタンスタイプなどの中でコスパが良いものを自動選択できる
- 複数のインスタンスタイプなどを使用候補にできる
- インスタンス数やvCPU数、メモリ量などを基準にスポットインスタンスを必要台数の確保と維持をすることができる
- EC2フリート側はおそらくvCPUなど以外のCloudWatchのメトリクスによる判定などもできる
    - ※おそらくGPU数などで判断したい場合にはスポットフリート側だとカバーできず、EC2フリート側が必要になる？
- オンデマンドとスポットインスタンスを混ぜたりすることができる（一部だけオンデマンドで台数を確保するなど）

スポットインスタンス自体がぐっとコスト削減面で有力なのに加えて、手動では最適なAZやインスタンスタイプの選択が手間で大変な点が解消でき一層コスト効率の良いスポットインスタンス運用ができるようにするための機能・・・といったところでしょうか。

# 手動で設定してみる

CloudFormation対応などは別の記事で試すとして、ひとまずマネジメントコンソール上で、手動でスポットフリートを触ってみます。

マネジメントコンソールからEC2のページに遷移してみたもののFleetという文字が無くどこから設定するのだろう・・・と初見の時に思ったのですが、どうやらSpot Requestsのメニューを選択してRequest Spot Instancesのボタンをクリックすればスポットフリート設定用のページになるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/0750ff1d-04fd-3583-b58b-0596c0477393.png)

遷移先のページではFleetという単語がタイトルなどに設定されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/00b8ddb1-30c5-6357-eb03-ef611178b16e.png)

色々と設定を進めていきます。とりあえず今回は一時的に起動することの確認だけを目的とするため、各種ネットワーク設定など含めスキップできる点はスキップしていきます。

AMIは今回はUbuntu 24.04のものを選択しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/e7503198-810b-613a-6e28-8637eadcddea.png)

フリート用のIAMはデフォルトのものを反映する設定があるようなのでそちらを選択します。若干時限付きな印象があるのが気になるところではあります・・・（IAM？リクエストの有効期限？）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/3d590826-d234-d1c6-5c4f-e7c1260632e7.png)

Target capacityの設定で必要なインスタンス数・もしくはvCPU数やメモリ量が指定できるようです。

基本的にはコスト面を考えると様々なインスタンスタイプが選択できる方が好ましく、xlarge・2xlarge・4xlargeを混ぜて使う・・・といったようなケースであればインスタンス数よりもvCPUなどの方が好ましい・・・といったところでしょうか（単純に似たようなスペックのインスタンスタイプであればインスタンス数などでも良さそうではあります）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/e92872ca-cb98-f0c5-47a9-d0f1a99a12bb.png)

今回は適当にインスタンス数で3とかを設定しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/5c4aadca-0afc-49a8-e72d-5db8117412f8.png)

Interruption behaviorに関しては通常のスポットインスタンス作成時と同じような感じでTerminate（終了して破棄）・Stop・Hibernate（Windowsのスリープと似たような形でメインメモリをディスクに保存して停止）の選択肢があるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/e96e8b52-7b24-85ca-3006-e8b39a677874.png)

Instance replacement strategyはLaunch onlyとLaunch before terminateの2つの選択肢があるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/9929cf69-831f-8873-f93b-9ac729a82e86.png)

この辺はキャパシティのリバランス関係の設定かと思われます。以下の記事を読む感じではスポットインスタンスの中断のリスクが上がった際に別のスポットインスタンスに差し替えたりしつつもインスタンスの終了処理を行うかどうかといった設定かなと感じています。

https://aws.amazon.com/jp/about-aws/whats-new/2021/11/amazon-ec2-fleet-spot-fleet-capacity-rebalancing/

Launch onlyを選択した場合にはリバランス時にスポットインスタンスの新規起動のみが実行され、不要になった分のスポットインスタンスは次回の中断時に破棄（もしくは停止）されます。中断リスクが高まってきているタイミングだと思いますので基本的には放っておけば中断されて自動的に想定台数（もしくはスペック）分になると思いますが、中断されるまでは余分にインスタンスが起動したままとなるためコスト的には無駄が発生するといえば発生することになります。

一方でLaunch before terminateの方はスポットインスタンスの終了前に新規起動が走る形となり、無駄に台数が増えるといったことを減らすことができます。

Launch before terminateの方を選択した場合には終了までの猶予秒数を指定するためのフォームが出てきます。サーバー起動や準備などに必要な状況に応じて調整することができそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/0ba67620-9013-246c-0231-8b968700f5fe.png)

Set maximum cost for Spot Instancesの設定にチェックを入れると1時間辺りのスポットインスタンスの最大コストを設定できます。1時間単位のドル単位で設定する形になっているようです。想定よりも確保できるスポットインスタンスの料金が一時的に上がっていて予算をオーバーしてしまう・・・といったことを避けるために必要に応じて設定が出来そうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/451f660b-929e-119d-8605-dfcab728e425.png)

ネットワーク設定ではVPCやアベイラビリティゾーンの指定を行うことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/d4c99706-48b2-3702-b546-7e44aeace166.png)

アベイラビリティゾーンの方ではNo preference（利用可能な全てのアベイラビリティゾーンを利用）もしくはSelect specific zone/subnetの二つが選択できるようです。後者を選択した場合は任意のアベイラビリティゾーンを選択することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/894e802d-d2e4-f19f-3f9b-7805794919cb.png)

ただしスポットインスタンスの性質上対象の選択肢が多い方が安いスポットインスタンスを選択しやすくなるので何か理由がなければ全てのアベイラビリティゾーンを選択する形で問題ないとは思います。

続いてInstance tyope requirementsの部分ではインスタンス選択条件となります。vCPUやメモリ量などで判定して選択してもらう形（Specify instance attributes that match your compute requirements）もしくはインスタンスタイプのリストを指定する形（Manually select instance types）を選択できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/d89cd77f-1ef8-6a54-fdae-657a20ef08ec.png)

ここはケースによって様々かもですが、個人的にはインスタンスタイプのリストを指定する形の方がしっくり来そうとは感じました。

Manually select instance typesの方を選択するとインスタンスタイプの一覧と追加などを行うためのUIが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/305b36cc-b8f6-8d7b-0c72-302c57de31a0.png)

インスタンスタイプの下の方には選択されたインスタンスタイプ数 × アベイラビリティゾーン数の数が十分かどうかが表示されます。インスタンスタイプによっては一時的に確保が難しくなるケースがあるため、この数字が十分確保できているかどうかの判定として表示されていると思われます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/be05d106-6693-5e12-ca08-bb3ef71a81a1.png)

※この辺りはスポットプール数などと調べると色々見つかると思います。大体20くらいは少なくともスポットプール数があると良いのではという印象でいます。

例 :

> AWS ではスポットプール数について最低 20、可能なら 30 を⽬指すことをお勧めしてます。

https://dev.classmethod.jp/articles/tsnote-ec2-auto-scaling-spot-instances/

Allocation strategyはスポットインスタンスの割り当て方針となります。
Price capacity optimizedは価格面を優先した選択肢となります。基本的にはこちらが推奨されているようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/6f3b35ac-ab68-ef06-34e2-0e0e4f3f8ed2.png)

その他の選択肢としては説明文などを読む限りではCapacity optimizedは中断のリスクの少なさを優先する方式、Diversified across all poolsは特定のインスタンスタイプに偏って一気に大量に中断されることを防ぐために万遍なく分散させるオプションかと思われます。

今回は雑に各設定を行いましたが、最後に諸々を加味した設定のまとめが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/7668cd8e-9d08-7549-207b-ebe2c1cea5eb.png)

JSON configを押すと設定を格納したJSONファイルをダウンロードできるようです。

Launchを押して起動してみます。

なんだかエラーとなったようです・・・。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/2c482edb-9b97-b465-e4c6-7dc286e36398.png)

少し調べていたのですがなんだかデフォルトで設定されるIAMロールだと弾かれたりする＆別途IAMロールのリソースを作成しないとうまくいかなそう・・・という気配があります。そんなことある？という感じですが何記事がそういった記述がされている記事があるのでしょうがないのかもしれません・・・（そもそもEC2フリートの方がメインでスポットフリートの方がもうあまり更新されていないとかがあるのかもしれません）。

> しかし、2022年4月現在のマネジメントコンソールからだとそのままの内容で対応できませんでした。
> ...
> マネジメントコンソールからの操作は諦めて、AWS CLI で必要な IAMロールを作成することにしました。

https://dev.classmethod.jp/articles/spotfleetrequestconfig-iamfleetrole-is-invalid-error/

以下の投稿にデフォルトのIAMではなくAWSServiceRoleForEC2SpotFleetなら行けたよ、という記述があったので試してみます。

https://stackoverflow.com/a/63129950

Apply defaultsを外すとIAMのロール選択ができるようになるのでAWSServiceRoleForEC2SpotFleetを選択してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/328f077d-a36e-d750-5192-3cf7b7af8f5d.png)

余談ですがApply defaultsの選択を外すとロードバランサー関係の選択用のUIも出てくる模様です。今回は試しで使っているAWSアカウントではロードバランサー周りは作成していないので割愛します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/1b949a7d-898b-664f-9d9a-072e2f4fed7b.png)

再度Launchボタンをクリックしたら今度は正常に通った模様です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/d11c5856-f882-582d-7d87-8bdbadc91014.png)

少し待って画面を更新したらスポットフリートで指定した分の複数のスポットリクエストが実行されていることが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/3892f80a-a18e-bd63-e20f-857ab3237a01.png)

少々雑に設定しすぎて想定していたよりも大きなインスタンスが起動されているので、最後にコスト的に忘れずにこの辺を削除して終わりとします（機会があればEC2フリートをCloudFormationなどで触ってみてまた記事にまとめようとおもいまｓ）。

# 参考文献・参考サイト

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/spot-fleet.html

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/Fleets.html

https://qiita.com/kikuziro/items/c716e1e414e275ec06aa

https://logmi.jp/tech/articles/321685

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-fleet.html

https://qiita.com/docdocdoc/items/6300c29e28f45a87d5ff

https://aws.amazon.com/jp/about-aws/whats-new/2021/11/amazon-ec2-fleet-spot-fleet-capacity-rebalancing/

https://qiita.com/nishimura-toru/items/fc226da30f6dbb845077

https://dev.classmethod.jp/articles/tsnote-ec2-auto-scaling-spot-instances/

https://stackoverflow.com/a/63129950

https://dev.classmethod.jp/articles/spotfleetrequestconfig-iamfleetrole-is-invalid-error/