새소식

클라우드/AWS

[AWS] Lambda를 통한 Instance 및 RDS 자동 중지 및 시작 방법

  • -

제가 작성한 AWS Lambda를 통한 EC2 인스턴스와 RDS 데이터베이스의 자동 중지 및 시작 방법에 대한 블로그 포스팅을 아래에 제시합니다. 이 포스팅은 AWS Lambda 함수를 사용하여 일정 시간이 지난 후에 EC2 인스턴스와 RDS 데이터베이스를 중지하고 다시 시작하는 방법에 대해 안내합니다.


개요

EC2 인스턴스 및 RDS는 시간당 또는 사용한 용량에 따라 비용이 청구됩니다. 이러한 비용은 인스턴스가 실행되는 동안 계속해서 발생하므로, 필요하지 않은 시간에 인스턴스가 실행되어 있는 경우 비효율적인 비용이 발생할 수 있습니다. 사용하지 않는 시간대에는 불필요한 비용이 나가지 않도록 중지시켜 두는 것이 좋습니다. 예를 들어, 회사 출근 시간에만 사용한다고 가정하면, 오전 8시부터 오후 7시까지만 켜지도록 설정할 수 있습니다. 사용 시간에 따른 비용 최적화를 위해 Lambda를 사용하여 EC2 인스턴스와 RDS를 자동으로 on/off 할 수 있도록 구성해봅시다.

 

Lambda 생성 및 코드 작성

Lambda는 AWS에서 제공하는 서버리스 컴퓨팅 서비스로, 특정 이벤트에 대한 리액션을 자동으로 수행하는 데 사용됩니다. Lambda 함수는 사용자가 정의한 코드를 실행하며, 이벤트 트리거를 기반으로 실행됩니다.

먼저, AWS 콘솔에서 EC2 인스턴스와 RDS를 자동으로 시작해주는Lambda에서 함수 생성을 눌러 함수를 생성합시다.

[그림 1] Instance/RDS auto-start 람다 생성

원하는 함수 이름을 입력하고, 역할은 우선 새 역할을 생성하는 것을 선택하고 넘어가겠습니다.

정상적으로 생성되면 다음 [그림 2]와 같은 화면을 볼 수 있습니다.

[그림 2] 람다 생성 후 화면

정상적으로 생성되었으면 아래 코드 소스 부분에 다음 코드를 그대로 입력해봅시다.

import boto3

region = 'ap-northeast-2'
instances = []
ec2_r = boto3.resource('ec2')
ec2 = boto3.client('ec2', region_name=region)
rds = boto3.client('rds')

for instance in ec2_r.instances.all():
    if instance.state['Name'] == 'stopped':
        for tag in instance.tags:
            if tag['Key'] == 'auto-start':
                if tag['Value'] == 'true':
                    instances.append(instance.id)

def lambda_handler(event, context):
    if len(instances) == 0:
        print('instance not found')
    else:
        ec2.start_instances(InstanceIds=instances)
        print('start your instances: ' + str(instances))
        
    dbs = rds.describe_db_instances()
    for db in dbs['DBInstances']:
        if (db['DBInstanceStatus'] == 'stopped'):
            doNotStart=1
            try:
                GetTags=rds.list_tags_for_resource(ResourceName=db['DBInstanceArn'])['TagList']
                for tags in GetTags:
                    if(tags['Key'] == 'auto-start' and tags['Value'] == 'true'):
                        result = rds.start_db_instance(DBInstanceIdentifier=db['DBInstanceIdentifier'])
                        print ("Starting instance: {0}.".format(db['DBInstanceIdentifier']))
                if(doNotStart == 1):
                    doNotStart=1
            except Exception as e:
                print ("Cannot start instance {0}.".format(db['DBInstanceIdentifier']))
                print(e)

간단하게 설명하자면, 서울 리전의 EC2 Instance와 RDS가 중지 상태이고, tags의 auto-start 키의 값이 true면 인스턴스를 시작시키게 됩니다.

 

Lambda 권한 설정

이대로 Deploy를 누르고 Test를 하면 Lambda에서 Instance와 RDS의 상태를 변경할 권한이 없어 실패할 것 입니다. 기본적으로 CloudWatch Log를 남기는 권한만 있는데, 구성 > 권한으로 이동하여 역할 이름을 눌러봅시다.

[그림 3] 람다 권한 확인

정책을 통해 권한을 수정하기 위해 정책 이름을 클릭합시다.

[그림 4] 정책 이름 클릭

우측의 JSON을 선택하고, 편집을 클릭하겠습니다.

[그림 5] JSON 형태로 정책 수정

기존 내용을 모두 지우고 다음 코드 내용을 붙여 넣습니다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "start",
            "Effect": "Allow",
            "Action": [
                "ec2:StartInstances",
                "rds:StartDBCluster",
                "rds:StartDBInstance"
            ],
            "Resource": [
                "arn:aws:rds:*:*:db:*",
                "arn:aws:ec2:*:*:instance/*"
            ]
        },
        {
            "Sid": "describe",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances",
                "ec2:DescribeTags",
                "ec2:DescribeInstanceStatus",
                "rds:ListTagsForResource",
                "rds:DescribeDBInstances",
                "rds:DescribeDBClusters"
            ],
            "Resource": "*"
        }
    ]
}

 

Tags 추가

EC2 Instance와 RDS를 시작하기 위해 필요한 권한들을 부여해두고, 자동 시작을 적용할 인스턴스의 Tags를 다음과 같이 설정해줍시다.

[그림 6] EC2 Instance의 Tags 설정

태그에서 auto-start 키에 true 값을 넣으면 람다를 실행시켰을 때 해당 인스턴스가 시작됩니다. 그리고 auto-stop도 미리 넣어두겠습니다.

Tags를 추가하고, 인스턴스를 중지를 시킨 상태에서 [그림 2]에서 Test 버튼을 눌러 앞서 생성한 람다를 실행시키면 인스턴스가 켜지는 것을 확인하실 수 있습니다.

 

EventBridge 트리거 추가

다음으로, [그림 2]에서 트리거 추가 버튼을 눌러 CloudWatch Events를 선택하면 Cron과 같이 스케줄 작업을 설정할 수 있습니다. 예약 표현식에서 cron 표현식을 작성할 수 있는데, 다음 [그림 7]과 같이 평일 오전 8시에 시작하도록 작성해봅시다. 참고로 UTC 시간 기준으로 +9시간을 더해야 한국 시간이 되니 참고해주세요!

[그림 7] EventBridge 생성

이렇게 EventBridge가 생성되면 평일 오전 8시마다 앞서 생성한 auto-start 람다가 실행됩니다.

 

auto-stop 요약 정리

기본적인 생성 방법은 auto-start 부분과 동일하고, 수정해야될 부분만 간단하게 설명합니다.

Lambda 코드는 다음과 같이 입력합니다.

import boto3

region = 'ap-northeast-2'
instances = []
ec2_r = boto3.resource('ec2')
ec2 = boto3.client('ec2', region_name=region)
rds = boto3.client('rds')

for instance in ec2_r.instances.all():
    if instance.state['Name'] == 'running':
        for tag in instance.tags:
            if tag['Key'] == 'auto-stop':
                if tag['Value'] == 'true':
                    instances.append(instance.id)

def lambda_handler(event, context):
    if len(instances) == 0:
        print('instance not found')
    else:
        ec2.stop_instances(InstanceIds=instances)
        print('stopped your instances: ' + str(instances))
        
    dbs = rds.describe_db_instances()
    for db in dbs['DBInstances']:
        if (db['DBInstanceStatus'] == 'available'):
            DoNotStop=1
            try:
                GetTags=rds.list_tags_for_resource(ResourceName=db['DBInstanceArn'])['TagList']
                for tags in GetTags:
                    if(tags['Key'] == 'auto-stop' and tags['Value'] == 'true'):
                        result = rds.stop_db_instance(DBInstanceIdentifier=db['DBInstanceIdentifier'])
                        print ("Stopping instance: {0}.".format(db['DBInstanceIdentifier']))
                if(DoNotStop == 1):
                    DoNotStop=1
            except Exception as e:
                print ("Cannot stop instance {0}.".format(db['DBInstanceIdentifier']))
                print(e)

Lambda 권한을 위한 정책의 json은 다음과 같이 입력합니다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "stop",
            "Effect": "Allow",
            "Action": [
                "ec2:StopInstances",
                "ec2:DescribeInstances",
                "ec2:DescribeTags",
                "ec2:DescribeInstanceStatus",
                "rds:StopDBCluster",
                "rds:ListTagsForResource",
                "rds:DescribeDBInstances",
                "rds:StopDBInstance",
                "rds:DescribeDBClusters"
            ],
            "Resource": "*"
        }
    ]
}

EventBridge의 예약 표현식은 cron(0 10 ? * MON-FRI *)으로 설정하여 오후 7시마다 auto-stop 람다가 실행되도록 설정합니다.

여기까지 정상적으로 설정되면 EC2 인스턴스 및 RDS의 태그에 auto-stop 키 값에 true를 설정하면 모든 설정이 완료됩니다.

 

해당 내용을 통해 비용을 최대한 절약할 수 있는 하나의 방법이 될 수 있길 바랍니다!!😎

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.