이제 스팟 요청을 취소하는 것을 잊고 안녕!
개요
개발 환경에 EC2의 스팟 인스턴스를 이용하는 것은 자주 있다고 생각합니다. 그 중에서도 '영구적 요청'을 사용하고 있다면 그냥 인스턴스만을 '종료'하고 스팟 요청을 취소하는 것을 잊지 않겠습니까? 요청 유효 기간 내에 있으면 동일한 유형의 인스턴스가 자동으로 좀비처럼 재작성되어 쓸모없는 청구가 발생합니다.
인스턴스를 삭제할 때 스팟 요청에서 취소하도록 운영 절차로 결정해도 그만 잊기 쉽기 때문에 자동화하는 방법을 소개합니다.
전제 조건 요약
구성
EventBridge를 사용하여 인스턴스 종료 이벤트 중에 지정한 Lambda를 실행하여 스팟 요청을 취소합니다.

EventBridge
이벤트로 인스턴스 상태 변경 알림에서 "Terminated"를 추가합니다.

eventbridge.json{
"detail-type": [
"EC2 Instance State-change Notification"
],
"source": [
"aws.ec2"
],
"detail": {
"state": [
"terminated"
]
}
}
람다
Lambda에 첨부된 역할에 다음 권한(인스턴스 정보 검색, 스팟 요청 취소)을 포함하면 OK입니다.
role.json{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:CancelSpotInstanceRequests",
"ec2:DescribeInstances"
],
"Resource": "*"
}
]
}
EventBridge에서 전달되는 변수는 다음과 같습니다.
동시에 여러 인스턴스를 삭제하더라도 하나씩 이벤트로 전송되므로,
Lambda 측에서는 기본적으로 단수를 상정한 구현으로 좋을 것입니다.
event.json{
"version": "0",
"id": "xxxxxxxxxxxxxxxxxxxxxx",
"detail-type": "EC2 Instance State-change Notification",
"source": "aws.ec2",
"account": "xxxxxxxxxx",
"time": "2020-10-26T09:28:11Z",
"region": "ap-northeast-1",
"resources": [
"arn:aws:ec2:ap-northeast-1:xxxxxx:instance/i-xxxxxxxxxxxx"
],
"detail": {
"instance-id": "i-xxxxxxxxxxxx",
"state": "terminated"
}
}
이벤트의 instance-id에서 인스턴스 정보를 검색하고 관련 스팟 요청을 취소합니다.
cancle_spotrequest.py
import json
import boto3
def lambda_handler(event, context):
'''
EC2インスタンス削除時に関連するスポットリクエストをキャンセルする
'''
print('--------event----------')
print(event)
print('------------------')
client = boto3.client('ec2')
event_detail = event['detail']
if event_detail['state'] != 'terminated':
return
# インスタンスIDで終了済みのスポットインスタンスを取得する
response = client.describe_instances(
Filters=[{
'Name': 'instance-state-name',
'Values': ['terminated']
},{
'Name': 'instance-lifecycle',
'Values': ['spot']
}],
InstanceIds=[event_detail['instance-id']]
)
# 対象がなければ、終了
if len(response['Reservations']) <= 0:
return
spot_request_id = ''
for reservations in response['Reservations']:
for ins in reservations['Instances']:
spot_request_id = ins['SpotInstanceRequestId']
print('--------cancel id----------')
print(spot_request_id)
print('------------------')
# スポットリクエストをキャンセル
client.cancel_spot_instance_requests(SpotInstanceRequestIds=[spot_request_id])
Reference
이 문제에 관하여(이제 스팟 요청을 취소하는 것을 잊고 안녕!), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/comefigo/items/dcdb47afc27de4a5c31f
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
이벤트로 인스턴스 상태 변경 알림에서 "Terminated"를 추가합니다.

eventbridge.json
{
"detail-type": [
"EC2 Instance State-change Notification"
],
"source": [
"aws.ec2"
],
"detail": {
"state": [
"terminated"
]
}
}
람다
Lambda에 첨부된 역할에 다음 권한(인스턴스 정보 검색, 스팟 요청 취소)을 포함하면 OK입니다.
role.json{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:CancelSpotInstanceRequests",
"ec2:DescribeInstances"
],
"Resource": "*"
}
]
}
EventBridge에서 전달되는 변수는 다음과 같습니다.
동시에 여러 인스턴스를 삭제하더라도 하나씩 이벤트로 전송되므로,
Lambda 측에서는 기본적으로 단수를 상정한 구현으로 좋을 것입니다.
event.json{
"version": "0",
"id": "xxxxxxxxxxxxxxxxxxxxxx",
"detail-type": "EC2 Instance State-change Notification",
"source": "aws.ec2",
"account": "xxxxxxxxxx",
"time": "2020-10-26T09:28:11Z",
"region": "ap-northeast-1",
"resources": [
"arn:aws:ec2:ap-northeast-1:xxxxxx:instance/i-xxxxxxxxxxxx"
],
"detail": {
"instance-id": "i-xxxxxxxxxxxx",
"state": "terminated"
}
}
이벤트의 instance-id에서 인스턴스 정보를 검색하고 관련 스팟 요청을 취소합니다.
cancle_spotrequest.py
import json
import boto3
def lambda_handler(event, context):
'''
EC2インスタンス削除時に関連するスポットリクエストをキャンセルする
'''
print('--------event----------')
print(event)
print('------------------')
client = boto3.client('ec2')
event_detail = event['detail']
if event_detail['state'] != 'terminated':
return
# インスタンスIDで終了済みのスポットインスタンスを取得する
response = client.describe_instances(
Filters=[{
'Name': 'instance-state-name',
'Values': ['terminated']
},{
'Name': 'instance-lifecycle',
'Values': ['spot']
}],
InstanceIds=[event_detail['instance-id']]
)
# 対象がなければ、終了
if len(response['Reservations']) <= 0:
return
spot_request_id = ''
for reservations in response['Reservations']:
for ins in reservations['Instances']:
spot_request_id = ins['SpotInstanceRequestId']
print('--------cancel id----------')
print(spot_request_id)
print('------------------')
# スポットリクエストをキャンセル
client.cancel_spot_instance_requests(SpotInstanceRequestIds=[spot_request_id])
Reference
이 문제에 관하여(이제 스팟 요청을 취소하는 것을 잊고 안녕!), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/comefigo/items/dcdb47afc27de4a5c31f
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:CancelSpotInstanceRequests",
"ec2:DescribeInstances"
],
"Resource": "*"
}
]
}
{
"version": "0",
"id": "xxxxxxxxxxxxxxxxxxxxxx",
"detail-type": "EC2 Instance State-change Notification",
"source": "aws.ec2",
"account": "xxxxxxxxxx",
"time": "2020-10-26T09:28:11Z",
"region": "ap-northeast-1",
"resources": [
"arn:aws:ec2:ap-northeast-1:xxxxxx:instance/i-xxxxxxxxxxxx"
],
"detail": {
"instance-id": "i-xxxxxxxxxxxx",
"state": "terminated"
}
}
import json
import boto3
def lambda_handler(event, context):
'''
EC2インスタンス削除時に関連するスポットリクエストをキャンセルする
'''
print('--------event----------')
print(event)
print('------------------')
client = boto3.client('ec2')
event_detail = event['detail']
if event_detail['state'] != 'terminated':
return
# インスタンスIDで終了済みのスポットインスタンスを取得する
response = client.describe_instances(
Filters=[{
'Name': 'instance-state-name',
'Values': ['terminated']
},{
'Name': 'instance-lifecycle',
'Values': ['spot']
}],
InstanceIds=[event_detail['instance-id']]
)
# 対象がなければ、終了
if len(response['Reservations']) <= 0:
return
spot_request_id = ''
for reservations in response['Reservations']:
for ins in reservations['Instances']:
spot_request_id = ins['SpotInstanceRequestId']
print('--------cancel id----------')
print(spot_request_id)
print('------------------')
# スポットリクエストをキャンセル
client.cancel_spot_instance_requests(SpotInstanceRequestIds=[spot_request_id])
Reference
이 문제에 관하여(이제 스팟 요청을 취소하는 것을 잊고 안녕!), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/comefigo/items/dcdb47afc27de4a5c31f텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)