본문 바로가기

프로그래밍/클라우드

[AWS] Amazon EC2 인스턴스 자동 실행, 중지 (Lambda 이용)

EC2 인스턴스를 일정한 주기로 실행하고 중지해야 하는 경우가 있다.

나의 경우를 예로 들면 사내 테스트 서버의 경우 회사 근무 시간 때에만 실행이 필요한 순간이 있었다.

또한 토이프로젝트로 자동 주식 매매 프로그램을 만들어 구동하고 있는데 매매 거래시간에만 인스턴스를 구동하고 이외의 시간에는 중지하여 비용을 줄이고자 하는 경우가 있었다.

 

스케줄링을 통해 Amazon EC2를 제어하는 방법은 여러 가지가 있을 수 있겠지만 여기서는 가장 직관적이고 간단할 것 같은 AWS Lambda와 Amazon CloudWatch를 이용해 구현해보려고 한다.

 

EC2 인스턴스를 실행하거나 종료하는 Lambda 함수를 만들고 특정 시간에 함수를 트리거하는 Amazon CloudWatch 이벤트를 생성하면 된다.

 


 

보다 구체적인 진행 과정은 아래와 같다.

여기에서는 EC2를 종료하는 Lambda를 만들어보겠다.

 

먼저 아래 화면과 같이 AWS Lambda에서 함수 생성을 한다.

 

AWS Lambda 함수 생성

 

다음으로 본인이 구별할 수 있는 적절한 Function name을 정한다.

 

런타임과 아키텍처는 각각 Python 3.9와 x86_64로 했다.

 

 

 

다음으로 실행 역할(execution role) 설정이 필요하다.

Lambda가 EC2를 제어하기 위해서는 특정한 권한이 필요하기 때문이다.

IAM에서 역할을 생성해두면 기존 역할 사용에서 선택이 가능하다.

 

실행 역할 설정 화

 

 

 

Identity and Access Management(IAM)에 들어가 필요한 권한들을 담은 역할을 만든다.

결과는 아래와 같다.

 

IAM 역할 생성

 

 

AllowStopEc2 정책

 

 

다시 Lambda를 생성하는 화면으로 돌아와 새로고침해보면 방금 생성한 정책을 찾을 수 있을 것이다.

그것을 선택하고 함수 생성을 완료한다.

 

함수 생성

 

 

함수 생성을 완료하면 lambda_function.py에 기본 코드가 생성되어있다.

코드를 새로 작성하기 위해 모두 삭제한다. (lambda_function.py는 그대로 두고 코드만 삭제하면 된다.)

 

기본 생성되어있는 lambda_function.py

 

 

위의 코드를 모두 지웠으면 아래의 코드를 붙여 넣기 한다.

import boto3
region = '<REPLACE_WITH_REGION>'
instances = ['<REPLACE_WITH_INSTANCE_ID_1>', '<REPLACE_WITH_INSTANCE_ID_2>']
ec2 = boto3.client('ec2', region_name=region)
​
def lambda_handler(event, context):
    ec2.stop_instances(InstanceIds=instances)
    print('stopped your instances: ' + str(instances))

 

참고로 EC2를 시작하는 코드는 아래와 같다.

import boto3
region = '<REPLACE_WITH_REGION>'
instances = ['<REPLACE_WITH_INSTANCE_ID_1>', '<REPLACE_WITH_INSTANCE_ID_2>']
ec2 = boto3.client('ec2', region_name=region)

def lambda_handler(event, context):
    ec2.start_instances(InstanceIds=instances)
    print('started your instances: ' + str(instances))

 

<REPLACE_WITH_REGION> 자리에는 현재 본인이 사용 중인 리전을, <REPLACE_WITH_INSTANCE_ID> 자리에는 종료할 인스턴스의 ID를 넣으면 된다.

 

EC2의 인스턴스 ID는 아래의 화면에서 확인이 가능하다.

EC2 인스턴스 ID 찾기

 

 

 

나의 경우는 아래와 같다.

완성 코드

 

코드를 모두 완성했으면 Deploy를 누른다.

 

 

다음으로 인스턴스를 종료시킬 트리거가 필요하다.

아래와 같이 "트리거 추가"(Add trigger)버튼을 누른다.

 

트리거 추가

 

 

EventBridge(CloudWatch Events)를 사용하면 cron표현식으로 스케줄링할 수 있다. 시간은 UTC 기준이다.

 

 

cron은 아래와 같이 표현하면 된다.

cron(Minutes Hours Day-of-month Month Day-of-week Year)

 

(cron 표현 예시)

빈도 표현식
매일 10:15 AM(UTC) cron(15 10 * * ? *)
월요일부터 금요일까지 오후 6:00 cron(0 18 ? * MON-FRI *)
매월 첫날 오전 8:00 cron(0 8 1 * ? *)
평일 10분마다 cron(0/10 * ? * MON-FRI *)
평일 오전 8:00부터 오후 5:55까지 5분마다 cron(0/5 8-17 ? * MON-FRI *)
매월 첫째 월요일 오전 9:00 cron(0 9 ? * 2#1 *)

 

 

자주 사용하지 않으면 은근히 헷갈리는데 https://crontab.guru/ 사이트를 참고하면 cron 표현식을 쉽게 만들 수 있다.

 

Crontab.guru - The cron schedule expression editor

 

crontab.guru

 

 

 

단순한 경우는 rate 표현식을 사용할 수도 있다.

 

rate 표현식은 아래와 같다.

rate(Value Unit)

 

(rate 표현 예시)

빈도 표현식
5분마다 rate(5 minutes)
매 시간 rate(1 hour)
7일마다 rate(7 days)

 

설명이 길어졌는데 완성한 화면은 다음과 같다.

나는 한국시각으로 매일 18시에 인스턴스를 종료하도록 했다.

 

매일 UTC 9시에 트리거

 

이렇게 하면 매일 UTC 기준으로 9시에 람다 코드가 실행되고 람다가 인스턴스를 중지시킬것이다.

 

끝.