python으로 EC2 관리하기

Seokbin·2021년 12월 21일
0
post-thumbnail

1. overview
입사 후 EC2를 이용한 개발, 테스트를 진행하면서 많은 편의성을 느껴 자주 사용하게 되었습니다. 저희 회사는 AWS를 월 200$ 사용할 수 있는 계정을 제공하는데 관리를 제대로 못하다 보니 요금 제한을 넘은 적이 많았습니다. 다행히 회사에서 처리를 해주었지만 인스턴스를 제때 중지를 시켜야 된다는 필요성을 느꼈습니다. 또한 Nvidia A100을 이용한 테스트가 필요해 p4d 타입의 인스턴스를 생성해야 하는데 다음과 같은 에러가 계속 발생하였습니다. 해당 리전에서 인스턴스 생성에 필요한 volume을 할당할 수 없다는 메시지 입니다. 인스턴스를 생성하기 위해서는 같은 리전에 있는 누군가가 volume을 제거해야 하는데 그때가 언제인지 알 수 없어 시간 날 때마다 시도를 해야합니다. 이러한 시도를 반복하다가 너무 귀찮아서 그냥 python으로 While문 돌려서 자동으로 실행시키고 싶다라는 생각이 들어 시작되었습니다. 그 외에도 python라이브러리인 boto3를 이용해 자주 테스트를 진행하면서 편의성을 느껴 이에 대한 기록을 남깁니다.


2. boto3 사용하기

AWS,GCP,Azure 3개의 클라우드 회사를 비교했을 때 개발자가 가장 사용하기 편한 것은 AWS라고 생각합니다. 기존에 3개의 회사에서 제공하는 stroage 서비스인 S3,blob_storage, Cloud Storage 를 통합해 한 화면에서 관리하는 프로그램을 개발한 적이 있는데 개발에 대한 편의성은 AWS가 최고라고 생각합니다. Library,Document,reference 등이 모두 다양하게 있어 개발에 큰 어려움이 있지 않았습니다. boto3를 사용하며 개발에 필요한 기능은 모두 이미 제공하고 있었습니다. 제가 사용한 코드는 다음과 같습니다. 저의 경우 AWS CLI 가 설치되어있어 aws configure을 통해 저의 인스턴스에 대한 인증이 이미 되어있는 상태에서 사용해 코드 상 별도의 Credential 부분이 없습니다. aws cli에서 설정시 $HOME/.aws에 credential이 존재해 boto3에서는 이를 자동으로 읽어옵니다.

import datetime
import time
import boto3
import botocore.exceptions
import smtplib
from email.mime.text import MIMEText

#p4d instance가 생성됬는지 확인
def check_instance_exist(ec2):
    instances = ec2.instances.all()
    ec2_check = False
    for instance in instances:
        inst_type = instance.instance_type
        if inst_type.startswith('p'):
            ec2_check = True
            print(f"ec2 instance(type:{inst_type} is exist")
    return ec2_check

#ec2 중지
def stop_instance(ec2):
    now = datetime.datetime.now()
    if now.hour == 19 and now.minute <=1:
        instances = ec2.instances.filter(Filters=[{
            'Name': 'instance-state-name', 'Values': ['running']}])
        for instance in instances:
            value = instance.tags[0]['Value']
            if value == 'k8s-master' or value.startswith('k8s-worker'):
                print(f'{instance.id} is stopped')
                instance.stop()


if __name__ =="__main__":

    ec2 = boto3.resource('ec2')
    count = 1
    
    while True:
        stop_instance(ec2)
        smtp = smtplib.SMTP('smtp.gmail.com', 587)
        smtp.starttls()
        smtp.login('ID','PASSWORD')
        msg = MIMEText('start')
        msg['Subject'] = 'ec2 instance p4d created'
        msg['To'] = 'mail ID'


        ec2 = boto3.resource('ec2')
        ec2_check = check_instance_exist(ec2)
        count += 1

        if ec2_check:
            print(f'stop process count {count}')
            break
        else:
            try:
                #ec2 생성 시도
                ec2.create_instances(ImageId='ami-007b3d03a35d0b2df',MinCount=1, MaxCount=1,InstanceType='p4d.24xlarge')
                smtp.sendmail('FROM ', 'To', msg.as_string())
    
            except botocore.exceptions.ClientError as e :
                print(e)
                pass
    
            time.sleep(60)

ec2 생성하는 코드의 경우 1분마다 p4d 타입의 인스턴스 생성을 시도합니다. 보통 위의 에러가 발생하기 떄문에 무시하고 계속 반복하도록 예외처리 합니다. 인스턴스가 생성되었는지 확인하는 부분은 인스턴스 전체 목록을 뽑아 타입이 p로 시작하는 것이 있는지 확인합니다. p4d의 경우 굉장히 비싸기 때문에 메일로 알림을 받도록 처리를 했습니다. stop_instance()의 경우 19시를 기준으로 Running 상태에서 k8s-master 이거나 k8s-worker tag를 가진 인스턴스를 중지하도록 합니다. 퇴근시간에 맞춰 자주 사용하는 instance를 중지시킵니다. 다음과 같이 인스턴스가 잘 중지된 것을 알 수 있습니다.


저는 위와 같이 코드를 작성해 실행시켜놓고 사용하고 있습니다. 실행 파일 또한 crontab 등 을 등록해 주기적으로 프로세스가 작동되는 지 확인하거나 좀 더 디테일하게 관리를 할 수 도 있을거 같습니다.클라우드 서비스를 이용하면서 요금에 대한 부분이 굉장히 민감하고 크기 때문에 관리가 잘 필요한 만큼 다음과 같이 안전을 확보하는 것도 좋은 방법이 될 수 있을 거 같습니다.

0개의 댓글