[AWS] 비용 최적화 프로젝트_(2)EC2 기동/정지 스케줄링

이 글의 목적과 커버 범위

  • 스테이징 혹은 테스트 EC2를 안 쓰는 시간에는 잠시 정지하여 비용을 아끼기 위함
  • 이 글은 철저히 AWS 상에서의 문제를 다루며, EC2 위에 어플리케이션 단으로 올라간 프로그램 자동 재시작 명령어는 쓰지 않았음

1. 대상 EC2에 Tag 설정하기

  • 인스턴스 태그에 Key가 AutoStopStart이고 Value가 True인 태그 생성
  • 태그를 이용하여 Lambda에서 스케줄링 작업이 진행되게한다.

    image

2. EventBridge, Lambda로 스케줄링 함수 작성

스케줄링 상세 내용

  • 월~금 저녁 9시 EC2 기동 중지
  • 월~금 오전 6시 EC2 기동 시작
  • 위의 조건으로 토~일은 자연스럽게 기동 중지된 상태

중지 스케줄링

  • 내용 : 월~금 저녁 9시 EC2Stop
  • 중지 스케줄링 함수 Lambda

    import boto3
    import logging
    import os
    from typing import List, Dict, Any
      
    # Logger 설정
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.INFO)
      
    # AWS 리전 설정 (Lambda 실행 리전 자동 감지)
    region = os.environ.get("AWS_REGION", "ap-northeast-2")
    ec2 = boto3.client("ec2", region_name=region)
      
    def ec2_stop() -> None:
        """
        'AutoStopStart' 태그가 'True'로 설정된 모든 실행 중인 EC2 인스턴스를 정지하는 함수
        """
        filters = [
            {"Name": "tag:AutoStopStart", "Values": ["True", "true", "TRUE"]},  # 대소문자 모두 허용
            {"Name": "instance-state-name", "Values": ["running"]}  # 'Running' → 'running'로 통일
        ]
      
        try:
            # 실행 중인 인스턴스 조회
            response = ec2.describe_instances(Filters=filters)
            running_instances: List[str] = []
      
            for reservation in response.get("Reservations", []):
                for instance in reservation.get("Instances", []):
                    running_instances.append(instance["InstanceId"])
      
            logger.info(f"Total running instances found: {len(running_instances)}")
      
            if running_instances:
                ec2.stop_instances(InstanceIds=running_instances)
                logger.info(f"Stopping instances: {running_instances}")
            else:
                logger.info("No running instances found to stop.")
      
        except Exception as e:
            logger.error(f"Error stopping EC2 instances: {str(e)}")
      
    def lambda_handler(event: Dict[str, Any], context: object) -> None:
        """
        AWS Lambda 핸들러 함수
        """
        logger.info("Lambda function started.")
        ec2_stop()
        logger.info("Lambda function execution completed.")
    
  • Lambda 트리거 EventBridge 설정 사항 : Lambda 기본 시간은 UTC이므로 +09:00 하여 cron job 작성한다.

      cron(0 12 ? * 2-6 *)
    

기동 스케줄링

  • 내용 : 월~금 오전 6시 EC2 기동 시작
  • 중지 스케줄링 함수 Lambda

    import boto3
    import logging
    import os
    from typing import List, Dict, Any
      
    # Logger 설정
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.INFO)
      
    # AWS 리전 설정 (Lambda 실행 리전 자동 감지)
    region = os.environ.get("AWS_REGION", "ap-northeast-2")
    ec2 = boto3.client("ec2", region_name=region)
      
    def ec2_start() -> None:
        """
        'AutoStopStart' 태그가 'True'로 설정된 모든 정지된 EC2 인스턴스를 시작하는 함수
        """
        filters = [
            {"Name": "tag:AutoStopStart", "Values": ["True", "true", "TRUE"]},  # 대소문자 모두 허용
            {"Name": "instance-state-name", "Values": ["stopped"]}  # 'Stopped' → 'stopped'로 통일
        ]
      
        try:
            # 정지된 인스턴스 조회
            response = ec2.describe_instances(Filters=filters)
            stopped_instances: List[str] = []
      
            for reservation in response.get("Reservations", []):
                for instance in reservation.get("Instances", []):
                    stopped_instances.append(instance["InstanceId"])
      
            logger.info(f"Total stopped instances found: {len(stopped_instances)}")
      
            if stopped_instances:
                ec2.start_instances(InstanceIds=stopped_instances)
                logger.info(f"Starting instances: {stopped_instances}")
            else:
                logger.info("No stopped instances found to start.")
      
        except Exception as e:
            logger.error(f"Error starting EC2 instances: {str(e)}")
      
    def lambda_handler(event: Dict[str, Any], context: object) -> None:
        """
        AWS Lambda 핸들러 함수
        """
        logger.info("Lambda function started.")
        ec2_start()
        logger.info("Lambda function execution completed.")
    
    
  • Lambda 트리거 EventBridge 설정 사항 : Lambda 기본 시간은 UTC이므로 +09:00 하여 cron job 작성한다.

      cron(0 21 ? * 1-5 *)
    

비용 절감 결과

  • 비용 절감 예상안은 월 20만원 아끼는 건데, 청구서 나오면 다시 돌아오겠다..