본문 바로가기

블로그

LG CNS 기술블로그 DX Lounge에서 최신 IT 소식을 만나보세요!

AWS Ambassador

필요할 때만 씁시다! Lambda로 껐다 켜는 EC2

2023.02.01

[ 머리말 ]

EC2 관련하여 비용 효율성을 달성할 수 있는 가장 쉬운 방법은, “우선 안 쓸 땐 Shutdown 한다” 입니다. 특정 날짜, 특정 시간에 서버를 켜고 끄는 방식의 운영은 서비스의 오픈 후에는 지속적인 적용이 어려울 수 있지만, 서비스의 특성에 따라 가능한 경우도 있고, 개발, 스테이징 환경 등에는 항상 적용해 둘 수 있는 비용 절약 방식입니다.

이번 블로그에서는, 특정 Tag와 Lambda를 활용하여 EC2와 RDS를 날짜, 시간에 맞춰 켜고 끄는 방법을 알아보겠습니다. 3가지 중요한 포인트가 있습니다.

(1) 적용이 쉬워야 한다.

(2) 시작/ 종료의 시간 설정이 분명하고 용이해야 한다.

(3) 암호화를 잊어서는 안된다.

진행 시나리오는 다음과 같습니다. 

“EBS가 암호화된 EC2를 TAG에 정의된 스케줄 적용 여부, 적용 시간에 따라 EC2를 켜고 끄는 Lambda를 구성하고 활용해 보는 것” 입니다. 

[ Architecture ]

[ Content ]

** EC2의 생성과 KMS에서의 CMS key 생성, 그를 통해 암호화된  EBS의 생성에 대한 절차는 우선 생략합니다! 

  1. IAM Role의 생성

람다에 부여할 IAM Role을 먼저 생성합니다.  해당 Role은 Lambda 생성 중에도 Create a Role을 통해 만들 수 있지만, EBS 암호화로 인한 문구 추가가 필수적으로 일어납니다. 따라서 권한에 대한 분명한 이해를 수행하기 위해, 먼저 IAM을 생성합니다.

     TIPS! – KMS에 대한 권한이 왜 필요한가?


     Lambda가 EC2에 대한 Stop / Start에 대한 권한을 필요로 하는 것은 이해할 수 있습니다. 그런데 왜 KMS에 대한 권한이 필요할까요? 
     KMS에 대한 권한이 없는 User가 암호화된 EC2를 Start / Stop 하면 어떻게 될까요? Stop은 잘됩니다. 하지만 Start는 부팅 중 에러가 납니다.
     EBS가 암호화된 경우 EC2의 Start를 위해서 KMS의 사용 권한이 필요한 것입니다. 따라서 Lambda도 KMS에 사용 권한을 보유해야 합니다. 

——————————–< IAM Policy > ———————————————————————————————————————————————-

{
    “Version”: “2012-10-17”,
    “Statement”: [
        {
            “Effect”: “Allow”,
            “Action”: [
                “logs:CreateLogGroup”,
                “logs:CreateLogStream”,
                “logs:PutLogEvents”
            ],
            “Resource”: “arn:aws:logs:::”    
  },  
{            
“Effect”: “Allow”
“Action”: [              
“ec2:Start”,
            “ec2:Stop”,              
“ec2:RebootInstances”,            
“ec2:Describe”,
                “ec2:CreateNetworkInterface”,
                “ec2:DescribeNetworkInterfaces”,
                “ec2:DeleteNetworkInterface”
            ],
            “Resource”: “”        
}, 

{                                                                           >>이 항목이 KMS Key를 위한 권한 부여로, IAM ROLE을 create a role을 선택한 경우라도 추가해줘야 하는 항목입니다.            

“Effect”: “Allow”,            
“Action”: [    
“kms:RetireGrant”,  
“kms:CreateGrant”,  
              “kms:ReEncrypt“,             
  “kms:GenerateDataKey*”,
                “kms:Encrypt”,
                “kms:DescribeKey”,
                “kms:Decrypt”
            ],
            “Resource”: [
                “arn:aws:kms:ap-northeast-2:{ACCOUNT ID}:key/{KEY-ARN}”   
            ]
        }
    ]
}


  1. Lambda 의 생성

(1) Create a Lambda 

(1) Runtime : Python 3.9 

(2) Architecture : x86_64

Advanced setting에는 lambda 구현 시 활용할 수 있는 다양한 옵션이 존재하는 데, 그중에서 강조하고 싶은 항목은 “Enable VPC”입니다.

때론 시스템의 보안 조건이 모든 리소스가 통제 가능한 사설망 IP를 활용하도록 지정된 경우가 있습니다.

그 경우 해당 옵션을 활용하면 EC2가 구현되어 있는 VPC , Subnet 에 lambda를 기동시켜서 보안 조건을 충족할 수 있습니다. 

(2) Insert Code

위의 내용을 수행하고 나면 아래와 같이 코드는 없는 케이스 형태의 Lambda가 생성됩니다.  이제 코드를 넣을 때입니다.

——————————–< Lambda Code > —————————————————————————————————————————————
import boto3
import time

##################################################################################################################

#(1) EC2 instances that contain a tag named Scheduled which is set to True

#(2) IF (1) is true, additional Tag is required for value of the Sch-Stop or Sch-Start , following format H:M – example 09:00

#(3) Setup CloudWatch event which will be executed every minute.

#(4) IAM role is required with permission to start and stop EC2 instances and write to CloudWatch logs.

#

#Example EC2 Instance tags:

#

#Schedule : True

#Sch-Start : 08:30

#Sch-Stop : 20:00

################################################################################################################

ec2 = boto3.resource(‘ec2’)
def lambda_handler(event, context)

# Get current time in format H:M
current_time = time.strftime(“%H:%M”)
print(current_time)

# Find all the instances that are tagged with Schedule:True
filters = [{
‘Name’: ‘tag:Schedule’,
‘Values’: [‘True’]

}
]
# Search all the instances which contains schedule filter
instances = ec2.instances.filter(Filters=filters)

stopInstances = []   
startInstances = []   

  # Locate all instances that are tagged to start or stop.
    for instance in instances:

for tag in instance.tags:

            if tag[‘Key’] == ‘Sch-Stop’:

                if tag[‘Value’] == current_time:

                    stopInstances.append(instance.id)

                    pass

                pass

            if tag[‘Key’] == ‘Sch-Start’:

                if tag[‘Value’] == current_time:

                    startInstances.append(instance.id)

                    pass

                pass

            pass

        pass
    
    print(current_time)

#shut down all instances tagged to stop
if len(stopInstances) > 0:
        # perform the shutdown
        stop = ec2.instances.filter(InstanceIds=stopInstances).stop()
        print (stop)
    else:
        print(“No instances has tag for shutdown.”)

    # start instances tagged to stop. 
    if len(startInstances) > 0:
        # perform the start
        start = ec2.instances.filter(InstanceIds=startInstances).start()
        print (start)
    else:
        print(“No instances has tag for start.”)


람다를 적용시킬 수 있는 방식은 람다의 설정항목 중 하나인 “Environment variable”을 활용하는 것이 대표적이나, 이 경우 람다를 작성한 사람이 아닌 일반 사용자의 경우 Tag의 적용된 내용이 무엇인지 가독성이 떨어질 수 있습니다. 

위의 코드는 람다의 Environment variable을 활용하는 것이 아닌, EC2에 부여된 Tag 를 읽어들여서 적용여부를 확인하는 방식으로, Tag에 Schedule : True  가 입력되면 람다의 적용 대상이 되며, Sch-Stop : 08:00 ( 중지하려는 시간) , Sch-Start : 18:00 (시작하려는 시간) 을 입력하면 해당 시간에 EC2가 중지되고 시작됩니다. 

TIPS! – TIme의 기준은?

시간만 입력하면 되는 데, 시간은 어느 기준일까요?  한번 적용해보시고 코드에 담긴 print(current_time) 을 보시면 아실 수 있습니다.
UTC 기준입니다!  따라서 한국 시간 기준 9시간을 뺀 후 입력하셔야 합니다. 

(3) Trigger 구성 

이제 람다에 코드 입력도 했고, IAM Role의 할당도 진행했습니다. 그럼 람다가 언제 수행되어야 하는지 trigger를 정해야 합니다.

위의 코드는 태그에 따라 서버 기동 / 중지 시간을 확인하는 만큼, 람다는 매분마다 수행되어 태그를 확인해야 합니다.  

따라서 trigger는 시간 스케쥴링이 가능한 EventBridge입니다.  Trigger의 등록은 아래 그림과 같이 람다 메뉴에서도 생성할 수 있고, EventBridge 서비스 콘솔에서도 생성할 수 있습니다.

Rule Type은 Schedule expression으로, 매분마다 수행되어야 하는 만큼, rate(1 minute)을 입력합니다. 특징은, 이 Rule type 입력 시 EventBridge 서비스 콘솔의 화면이 조금 더 이해가 용이합니다.

궁금하시면 직접 가서 확인해 보세요! 

위와 같이 입력이 끝나면,  매분마다 람다가 수행되는 것을 Monitoring 화면에서 보실 수 있으며, 아래와 같이 EC2가 정상 종료되어 있는 것을 보실 수 있습니다!

[ 마무리 ]

EC2를 생성했을 때는 다 쓰면 끄면 되니까~라고 생각하여 이런 자동화 절차를 등록하지 않는 경우가 많습니다. 하지만 의외로 많은 실수가 이어지거나 ,잊게 되는 것이 이런 서버 종료 , 시작이며 꼭 그것이 기억나는 때가 월 사용료 지불 때입니다. 꼭 잊지 말고 초반부터 스케줄링을 걸어두세요!!!!! 

챗봇과 대화를 할 수 있어요