Lambda 関数を利用してスポットプレイスメントスコア結果を SNS で通知してみた
はじめに
テクニカルサポートの 片方 です。
Lambda 関数を利用して、スポットプレイスメントスコア 結果を SNS より通知する仕組みを作成してみました。
スポットプレイスメントスコアの仕組み
スポットプレイスメントスコア機能を使用する場合は、まずスポットインスタンスのコンピューティング要件を指定します。その後、Amazon EC2 は、スポットリクエストが成功する可能性が高い上位 10 リージョン、を返します。各リージョンまたはアベイラビリティーゾーンは、1~10 のスケールで採点されます。10 はスポットリクエストが成功する可能性が高いことを示し、1 はスポットリクエストが成功する可能性が低いことを示します。
実装してみた
インスタンスタイプとリージョンを指定して、スポットプレイスメントスコアを取得します。
SNS を利用しますが、SNS トピックとサブスクリプション設定については省かせていただきます。
なお、SNS トピックの arn は後ほど必要となるのでメモしてください。
ロール
ロールを作成します。Lambada 関数で使用するためのロールです。
※ 信頼関係
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
アタッチするポリシー例
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": "ec2:GetSpotPlacementScores",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "sns:Publish",
"Resource": "arn:aws:sns:ap-northeast-1:123456789012:aaaaa-xxxxx"
}
]
}
※ 適宜修正してください。
"sns:Publish" の "Resource" では利用する SNS の arn を記述してください。
Lambda 関数
Python 3.12 で作成しました。
実行ロールでは、既存のロールを使用するを選択し、先ほど作成したロールを指定します。
実装する Lambda 関数例
import boto3
import json
import os
def lambda_handler(event, context):
# EC2クライアントとSNSクライアントを作成
ec2_client = boto3.client('ec2')
sns_client = boto3.client('sns')
# SNSトピックARN、インスタンスタイプ、リージョン名を環境変数から取得
sns_topic_arn = os.environ['SNS_TOPIC_ARN']
instance_type = os.environ['INSTANCE_TYPE']
region_names = os.environ['REGION_NAMES'].split(',') # カンマで区切られたリージョン名をリストに変換
# ターゲット容量とターゲット容量の単位を設定
target_capacity = 5
target_capacity_unit_type = 'vcpu'
try:
# スポットプレイスメントスコアを取得
response = ec2_client.get_spot_placement_scores(
InstanceTypes=[instance_type],
TargetCapacity=target_capacity,
TargetCapacityUnitType=target_capacity_unit_type,
MaxResults=10,
RegionNames=region_names,
SingleAvailabilityZone=True # アベイラビリティゾーンごとのスコアを取得
)
# 結果を取得
spot_scores = response.get('SpotPlacementScores', [])
results = []
for score in spot_scores:
results.append({
'AvailabilityZoneId': score.get('AvailabilityZoneId', 'No AvailabilityZoneId available'),
'Score': score.get('Score', 'No Score available')
})
# SNS通知のサブジェクトを環境変数に基づいて設定
subject = f'Spot Placement Scores for {instance_type}'
# 結果をSNSトピックに通知
message = json.dumps(results, indent=2)
sns_client.publish(
TopicArn=sns_topic_arn,
Subject=subject,
Message=message
)
# 結果をログに出力
print(message)
return {
'statusCode': 200,
'body': message
}
except Exception as e:
print(f"Error: {str(e)}")
return {
'statusCode': 500,
'body': json.dumps(f"Internal server error: {str(e)}")
}
環境変数設定
- SNS_TOPIC_ARN: SNSトピックのARNを設定します。
- INSTANCE_TYPE: 例えば r7gd.metal のように、対象のインスタンスタイプを設定します。
- REGION_NAMES: 例としてap-northeast-1、複数のリージョンを指定する場合は ap-northeast-1,us-west-2 のようにカンマ区切りで設定します。
これで、実装は完了です。お疲れさまでした!
検証してみた
Lambda 関数テストを利用して検証してみました。
暫くすると通知されました。
※ 一部マスクします
Spot Placement Scores for t1.micro
[
{
"AvailabilityZoneId": "apne1-az1",
"Score": 3
},
{
"AvailabilityZoneId": "usw2-az2",
"Score": 3
},
{
"AvailabilityZoneId": "usw2-az3",
"Score": 3
},
{
"AvailabilityZoneId": "usw2-az1",
"Score": 3
},
{
"AvailabilityZoneId": "apne1-az4",
"Score": 3
}
]
--
If you wish to stop receiving notifications from this topic, please click or visit the link below to unsubscribe:
https://sns.ap-northeast-1.amazonaws.com/unsubscribe.html?SubscriptionArn=arn:aws:sns:ap-northeast-1:123456789012:aaaaa-xxxxx:7ede8eb1-aaaa-1111-bbbb-1234de098765&[email protected]
Please do not reply directly to this email. If you have any questions or comments regarding this email, please contact us at https://aws.amazon.com/support
東京リージョンで申し上げると、t1.micro は 2 つの AZ のみ利用可能なため、少なく表示されています。
以下は、c5.24xlarge で確認した際の結果です。
成功です!
まとめ
Amazon EventBridge と合わせて利用することで、定期実行を行うことも可能なのでご検討ください。
本ブログが誰かの参考になれば幸いです。
参考資料
- スポットプレイスメントスコア - Amazon Elastic Compute Cloud
- get_spot_placement_scores - Boto3 1.35.10 documentation
アノテーション株式会社について
アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。