AWS Fault Injection Simulator(以降 AWS FIS) を使うとスポットインスタンスの中断テストを実行できます。ところで AWS ParallelCluster で起動したスポットインスタンスのコンピュートノードにも AWS FIS の中断テストは対応しているのでしょうか?確認してみました。
確認結果
AWS FIS はスポットインスタンスのコンピュートノートの中断テストに利用できました。
検証背景
とある HPC 環境で計算中のコンピュートノードの中断対策を検討していました。ロジックのテストのためにコンピュートノードに対して中断イベントを発生させられるのか確認するのが目的です。
※ ロジックは検討段階です。
確認してみた
マネージメントコンソールから中断テストを実行できると検証が捗ります。下記のリンクで紹介されている実行手順を参考にはじめます。
実際に試したところ実行手順に変更はなく同じ操作でした。詰まることもなく ParallelCluster から起動したスポットインスタンスのコンピュートノードに対して中断イベントを発生させ、コンピュートノードを終了させることができました。本記事では ParallelCluster に関する部分を中心に実行過程を紹介します。
検証環境
項目 | 値 |
---|---|
AWS ParallelCluster | 3.8.0 |
OS | Ubuntu 22.04 LTS |
CPU Arch | Intel(x86_64) |
HeadNode | t3.micro |
コンピュートノードの起動
コンピュートノードを起動させて待機させるだけのスクリプトを用意しました。
#! /bin/bash
sleep 1h
ヘッドノードからテストジョブをサブミットして、スポットインスタンスのコンピュートノードを起動させます。
# キューは空です
$ squeue
JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
# テストジョブをサブミットしました
$ sbatch sleep.sh
Submitted batch job 5
# キューに入りました
$ squeue
JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
5 test1 test.sh ubuntu CF 0:02 1 test1-dy-test1-1
# コンピュートノードが起動してきて Status Run となり、Sleep が実行中です
$ squeue
JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
5 test1 sleep.sh ubuntu R 1:20 1 test1-dy-test1-1
間もなくしてコンピュートノードが起動しました。
AWS FIS から中断テストを行う下準備は完了です。
スポットインスタンスの中断イベントを実行
EC2 コンソールのスポットリクエストメニューを開きます。コンピュートノードで起動してきたインスタンス ID を確認の上、指定しアクションから「中断を開始」をクリックします。
「中断を開始する」をクリックします。
AWS FIS からの中断テスト実行完了です。
実行手順は非常に簡単ですね。中断対象のインスタンス ID を間違えないようにご注意ください。
中断テストの実行結果確認
スポットインスタンスの中断が発生するときは、インスタンスが終了する 2 分前にスポットインスタンスの中断通知がベストエフォートで行われます。中断通知の確認方法は 2 つ用意されており、 EC2 インスタンス上のメタデータを参照するか、EventBridge のイベントをフックするかです。
コンピュートノードより
コンピュートノードにログインしました。最初に AWS FIS で中断テストを実行する前のメタデータを確認します。
内容は404 Not Found
となっています。スポットインスタンスの中断通知がない状態、つまり普通に起動している状態ですと 404 エラーが返ってくるのは期待した動作です。
$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/spot/instance-action
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 56 100 56 0 0 10995 0 --:--:-- --:--:-- --:--:-- 11200
* Trying 169.254.169.254:80...
* Connected to 169.254.169.254 (169.254.169.254) port 80 (#0)
> GET /latest/meta-data/spot/instance-action HTTP/1.1
> Host: 169.254.169.254
> User-Agent: curl/7.81.0
> Accept: */*
> X-aws-ec2-metadata-token: AQAEAISSHaLkSrJp-BOykJiWo9D3gE0teOqbE3HutERhx_E0hRZOJQ==
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< X-Aws-Ec2-Metadata-Token-Ttl-Seconds: 21600
< Content-Type: text/html
< Content-Length: 339
< Date: Thu, 28 Dec 2023 08:34:38 GMT
< Server: EC2ws
< Connection: close
<
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>404 - Not Found</title>
</head>
<body>
<h1>404 - Not Found</h1>
</body>
</html>
* Closing connection 0
次に中断アクションを実行後にメタデータを確認した結果です。
{"action":"terminate","time":"2023-12-28T08:38:45Z"}
という終了予定時刻のメッセージを確認できます。
記載されている時刻は中断アクションを実行した時刻からちょうど 2 分後でした。こちらも期待した結果となりました。
$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` && curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/spot/instance-action
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 56 100 56 0 0 7801 0 --:--:-- --:--:-- --:--:-- 8000
* Trying 169.254.169.254:80...
* Connected to 169.254.169.254 (169.254.169.254) port 80 (#0)
> GET /latest/meta-data/spot/instance-action HTTP/1.1
> Host: 169.254.169.254
> User-Agent: curl/7.81.0
> Accept: */*
> X-aws-ec2-metadata-token: AQAEAISSHaJW85ZQ4az2gizQ_5wjv5LHeDa77Wj5v0yUCi84fZU4zA==
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Aws-Ec2-Metadata-Token-Ttl-Seconds: 21600
< Content-Type: text/plain
< Accept-Ranges: none
< Last-Modified: Thu, 28 Dec 2023 08:36:46 GMT
< Content-Length: 52
< Date: Thu, 28 Dec 2023 08:36:54 GMT
< Server: EC2ws
< Connection: close
<
* Closing connection 0
{"action":"terminate","time":"2023-12-28T08:38:45Z"}
単にスポットインスタンスを 2 分後に終了処理をかけるのではなく、スポットインスタンスの中断通知を確認できることに AWS FIS を使う意味があります。
EventBridge より
スポットインスタンスの中断通知イベントをキャッチする EventBridge のルールを作成しました。イベントパターンの設定は下記になります。
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Spot Instance Interruption Warning"]
}
イベント内容は SNS を利用しメールで送信してみました。メール本文中の JSON が読みづらいため整形した内容は下記になります。
{
"version": "0",
"id": "6b29e4a0-6de0-eb34-9009-0510aa73371f",
"detail-type": "EC2 Spot Instance Interruption Warning",
"source": "aws.ec2",
"account": "123456789012",
"time": "2023-12-28T09:47:50Z",
"region": "ap-northeast-1",
"resources": [
"arn:aws:ec2:ap-northeast-1c:instance/i-0a1755f717b68dc70"
],
"detail": {
"instance-id": "i-0a1755f717b68dc70",
"instance-action": "terminate"
}
}
EventBridge からも AWS FIS で発生させたスポットインスタンスの中断通知を確認できました。ちなみに実際に AWS FIS で中断アクション実行後に届いたメールが以下になります。
コンピュートノードはどうなったのか?
中断アクション実行から 2 分後にはスポットインスタンスのリクエストはclosed
となりました。
リクエストがなくなり、コンピュートノードは終了しました。
ヘッドノードからジョブキューを確認すると、キューは空になっていました。コンピュートノードで計算中にスポットインスタンスが落ちても、キューには残らないため再実行はされません。
# キューは空になりました。
$ squeue
JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
まとめ
- AWS FIS からの中断テストはスポットインスタンスで起動したコンピュートノードに対しても使える
- スポットインスタンスの中断通知は通常のスポットインスタンスと同じく利用できる
おわりに
AWS FIS から中断テストが ParallelCluster のコンピュートノードでも問題なく利用できました。ParallelCluster でも手軽にスポットインスタンスの中断通知テストできることが確認できました。計算途中でインスタンスストアに書きだしている中間ファイルをスポットインスタンスの中間通知があったときに、S3 へ退避するロジックがうまくいったら改めてブログで共有します。