내 소소한..

AWS에서 람다(Lambda)로 EC2 시작/종료하기 본문

IT/AWS

AWS에서 람다(Lambda)로 EC2 시작/종료하기

쿠르릉 2021. 1. 22. 23:22

이전 글(2021/01/21 - [IT/AWS] - AWS에서 람다(Lambda)로 커스텀 VPC에 EC2 인스턴스 추가하기)에서는 기본 VPC가 아닌 서브넷에 EC2 인스턴스를 추가로 띄우는 방법을 알아봤다.

마찬가지로 람다(lambda) 스크립트로 EC2를 시작하거나 종료할 수 있다.

또, 이렇게 생성한 람다 스크립트는 정해진 시간에 실행할 수 있게 설정해서 필요한 시간대에만 EC2로 서비스를 할 수도 있다.

 

목표

  • 현재 계정 내 EC2 목록을 확인해서
  • 정지된 인스턴스는 시작하고
  • 시작된 인스턴스는 정지한다
  • 만든 람다 함수를 시간 이벤트를 발생해 자동 실행되게 한다.

 

주의: 아래 예제를 따라하면 현재 서비스 중인 EC2를 종료하거나 시작할 수 있다. 아래 함수는 테스트로만 사용해야 한다.

 

IAM 정책/역할 생성

lambda로 EC2를 시작하거나 종료하려면, 람다에게 부여할 역할에 EC2 시작과 종료가 추가가 가능하게 해야 한다. 바로 이어서 람다 함수를 만들 때 새로 만든 정책이 부여된 역할을 할당할 것이다.

정책 생성

먼저 IAM 관리 콘솔로 이동해서 왼쪽 메뉴에서 "정책"을 선택한다.

정책 목록이 나타나면 왼쪽 상단의  정책 생성  버튼을 클릭한다.

새 정책 생성하기

그 뒤 굳이 시각적 편집기를 뒤로 하고.. JSON 탭을 선택한 뒤 아래 내용을 넣는다.

{
  "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:DescribeInstanceStatus"
      ],
      "Resource": "*"
    }
  ]
}

내용인즉슨, 첫 번째 Statement는 CloudWatch Log에 로그를 쌓을 수 있는 권한을 허용하는 것이며, 다음 절은 코드 그대로 ec2를 시작하고 종료하는 것이다.

"ec2:DescribeInstanceStatus"는 아마존이 제공하는 예제 대비 추가된 부분이다. 람다 스크립트에서 EC2 목록을 조회해서 각 EC2를 종료하고 시작하려면 현재 존재하는 EC2 정보를 조회할 수 있어야 한다.

이어서  정책 검토  버튼을 누른다.

정책 검토

정책에 이름을 부여해야 한다. 적절히 부여하자. 그 뒤  정책 생성  버튼을 클릭하면 잠시 후 정책이 생성된다.

 

역할 생성

정책을 만들었는데 왜 역할을 만들어야 하는가 처음엔 혼동스럽다.

그러나.. 역할이 여러 정책을 포함한다고 생각하면 이해하기 쉽다.

또한 람다 함수가 특정 역할을 갖도록 할 수 있다. (반면 정책 단위 부여는 불가능하다.)

왼쪽 메뉴에서 "역할" 항목을 선택한 뒤, 역할 관리 화면의  역할 만들기  버튼을 클릭한다.

새 역할 만들기

사용 사례에서 Lambda를 선택하고  다음: 권한  버튼을 클릭한다.

앞서 만든 정책을 연결

앞서 만든 정책을 검색해서 연결한다. 그 뒤  다음: 태그  버튼을 클릭한다.

태그는 내용을 별도로 추가하지 않아도 되므로  다음: 검토  버튼을 클릭해 검토 단계로 넘어간다.

역할 이름 입력

역할 이름을 적당히 넣고  역할 만들기  버튼을 클릭하면 권한이 생성된다.

 

람다 함수 만들기

함수 생성

이제 본격적으로 람다 함수를 만들 차례이다.

람다 관리 콘솔에서  함수 생성  함수 생성  버튼을 클릭한다. (관리 콘솔 진입 후 바로 함수 화면이 나오지 않는다면 왼쪽 메뉴에서 "함수"를 선택한다.)

새 함수 생성하기

새로운 람다 함수를 생성한다.

  • 이름을 적당히 짓고(예제는 실행중인 EC2는 내리고 정지된 EC2는 실행하므로 ToggleEC2라고 이름을 지었다.)
  • 런타임으로 Python3.8을 선택한다.
  • 기본 실행 역할 변경을 펼쳐 기존 역할 사용을 체크하고
  • 기본 역할로 앞서 정책/역할에서 만든 역할 이름을 선택한다. (예제에서는 LambdaEC2StartStop)

그 뒤  함수 생성  버튼을 클릭하면 막바로 람다 함수가 생성되고, 코드 편집 화면으로 넘어간다.

코드 편집

코드 내용으로 아래 파이썬 코드를 채워 넣는다.

import json
import boto3
from pprint import pprint

def lambda_handler(event, context):
    client = boto3.client("ec2")
    status = client.describe_instance_status(IncludeAllInstances = True)
    
    #pprint(status)
    instanceStatus = "none";
    for i in status["InstanceStatuses"]:
        #print("AvailabilityZone :", i["AvailabilityZone"])
        #print("InstanceId :", i["InstanceId"])
        #print("InstanceState :", i["InstanceState"])
        #print("InstanceStatus", i["InstanceStatus"])
        if i["InstanceState"]["Code"] == 80:
            client.start_instances(InstanceIds=[i["InstanceId"]])
            print("인스턴스 시작 요청. ID : " + i["InstanceId"]);
            instanceStatus = "started"
        elif i["InstanceState"]["Code"] == 16:
            client.stop_instances(InstanceIds=[i["InstanceId"]])
            print("인스턴스 정지 요청. ID : " + i["InstanceId"]);
            instanceStatus = "stopped"
    return {
        'status': instanceStatus
    }

코드 내용은

  • 전체 ec2 목록을 가져와서(describe_instance_status 함수) 
  • 각 인스턴스 별로
  • 상태코드가 80(정지)이면 인스턴스를 시작하고(start_instances 함수)
  • 상태코드가 16(시작)이면 인스턴스를 정지한다(stop_instances 함수)

의도적으로 주석을 삭제하지 않고 남겨 놓았다. 실행 중 status 변수에 들어있는 값이 궁금할 때는 # 주석을 풀면서 확인해보면 명확해진다.

 

Deploy 및 테스트

편집기 위의 Deploy 버튼을 눌러 코드를 배포한다.

배포 완료

배포가 완료되면 위와 같은 메시지가 편집기 오른쪽 상단에 나타난다.

이제 테스트를 할 차례이다. 매번 그렇지만 처음으로 Test 버튼을 누르면 테스트에 사용할 데이터 셋을 생성하는 팝업이 나타난다.

테스트 데이터 만들기

따로 테스트 데이터가 필요하지 않으므로 내용을 비워서 {}로 채우고 생성 버튼을 클릭하면 팝업이 닫힌다.

아직 테스트가 실행된게 아니다.

다시 Test 버튼을 클릭한다.

실행 결과

정지돼 있던 인스턴스에 시작 요청이 날아갔다. EC2 콘솔에 가서 인스턴스를 확인해보면 가동된 것을 확인할 수 있을 것이다. 만약 EC2가 가동중이었다면 "인스턴스 정지 요청"이 대신 나타나고 해당 인스턴스가 정지된다.

다시 한번 Test 버튼을 클릭하면 이번에는 시작된 인스턴스에 정지 요청이 날아간다.

인스턴스가 여러개라면 호출이 여러번 이뤄지는 것을 확인할 수 있을 것이다.

 

스케줄 걸기

이제 함수는 정상 작동하지만, 자동화되지 않는다면 함수가 쓸모 없을것이다. (EC2 관리 콘솔에서 내리고 올리면 되니..)

스케줄은 CloudWatch에서 이벤트를 발생시켜 걸 수 있다.

(마치 유닉스/리눅스 환경에서 cron을 사용하는 것과 유사하다. 윈도우라면 윈도우 스케줄러..)

CloudWatch 관리 콘솔 왼쪽 메뉴에서 "이벤트>규칙"을 선택한다.

규칙 만들기

규칙 생성 버튼을 눌러 규칙 생성 화면으로 이동한다.

규칙 정의

이벤트 규칙 내용을 입력한다.

  • 먼저 일정을 선택하고
  • Cron 표현식을 클릭한 뒤 실행할 스케줄을 입력한다. 위 내용은 매 시 52,55분에 해당 이벤트를 발생하는 것이다. cron 표현식은 아래 "자세히 알아보십시오"를 누르거나 검색해본다.
  • 대상으로 Lambda 함수를 선택하고(기본임) 앞서 만든 함수를 지정한다.

그 뒤 세부 정보 구성 버튼을 클릭해 다음 화면으로 이동한다.

 

함수 이름 입력

함수 이름을 넣고 규칙 생성 버튼을 클릭하면 규칙이 생성된다.

이제 매 시 52분, 55분에 앞서 만든 람다 함수가 호출된다.

 

호출 여부 및 실행 결과 확인

시간에 맞춰 이벤트가 호출됐는지는 직접 해당 시간에 EC2 관리콘솔에서 확인할 수 있다.

좀 더 세련된 방법은 CloudWatch 로그를 확인하는 것이다.

CloudWatch 관리 콘솔 왼쪽 메뉴에서 "로그" > "로그 그룹"을 선택한다.

로그 그룹 조회

로그 그룹에는 람다 함수의 실행 이력이 남는 로그 그룹이 이미 생성돼 있다. 로그 그룹을 클릭한다.

로그 스트림 확인

로그 스트림에는 지금까지 함수를 실행한 실행 결과가 목록에 나타나 있다. 적절히 시간 단위로 잘라서 로그 스트림을 만든 듯 하다. 아래 로그 스트림은 람다 함수를 만들면서 테스트했을 때의 기록이고 위의 빨간 네모는 CloudWatch 이벤트로 52분, 55분에 실행한 기록이다.

로그 스트림을 클릭하자.

이벤트 로그 확인

52분과 55분에 예정대로 이벤트가 발생돼 람다 함수가 실행됐음을 알 수 있다.

이처럼 이벤트를 사용하면 간단한 스케줄러를 사용하는 업무를 AWS 내에서 구현할 수 있다.

'IT > AWS' 카테고리의 다른 글

AWS에서 람다(Lambda)로 커스텀 VPC에 EC2 인스턴스 추가하기  (0) 2021.01.21
Comments