AWS Instance Scheduler (AWS Lambda)

2021. 5. 6. 16:16Cloud/AWS Lambda

AWS의 서비스를 이용하다보면 Console 또는 CLI를 통해 수동으로 관리하게 된다. 가령 EC2를 예로 들면 서버 리소스를 사용하기 위해 running 시켜놓고 사용을 하지 않을 때는 서버를 꺼줘야 비용 부담이 적게 발생하게 된다.

하지만 서버의 수가 적거나 간단한 테스트용이라면 상관 없지만 서버가 매우 많고 서버마다 필요한 케이스들이 상이하다면 관리하기가 힘들다. 또한 그렇지 않더라도 매일 사용하는 서버의 경우 일일이 켜주는 작업은 다소 비효율적이기도 하다.

따라서 정해진 시간, 날짜에 서버를 자동으로 켜고 끄는 서버 스케쥴링을 구현해보도록 하자


1. EC2 생성

2. 서버 스케쥴링을 위한 정책 생성

3. 정책을 이용하기 위해 역할 생성

4. Lambda 생성

5. 이벤트 로그를 확인하기 위해 CloudWatch 생성

6. 코드 작성 (Python)


내용을 시작하기에 앞서 각 서비스마다 태그와 관련된 사항이 나올 때,

'Name : EC2-Scheduling-서비스명' 으로 설정하겠다.

1. EC2 생성

테스트용으로 만들 것이기 때문에 프리티어로 만들어보도록 하자

EC2 생성

Amazon Linux2 프리티어로 모두 default 설정했다.  (Tag > Name : EC2-Scheduling-EC2)

2. 서버 스케쥴링을 위한 정책 생성

IAM에서 '정책' 탭을 클릭하고 '정책 생성'으로 이동한다.

정책 생성 페이지에서 JSON으로 Lambda가 EC2를 관리할 수 있는 Action을 추가해준다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances",
                "ec2:StartInstances",
                "ec2:StopInstances"
            ],
            "Resource": "*"
        }
    ]
}

태그는 개인적 편의에 따라 구분지으면 된다.

ex, Name : EC2-Scheduling-Policy

 

정책 생성

다음과 같이 다른 서비스와 구분이 될 정도로만 작성해주고 모두 default 설정해준다.

3. 정책을 이용하기 위해 역할 생성

정책 생성이 완료되면 IAM에서 '역할' 탭으로 이동하자. 정책과 비슷한 프로세스로 '역할 만들기'를 클릭한다.

 

역할 생성

다음과 같은 페이지가 보일 것이다. 그림에서의 '사용 사례 선택'에 있는 Lambda를 클릭한다. '사용 사례 선택'은 사용자마다 다르게 나타날 것이다. 만약 이 위치에 Lambda가 없다면 밑에 있는 '또는 서비스를 선택하여 해당 서비스의 사용 사례 확인'에서 찾아 클릭하고 다음으로 넘어간다.

 

앞서 정책만들기를 통해 Lambda가 EC2를 관리할 수 있는 정책을 만들었었다. '역할 만들기' 페이지의 '정책 필터'에서 'EC2-Scheduling-Policy'(본인이 설정한 tag명)와 'AWSLambdaBasicExecutionRole'를 추가해준다.

 

생성이 완료되면 다음과 같은 정보를 확인할 수 있다.

4. Lambda 생성

이제 Lambda 함수를 생성해보자

서버 스케쥴링 예시를 Python으로 만들 것이기 때문에 런타임은 Python으로 설정해준다. 또한 '기본 실행 역할 변경'에서 기존 역할 사용을 클릭해 아까 우리가 만든 EC2-Scheduling-Role을 선택해서 사용할 수 있게끔 설정한다.

 

이러한 모습을 확인할 수 있다. 이제 로그를 관리하기 위해 '+ 트리거 추가' 로 CloudWatch를 구성해보자

5. 이벤트 로그를 확인하기 위해 CloudWatch 생성

'트리거 추가' 클릭 후, 트리거 구성에서 'EventBridge(CloudWatch Events)'를 선택한다.

서버 스케쥴링을 간단히 테스트해보는 과정이므로 평일 5분마다 서버를 자동으로 켜고 끄는 규칙으로 설정해보도록 하자

cron(0/5 * ? * MON-FRI *)

cron 식을 다음과 같이 표현했는데 다른 예시로는 여기를 참조하길 바란다.

6. 코드 작성

Lambda의 '코드'에서 다음과 같이 코드를 작성해보자. 단 'lambda_function.py'의 파일명을 바꾸면 안 된다.

파일을 클릭하고 해당 코드를 입력해준다. 매번 코드를 수정하고 Deploy를 클릭하고 Test를 클릭해주면 된다.

import json
import datetime
import boto3

instance_ID = 'EC2-Scheduling-EC2' # 이 부분은 따로 테스트 이벤트로 관리하면 더 좋을 것

def lambda_handler(event, context):
    client = boto3.client('ec2')  #ec2 client 불러오기
    response = client.describe_instances() # 계정에 있는 EC2 instance 모두 할당
    
    ec2_list = []       # 타겟 EC2를 저장하기 위한 리스트. start_instances or stop_instances의 경우, 리스트 인자를 필수적으로 할당해줘야 함
    is_Running = False
    
    for ec2 in response['Reservations']:
        for instance in ec2['Instances']:
            for tags in instance['Tags']:
                if tags['Key'] == 'Name':
                    if instance_ID in tags['Value']: # 만약 찾고자 하는 instance가 있는 경우
                        print("\n=== FIND TARGET EC2 ===")
                        print(tags['Value'] + ' : ' + instance['InstanceId'] + '\n')
                        ec2_list.append(instance['InstanceId'])
                            
                        if instance['State']['Code'] == 16: # running(16) # 현재 running 중이면 is_Running을 True로 갱신
                            is_Running = True
                        else :      # 그렇지 않다면 False
                            is_Running = False


    if is_Running == False :    # 현재 EC2가 running 중이지 않으므로 start해준다
        start = client.start_instances(InstanceIds = ec2_list)
        print("=== SERVER START ====")
        return start
    else :                      # 현재 타겟 EC2가 running 중이라면 Stop해준다.
        stop = client.stop_instances(InstanceIds = ec2_list)
        print("=== SERVER STOP ====")
        return stop

Test 버튼을 클릭하기 전에 아까 만든 EC2를 다시 한 번 정상적으로 running 중인지 확인해보자

Test 버튼을 클릭하면 stop의 객체를 리턴해주고 EC2를 확인하면 인스턴스 중지가 됨을 확인할 수 있다.

또한 CloudWatch의 로그 그룹에서 서버가 5분마다 켜지고 꺼지는 것을 확인할 수 있다.