최근 전 세계적으로 클라우드 기술이 폭발적으로 성장하면서, 개인과 기업 모두 이를 적극 도입하고 있습니다. 가장 큰 이유 중 하나는 초기 인프라 구축 비용을 크게 줄이고, 필요한 만큼만 유연하게 인프라를 확장하거나 축소할 수 있다는 데 있습니다. 전통적인 온프레미스 환경에서는 서버를 구매/설치/관리하는 데 막대한 비용과 시간이 들었지만, 클라우드에서는 사용한 만큼 과금(Pay-as-you-go) 되는 특성을 통해 한층 탄력적인 운영이 가능합니다.
특히 개발/테스트용 서버는 실제로 업무 시간에만 쓰이는 경우가 많습니다. 그럼에도 별도의 스케줄 없이 사용한다면 불필요한 인프라 비용이 계속 발생하게 됩니다. 이번 글에서는 AWS EventBridge + Lambda를 활용해 특정 태그가 달린 EC2 인스턴스를 업무 시간에만 자동으로 시작(ON) 하고, 퇴근 후나 주말에는 자동으로 중지(OFF) 하는 방법을 소개합니다.
아키텍처

- Event Bridge: 특정 시간에 Lambda 함수를 호출하여 EC2 중지 또는 시작 이벤트를 발생시키는 역할
- Lambda 함수: 트리거에 의해 실제 EC2 중지 또는 시작하는 로직을 수행
- EC2: 중지 또는 시작 대상 서버
동작 흐름
※ 업무 시간은 월-금 09:00 ~ 18:00으로 정의
※ 스케줄링 적용을 원하는 EC2에 태그 정보("Scheduler": "OfficeHours"
)를 미리 설정
EC2 시작
- Event Bridge 규칙을 통해 업무 시작 시간(월-금, 09:00)에 Lambda로 동작(
"action": "start"
)과 태그 정보("Scheduling": "OfficeHours"
)를 전달 - Lambda 함수에서 해당 태그가 달린 EC2 인스턴스 검색 후, StartInstances API 호출하여 일괄 시작
EC2 중지
- Event Bridge 규칙을 통해 퇴근 시간(월-금, 18:00)에 Lambda로 동작(
"action": "stop"
)과 태그 정보("Scheduling": "OfficeHours"
)를 전달 - Lambda 함수에서 해당 태그가 달린 EC2 인스턴스 검색 후, StopInstances API 호출하여 일괄 중지
구성 절차 실습
※ 사전에 EC2는 생성하여 존재한다고 가정합니다.
※ 본 실습 과정에서는 Lambda 함수 런타임 환경은 Python 3.13을 사용하며, 리전은 현재 EC2가 위치하는 리전을 대상으로 합니다.
스케줄링 적용 EC2 태그 설정

해당 EC2 태그에 아래의 Key: Value를 추가합니다.
추후 Lambda 함수 구성 시, 아래의 Key/Value 쌍이 존재하는 EC2 인스턴스를 대상으로만 스케줄링 적용되도록 구성합니다.
- Scheduling: OfficeHours
Lambda 함수 생성

이미지와 같이 AWS Management Console에서 Lambda 함수 생성 화면으로 접속한 후, 아래와 같이 설정합니다.
- 함수 이름: EC2-Scheduler-By-Tag
- 런타임: Python 3.13
- 아키텍처(선택사항): arm64
(기본 값인 x86_64로 진행하셔도 무방하며, arm64의 경우 본 예제에서 구성하는 단순 EC2 스케줄링 구성에는 문제가 없으나, 임의로 코드 변경 시 호환성 이슈가 발생할 수 있습니다.) - 실행 역할: 기본 Lambda 권한을 가진 새 역할 생성
Lambda 함수 권한 추가
Lambda 함수를 통해 EC2를 시작/중지하기 위해서는 Lambda 함수에 할당된 IAM 역할(Role)에 EC2 목록 조회, 시작/중지에 대한 IAM 정책(Policy)을 추가해야 합니다.
Lambda 함수 상단의 구성 – 권한 – 실행 역할 이름을 클릭합니다.

권한 추가 – 인라인 정책 생성을 클릭합니다.

화면 우측 상단의 JSON을 클릭하고, 아래의 정책을 기입합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:StartInstances",
"ec2:StopInstances"
],
"Resource": "*"
}
]
}

아래 이미지와 같이 정책이 추가된 것을 확인할 수 있습니다.

Lambda 코드 소스
import boto3
import json
ec2 = boto3.client('ec2')
def lambda_handler(event, context):
# EventBridge에서 전달받은 파라미터
action = event.get("action") # start 또는 stop
tag_key = event.get("tagKey") # 예: Scheduling
tag_value = event.get("tagValue") # 예: OfficeHours
# 필수 파라미터 유무 확인
if not action or not tag_key or not tag_value:
return "필수 파라미터 누락: action, tagKey, tagValue."
# 특정 태그가 달린 인스턴스 조회
response = ec2.describe_instances(
Filters=[
{
'Name': f'tag:{tag_key}',
'Values': [tag_value]
}
]
)
# 인스턴스 ID 추출
instance_ids = []
for reservation in response['Reservations']:
for instance in reservation['Instances']:
instance_ids.append(instance['InstanceId'])
if not instance_ids:
return f"해당 태그가 구성된 EC2 인스턴스를 찾을 수 없습니다. {tag_key}={tag_value}"
# 액션에 따라 start 또는 stop
if action == "start":
ec2.start_instances(InstanceIds=instance_ids)
return f"EC2 시작됨: {instance_ids}"
elif action == "stop":
ec2.stop_instances(InstanceIds=instance_ids)
return f"EC2 중지됨: {instance_ids}"
else:
return "잘못된 action입니다. 'start' 또는 'stop' 둘 중 하나만 입력 가능합니다."
아래 이미지와 같이 Lambda 코드 작성 후 좌측의 Deploy 버튼을 클릭하여 배포합니다.

Lambda 코드 테스트
작성한 Lambda 함수의 코드가 정상적으로 작동하는지 테스트합니다.
아래와 같이 테스트 이벤트를 작성합니다.
EC2 시작(Start) 테스트
{
"action": "start",
"tagKey": "Scheduling",
"tagValue": "OfficeHours"
}

EC2 시작 테스트 버튼을 클릭하면, 아래와 같이 해당 EC2가 시작된 것을 확인할 수 있습니다.

EC2 중지(Stop) 테스트
{
"action": "stop",
"tagKey": "Scheduling",
"tagValue": "OfficeHours"
}

EC2 중지 테스트 버튼을 클릭하면, 아래와 같이 해당 EC2가 중지된 것을 확인할 수 있습니다.

EventBridge 규칙 추가
Amazon EventBridge 콘솔 – 버스 – 규칙 – 규칙 생성을 클릭합니다.
아래와 같이 이름 및 일정을 정의한 후, 규칙 생성으로 이동을 클릭합니다.
EC2 시작 규칙
다음 이미지와 같이 규칙 세부 정보를 정의합니다.
- 이름: Start-EC2-On-OfficeHours
- 규칙 유형: 일정
- 규칙 생성으로 이동 버튼 클릭

일정 패턴은 cron식을 기반으로 정의합니다.
현재 업무 시간은 한국 시간(KST) 기준 월-금 09:00이며, cron식은 UTC를 기준으로 설정되어야 하므로 다음과 같습니다.
- cron(0 0 ? * MON-FRI *)
아래 이미지와 같이 현지 시간대로 변경하면, 정상적으로 월-금 09:00에 트리거하는 것으로 설정된 것을 확인할 수 있습니다.

- 대상 유형: AWS 서비스
- 대상 선택: Lambda 함수
- 함수: EC2-Scheduler-By-Tag
- 추가 설정
- 입력 대상 구성: 상수(JSON 텍스트)
- JSON으로 상수를 지정
{
"action": "start",
"tagKey": "Scheduling",
"tagValue": "OfficeHours"
}
아래 이미지와 같이 일정 건너뛰기 이후, 규칙 생성 버튼을 클릭합니다.

EC2 중지 규칙
다음 이미지와 같이 규칙 세부 정보를 정의합니다.
- 이름: Stop-EC2-On-OfficeHours
- 규칙 유형: 일정
- 규칙 생성으로 이동 버튼 클릭

일정 패턴은 cron식을 기반으로 정의합니다.
현재 퇴근 시간은 한국 시간(KST) 기준 월-금 18:00이며, cron식은 UTC를 기준으로 설정되어야 하므로 다음과 같습니다.
- cron(0 9 ? * MON-FRI *)
아래 이미지와 같이 현지 시간대로 변경하면, 정상적으로 월-금 18:00에 트리거하는 것으로 설정된 것을 확인할 수 있습니다.

- 대상 유형: AWS 서비스
- 대상 선택: Lambda 함수
- 함수: EC2-Scheduler-By-Tag
- 추가 설정
- 입력 대상 구성: 상수(JSON 텍스트)
- JSON으로 상수를 지정
{
"action": "stop",
"tagKey": "Scheduling",
"tagValue": "OfficeHours"
}
아래 이미지와 같이 일정 건너뛰기 이후, 규칙 생성 버튼을 클릭합니다.

Lambda 함수 확인
다시 Lambda 함수로 돌아와 보면, 아래 이미지와 같이 2개의 트리거가 정상적으로 생성된 것을 확인할 수 있으며, 정상적으로 구성되었다면 업무 시간인 월-금 09:00에 대상 태그가 설정된 EC2가 시작되며, 월-금 18:00에 중지되는 것을 확인할 수 있습니다.

참고 문서
이상으로, 클라우드 환경에서 비용을 절감하기 위한 EC2 스케줄링 방법을 살펴보았습니다.
EventBridge를 이용해 액션(start
/stop
)과 태그 정보를 함께 넘기면, 원하는 시간대에 특정 태그가 달린 인스턴스만 일괄적으로 제어할 수 있어 편리하게 사용할 수 있습니다. 개발/테스트 서버뿐 아니라, 필요한 경우 다양한 업무 시나리오에도 응용해보세요!
NDS는 많은 클라우드 경험을 통해 서비스 도입에 도움을 드릴 수 있습니다.
AWS 관련 문의 사항 또는 클라우드 전문가의 도움을 받고 싶으시다면, 지금 바로 NDS Sales팀으로 연락주시길 바랍니다.
SA 유윤종