BLOG

Amazon EC2 스팟 인스턴스 중단 알림 활용하기
작성일: 2018-03-26

Amazon EC2 Spot Instances는 온디맨드 가격에 비해 저렴한 가격으로 제공되는 AWS 클라우드의 여분의 컴퓨팅 용량입니다. 온디맨드 인스턴스와 스팟 인스턴스의 유일한 차이점은 EC2가 용량을 다시 필요로 할 때 2분동안의 알림으로 스팟 인스턴스가 Amazon EC2에 의해 중단 될 수 있다는 것입니다.

 

고객들은 2015년 1월부터 instance metadata service를 통해 제공되는 스팟 인스턴스 중단 알림을 활용하여 잠재적인 중단 상황에 대해 원활하게 작업 부하를 조정할 수 있습니다. 예를 들면, 작업 상태 저장, 로드 밸런서 분리 또는 유출 등이 있습니다. 2분 스팟 인스턴스 중단 알림은 스팟 인스턴스를 사용할 때 강력한 도구라는 것은 말할 필요도 없을 것 입니다.

 

2018 년 1월 스팟 인스턴스 중단 알림은 Amazon CloudWatch Events에서 이벤트로 사용할 수 있게 되었습니다. 이를 통해 AWS Lambda functions 또는 Amazon SNS topics와 같은 대상이 알림을 모니터링 하기 위해 Amazon CloudWatch Events 규칙을 작성하여 스팟 인스턴스 중단 알림을 처리 할 수 있습니다.

 

이번 포스팅에서는 CloudWatch 이벤트의 스팟 인스턴스 중단 알림을 활용하여 스팟 인스턴스를 엘라스틱 로드 밸런싱 어플리케이션 로드 밸런서에서 자동 등록 해제하는 사용 사례를 살펴 봅니다.

 

Architecture

이 참조 아키텍처에서는 AWS CloudFormation 템플릿을 사용하여 다음을 배포합니다.

 

 

AWS CloudFormation 스택 배포가 완료되면 두 가용 영역에서 다양화 된 Amazon EC2 Spot Fleet 요청을 생성하고 최근의 Spot Fleet 기능인 엘라스틱 로드 밸런싱 통합 인스턴스 Spot Fleet 태그 지정을 사용합니다.

 

스팟 인스턴스 중 하나가 중단 알림을 받으면 Spot Fleet이 이벤트를 CloudWatch Events에 보냅니다. CloudWatch Events 룰은 두 타겟, Lambda function 및 SNS 항목을 통지합니다. Lambda function은 인스턴스가 중단되기 전에 거의 2분간의 연결 유출을 활용하여 응용 프로그램 로드 밸런서 대상 그룹에서 스팟 인스턴스를 분리합니다. SNS 항목은 메시지를 수신하고 판독기가 연습용으로 사용하는 예제로 제공됩니다.

 

EC2 스팟 인스턴스 중단 알림 참조 아키텍처 다이어그램

 

예행 연습

이 연습을 완료하려면 AWS CLI를 설치 및 구성하고 CloudFormation 스택을 시작할 수 있어야 합니다.

 

스택 실행

CloudFormation 스택을 론칭 합니다. GitHub에서 확인하거나 템플릿을 직접 가져올 수 있습니다. 이 포스팅에서는 스택 이름 “spot-spin-cwe“을 사용하지만 마음에 드는 이름은 자유롭게 사용해도 됩니다. 지시 사항을 변경하는 것을 잊지만 않으면 됩니다.

 

Bash

$ git clone https://github.com/awslabs/ec2-spot-labs.git

 

$ aws cloudformation create-stack –stack-name spot-spin-cwe \

–template-body file://ec2-spot-labs/ec2-spot-interruption-notice-cloudwatch-events/ec2-spot-interruption-notice-cloudwatch-events.yaml \

–capabilities CAPABILITY_IAM

 

StackId 값을 받으면 스택이 시작되는지 확인해야 합니다.

 

Json

{

“StackId”: “arn:aws:cloudformation:us-east-1:123456789012:stack/spot-spin-cwe/083e7ad0-0ade-11e8-9e36-500c219ab02a”

}

 

세부 정보 검토

다음은 스택에 의해 시작되는 아키텍처의 세부 사항입니다.

 

IAM 사용 권한

아키텍처의 일부 구성 요소에 권한을 부여합니다.

 

  • Lambda function
  • CloudWatch 이벤트 규칙
  • Spot Fleet

 

Lambda function은 CloudWatch 로그에 로그를 쓸 수 있도록 기본적인 Lambda function 실행 권한을 필요로 합니다. 이를 위해 AWS에서 관리하는 정책을 사용할 수 있습니다. 또한 EC2 태그를 설명하고 엘라스틱 로드 밸런싱 내에서 대상 등록을 취소해야 합니다. 이러한 정책에 대한 사용자 지정 정책을 만들 수 있습니다.

 

YAML

lambdaFunctionRole:

Properties:

AssumeRolePolicyDocument:

Statement:

– Action:

– sts:AssumeRole

Effect: Allow

Principal:

Service:

– lambda.amazonaws.com

Version: 2012-10-17

ManagedPolicyArns:

– arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

Path: /

Policies:

– PolicyDocument:

Statement:

– Action: elasticloadbalancing:DeregisterTargets

Effect: Allow

Resource: ‘*’

– Action: ec2:DescribeTags

Effect: Allow

Resource: ‘*’

Version: ‘2012-10-17’

PolicyName:

Fn::Join:

– ‘-‘

– – Ref: AWS::StackName

– lambdaFunctionRole

Type: AWS::IAM::Role

 

CloudWatch 이벤트가 Lambda function을 호출하고 SNS 항목에 게시 할 수 있게 합니다.

YAML

lambdaFunctionPermission:

Properties:

Action: lambda:InvokeFunction

FunctionName:

Fn::GetAtt:

– lambdaFunction

– Arn

Principal: events.amazonaws.com

SourceArn:

Fn::GetAtt:

– eventRule

– Arn

Type: AWS::Lambda::Permission

 

YAML

snsTopicPolicy:

DependsOn:

– snsTopic

Properties:

PolicyDocument:

Id:

Fn::GetAtt:

– snsTopic

– TopicName

Statement:

– Action: sns:Publish

Effect: Allow

Principal:

Service:

– events.amazonaws.com

Resource:

Ref: snsTopic

Version: ‘2012-10-17’

Topics:

– Ref: snsTopic

Type: AWS::SNS::TopicPolicy

 

마지막으로, Spot Fleet은 엘라스틱 로드 밸런싱에서 스팟 인스턴스, 태그 및 등록 대상을 요청할 수 있는 권한이 필요합니다. 이를 위해 AWS에서 관리하는 정책을 활용할 수 있습니다.

 

YAML

spotFleetRole:

Properties:

AssumeRolePolicyDocument:

Statement:

– Action:

– sts:AssumeRole

Effect: Allow

Principal:

Service:

– spotfleet.amazonaws.com

Version: 2012-10-17

ManagedPolicyArns:

– arn:aws:iam::aws:policy/service-role/AmazonEC2SpotFleetTaggingRole

Path: /

Type: AWS::IAM::Role

 

엘라스틱 로드 밸런싱 타임아웃 지연

2분 스팟 인스턴스 알림을 활용하여 엘라스틱 로드 밸런싱 대상 그룹 등록 해제 제한 시간을 조정할 수 있습니다. 대상이 대상 그룹에서 등록 취소되면 타임아웃 지연의 시간 동안 연결 유출 모드로 전환됩니다: 120초, 2분 알림과 같습니다.

 

YAML

loadBalancerTargetGroup:

DependsOn:

– vpc

Properties:

HealthCheckIntervalSeconds: 5

HealthCheckPath: /

HealthCheckTimeoutSeconds: 2

Port: 80

Protocol: HTTP

TargetGroupAttributes:

– Key: deregistration_delay.timeout_seconds

Value: 120

UnhealthyThresholdCount: 2

VpcId:

Ref: vpc

Type: AWS::ElasticLoadBalancingV2::TargetGroup

 

CloudWatch 이벤트 규칙

CloudWatch Events에 게시되는 스팟 인스턴스 중단 알림을 캡처 하려면 Lambda function과 SNS 항목이라는 두 개의 타겟이 있는 규칙을 만들어야 합니다.

 

YAML

eventRule:

DependsOn:

– snsTopic

Properties:

Description: Events rule for Spot Instance Interruption Notices

EventPattern:

detail-type:

– EC2 Spot Instance Interruption Warning

source:

– aws.ec2

State: ENABLED

Targets:

– Arn:

Ref: snsTopic

Id:

Fn::GetAtt:

– snsTopic

– TopicName

– Arn:

Fn::GetAtt:

– lambdaFunction

– Arn

Id:

Ref: lambdaFunction

Type: AWS::Events::Rule

 

Lambda function

Lambda function은 우리의 무거운 짐을 덜어줍니다. CloudWatch 이벤트의 세부 정보는 Lambda function에 게시되고, boto3을 사용하여 두 개의 AWS API 호출 만듭니다. 첫 번째 호출은 “TargetGroupArn” 키를 필터링 하여 스팟 인스턴스에 대한 EC2 태그를 형성 합니다. 이 태그가 발견되면 인스턴스는 태그 값으로 저장된 대상 그룹 ARN에서 등록 취소됩니다.

 

Python

import boto3

def handler(event, context):

instanceId = event[‘detail’][‘instance-id’]

instanceAction = event[‘detail’][‘instance-action’]

try:

ec2client = boto3.client(‘ec2’)

describeTags = ec2client.describe_tags(Filters=[{‘Name’: ‘resource-id’,’Values’:[instanceId],’Name’:’key’,’Values’:[‘loadBalancerTargetGroup’]}])

except:

print(“No action being taken. Unable to describe tags for instance id:”, instanceId)

return

try:

elbv2client = boto3.client(‘elbv2’)

deregisterTargets = elbv2client.deregister_targets(TargetGroupArn=describeTags[‘Tags’][0][‘Value’],Targets=[{‘Id’:instanceId}])

except:

print(“No action being taken. Unable to deregister targets for instance id:”, instanceId)

return

print(“Detaching instance from target:”)

print(instanceId, describeTags[‘Tags’][0][‘Value’], deregisterTargets, sep=”,”)

return

 

SNS 항목

마지막으로 예제 타겟으로 SNS 항목을 만들었습니다. 예를 들어, 스팟 인스턴스 중단 알림을 받으면 전자 메일 알림을 수신하기 위해 SNS 항목에 전자 메일 주소를 입력시킬 수 있습니다.

 

YAML

snsTopic:

Properties:

DisplayName: SNS Topic for EC2 Spot Instance Interruption Notices

Type: AWS::SNS::Topic

 

Spot Fleet 요청 만들기

Spot Fleet 요청을 생성하려면 CloudFormation 스택이 생성한 일부 리소스를 사용하여 Spot Fleet 요청 시작 구성을 채웁니다. CloudFormation 스택의 출력 값에서 값을 찾을 수 있습니다.

 

Bash

$ aws cloudformation describe-stacks –stack-name spot-spin-cwe

 

CloudFormation 스택의 출력 값을 사용하여 Spot Fleet 요청 구성에서 다음 값을 업데이트합니다.

 

  • % spotFleetRole %
  • % publicSubnet1 %
  • % publicSubnet2 %
  • % loadBalancerTargetGroup % (두 군데)

 

또한 % amiId %를 해당 지역의 최신 Amazon Linux AMI로 대체하고 % keyName %을 사용자 환경으로 대체합니다.

 

Json

{

“AllocationStrategy”: “diversified”,

“IamFleetRole”: “%spotFleetRole%”,

“LaunchSpecifications”: [

{

“ImageId”: “%amiId%”,

“InstanceType”: “c4.large”,

“Monitoring”: {

“Enabled”: true

},

“KeyName”: “%keyName%”,

“SubnetId”: “%publicSubnet1%,%publicSubnet2%”,

“UserData”: “IyEvYmluL2Jhc2gKeXVtIC15IHVwZGF0ZQp5dW0gLXkgaW5zdGFsbCBodHRwZApjaGtjb25maWcgaHR0cGQgb24KaW5zdGFuY2VpZD0kKGN1cmwgaHR0cDovLzE2OS4yNTQuMTY5LjI1NC9sYXRlc3QvbWV0YS1kYXRhL2luc3RhbmNlLWlkKQplY2hvICJoZWxsbyBmcm9tICRpbnN0YW5jZWlkIiA+IC92YXIvd3d3L2h0bWwvaW5kZXguaHRtbApzZXJ2aWNlIGh0dHBkIHN0YXJ0Cg==”,

“TagSpecifications”: [

{

“ResourceType”: “instance”,

“Tags”: [

{

“Key”: “loadBalancerTargetGroup”,

“Value”: “%loadBalancerTargetGroup%”

}

]

}

]

}

],

“TargetCapacity”: 2,

“TerminateInstancesWithExpiration”: true,

“Type”: “maintain”,

“ReplaceUnhealthyInstances”: true,

“InstanceInterruptionBehavior”: “terminate”,

“LoadBalancersConfig”: {

“TargetGroupsConfig”: {

“TargetGroups”: [

{

“Arn”: “%loadBalancerTargetGroup%”

}

]

}

}

}

 

구성을 저장하고 Spot Fleet 요청을 배치 합니다.

 

Bash

$ aws ec2 request-spot-fleet –spot-fleet-request-config file://sfr.json

 

그 답장으로 요청을 확인하는 SpotFleetRequestId를 수신해야 합니다.

 

Json

{

“SpotFleetRequestId”: “sfr-3cec4927-9d86-4cc5-a4f0-faa996c841b7”

}

 

ActivityStatus가 “fulfilled”인지 확인하거나 요청을 설명하면서 FulfilledCapacityTargetCapacity보다 크거나 같은지 확인하여 Spot Fleet 요청이 완료되었는지 확인할 수 있습니다.

 

Bash

$ aws ec2 describe-spot-fleet-requests –spot-fleet-request-id sfr-3cec4927-9d86-4cc5-a4f0-faa996c841b7

 

Json

{

“SpotFleetRequestConfigs”: [

{

“ActivityStatus”: “fulfilled”,

“CreateTime”: “2018-02-08T01:23:16.029Z”,

“SpotFleetRequestConfig”: {

“AllocationStrategy”: “diversified”,

“ExcessCapacityTerminationPolicy”: “Default”,

“FulfilledCapacity”: 2.0,

“TargetCapacity”: 2,

}

]

}

 

다음으로 스팟 인스턴스가 엘라스틱 로드 밸런싱 대상 그룹에 등록되어 있고 정상 상태인지 확인할 수 있습니다.

 

Bash

$ aws elbv2 describe-target-health –target-group-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/spot-loadB-1DZUVWL720VS6/26456d12cddbf23a

 

Json

{

“TargetHealthDescriptions”: [

{

“Target”: {

“Id”: “i-056c95d9dd6fde892”,

“Port”: 80

},

“HealthCheckPort”: “80”,

“TargetHealth”: {

“State”: “healthy”

}

},

{

“Target”: {

“Id”: “i-06c4c47228fd999b8”,

“Port”: 80

},

“HealthCheckPort”: “80”,

“TargetHealth”: {

“State”: “healthy”

}

}

]

}

 

테스트

테스트를 위해 Spot Fleet이 스팟 인스턴스에서 취하는 모든 중단 작업이 스팟 인스턴스 중단 알림을 제공한다는 사실을 활용할 수 있습니다. 따라서 Spot Fleet의 대상 크기를 2에서 1로 간단히 줄일 수 있습니다. 중단된 인스턴스는 중단 알림을 받습니다.

 

Bash

$ aws ec2 modify-spot-fleet-request –spot-fleet-request-id sfr-3cec4927-9d86-4cc5-a4f0-faa996c841b7 –target-capacity 1

 

Json

{

“Return”: true

}

 

중단 알림이 CloudWatch Events에 게시되는 즉시, Lambda function은 인스턴스를 대상 그룹에서 트리거하고 분리하여 효과적으로 인스턴스를 유출 상태로 만듭니다.

 

Bash

$ aws elbv2 describe-target-health –target-group-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/spot-loadB-1DZUVWL720VS6/26456d12cddbf23a

 

Json

{

“TargetHealthDescriptions”: [

{

“Target”: {

“Id”: “i-0c3dcd78efb9b7e53”,

“Port”: 80

},

“HealthCheckPort”: “80”,

“TargetHealth”: {

“State”: “draining”,

“Reason”: “Target.DeregistrationInProgress”,

“Description”: “Target deregistration is in progress”

}

},

{

“Target”: {

“Id”: “i-088c91a66078b4299”,

“Port”: 80

},

“HealthCheckPort”: “80”,

“TargetHealth”: {

“State”: “healthy”

}

}

]

}

 

결론

결론적으로, Amazon EC2 스팟 인스턴스 중단 알림은 상태 저장, 연결 끊기 등과 같은 작업을 위해 워크로드에서 Amazon EC2 스팟 인스턴스를 활용할 때 매우 강력한 도구입니다. 나는 여러분들이 여러분들의 환경에서 이것을 어떻게 사용하고 있는지 듣고 싶습니다!

 

원문 URL: https://aws.amazon.com/ko/blogs/compute/taking-advantage-of-amazon-ec2-spot-instance-interruption-notices/

** 메가존 TechBlog는 AWS BLOG 영문 게재글중에서 한국 사용자들에게 유용한 정보 및 콘텐츠를 우선적으로 번역하여 내부 엔지니어 검수를 받아서, 정기적으로 게재하고 있습니다. 추가로 번역및 게재를 희망하는 글에 대해서 관리자에게 메일 또는 SNS페이지에 댓글을 남겨주시면, 우선적으로 번역해서 전달해드리도록 하겠습니다.