[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에서 함수 생성을 눌러 함수를 생성합시다.
원하는 함수 이름을 입력하고, 역할은 우선 새 역할을 생성하는 것을 선택하고 넘어가겠습니다.
정상적으로 생성되면 다음 [그림 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를 남기는 권한만 있는데, 구성 > 권한으로 이동하여 역할 이름을 눌러봅시다.
정책을 통해 권한을 수정하기 위해 정책 이름을 클릭합시다.
우측의 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를 다음과 같이 설정해줍시다.
태그에서 auto-start 키에 true 값을 넣으면 람다를 실행시켰을 때 해당 인스턴스가 시작됩니다. 그리고 auto-stop도 미리 넣어두겠습니다.
Tags를 추가하고, 인스턴스를 중지를 시킨 상태에서 [그림 2]에서 Test 버튼을 눌러 앞서 생성한 람다를 실행시키면 인스턴스가 켜지는 것을 확인하실 수 있습니다.
EventBridge 트리거 추가
다음으로, [그림 2]에서 트리거 추가 버튼을 눌러 CloudWatch Events를 선택하면 Cron과 같이 스케줄 작업을 설정할 수 있습니다. 예약 표현식에서 cron 표현식을 작성할 수 있는데, 다음 [그림 7]과 같이 평일 오전 8시에 시작하도록 작성해봅시다. 참고로 UTC 시간 기준으로 +9시간을 더해야 한국 시간이 되니 참고해주세요!
이렇게 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를 설정하면 모든 설정이 완료됩니다.
해당 내용을 통해 비용을 최대한 절약할 수 있는 하나의 방법이 될 수 있길 바랍니다!!😎
'클라우드 > AWS' 카테고리의 다른 글
[AWS] Site-to-Site VPN 구성하기: 온프레미스 사설망과의 연결 (1) | 2023.12.23 |
---|---|
[AWS] EFS 생성 및 마운트 방법 (1) | 2023.06.07 |
[AWS] Cost & usage reports를 통한 비용 보고서 생성 (0) | 2023.05.11 |
[AWS] Calculator를 통한 예상 비용 계산 방법 (0) | 2023.05.02 |
[AWS] AWS CLI를 여러 계정으로 이용하기 (0) | 2023.04.22 |
소중한 공감 감사합니다