Browsing Tag

cron

NCP

[NCP] Cloud Function으로 원하는 시간대에 서버를 시작하고 중지하자

안녕하세요. ManVSCloud 김수현입니다.

최근에는 Shell Script가 아닌 Python을 사용해보며 조금씩 개발 영역까지 도전해보는 시간을 갖고 있습니다.

Shell Script로 제가 필요한 것들만 만들어봤지 정작 제대로된 개발 공부를 해본 적이 없어서 처음 Python은 어떻게 시작해야하나 막막했는데 아무래도 필요한 것을 직접 만들면서 배우는 게 나을 것같다고 판단하여 네이버 클라우드 플랫폼의 Cloud Function으로 서버를 시작하고 중지하는 것부터 시작해보자고 생각했습니다.

오늘은 네이버 클라우드의 Serverless 상품인 Cloud Function을 이용하여 서버를 시작하고 중지하는 방법을 포스팅 할 것입니다.


Cloud Function

먼저 간단하게 Cloud Function에 대해 소개해보려합니다.
Cloud Function은 네이버 클라우드 플랫폼에서 Serverless 서비스입니다.

AWS에서는 Lambda, Azure의 Functions와 같은 서비스라고 볼 수 있는데 이러한 서버리스 컴퓨팅을 사용함으로 관리에 대한 부담감으로부터 벗어날 수 있고 코드가 동작한 실행 단위만큼만 비용이 발생하기때문에 비용 절감까지 노려볼 수 있습니다.

Cloud Function을 구독하여 상품을 이용하게 되면 크게 Dashboard/Action/Trigger 카테고리로 분리하여 관리할 수 있습니다.

  • Dashboard : Cloud Fuction의 상태, 기간별 실행, 월간 사용량, 실행 비율, 기간별 액션 실행 결과를 직관적이며 가시적으로 확인할 수 있습니다.
    (실행 결과에 대한 로그, 실행 시간 등 다양하게 확인 가능)
  • Action : Action은 Package 단위로 관리가 가능합니다. 여러 Action을 생성할 때 공통적으로 사용되는 파라미터가 있다면 하나의 패키지로 묶어 관리하는 방법을 사용할 수 있습니다.
    Action은 실질적으로 실행되는 코드, 런타임 정보 등을 생성 및 설정할 수 있습니다.
  • Trigger : Trigger의 종류는 다양합니다. Basic, Cron, GitHub 이벤트, Cloud Insight, Object Storage, Cloud IoT Core이 존재합니다. 대표적으로 Cron 트리거를 사용하게 될 경우 연결된 Action은 Cron에 설정한 시간에 맞춰서 코드가 동작하고 Cloud Insight 트리거를 사용하게 되면 Cloud Insight의 Event Rule 알림에 맞춰서 트리거가 동작하게 됩니다.

다만 Cloud Function은 현재까지 KR-2 Zone만 사용 가능한 상태라 KR-1 지원에 대한 부분은 조금 더 시간이 필요할 것으로 보입니다.


Trigger

자, 이제 Cloud Function으로 서버를 원하는 시간대에 시작하고 중지합시다.
먼저 Cloud Function에서 사용할 Private Subnet을 KR-2 Zone에 하나 생성해주세요.

[Compute] – [Cloud Functions]에서 먼저 상품 사용을 하도록 합시다.
그리고 Trigger를 생성할 것입니다.
(이름이나 설명 부분은 원하는 대로 써주세요.)

1) 트리거 종류 : cron
2) Cron 정보 설정 : 원하는 시간대로 설정

ex) 월~금(평일) 오전 8시 30분

Trigger 생성은 총 2번 해주어야합니다.

서버가 시작할 시간의 cron, 서버가 중지될 시간의 cron 둘 다 만들어줍시다.


Action

※ Package 생성


Action도 Cron과 동일하게 서버가 시작하는 Action, 종료되는 Action 2가지를 생성하는데 두 Action간에 공통적으로 사용되는 디폴트 파라미터가 존재하므로 Package를 먼저 생성해줄 것입니다.

{"API_URL":"https://ncloud.apigw.ntruss.com","NCLOUD_ACCESS_KEY":"-","NCLOUD_SECRET_KEY":"-","REGION":"KR","SRVLIST":"&serverInstanceNoList.1=11111111"}

API_URL : 말 그대로 API의 URL을 입력하는 곳입니다.
NCLOUD_ACCESS_KEY : 네이버 클라우드 플랫폼의 ACCESS KEY를 입력하는 곳입니다.
NCLOUD_SECRET_KEY : 네이버 클라우드 플랫폼의 SECRET KEY를 입력하는 곳입니다.
REGION : REGION이 입력되는 곳입니다.
SRVLIST : 서버 리스트=서버의 인스턴스 ID가 입력되는 곳입니다.

중요한 포인트1. 민간존, 금융존, 공공존의 API URL이 다르니 API 가이드를 참고해서 사용하는 환경에 맞는 URL로 변경해주어야합니다.

2. ACCESS KEY, SECRET KEY를 넣어주는 곳은 왠만하면 Sub Account에서 서버 시작, 중지에 대한 권한만 존재하는 계정을 생성하여 최소 권한만 부여된 계정의 ACCESS KEY, SECRET KEY를 추가해줍시다.

3. REGION 역시 민간존, 금융존, 공공존마다 코드가 다릅니다. 예를들어 민간존은 KR인데 금융존에서는 FKR이니 이 부분 역시 잘 확인하여 변경이 필요합니다.

4. 서버의 인스턴스 ID는 네이버 클라우드 콘솔의 [Server] – 상세 정보에서도 확인할 수 있습니다. 무엇보다 서버 시작/중지 대상이 한 대가 아니라 다수의 서버가 존재할 경우 SRVLIST에 다음과 같이 입력해줄 수 있습니다.

1) &를 이용하여 serverInstanceNoList 추가
2) serverInstanceNoList다음 .1 .2 .3 과 같은 방식으로 구분

"SRVLIST":"&serverInstanceNoList.1=11111111&serverInstanceNoList.2=22222222&serverInstanceNoList.3=33333333"

※ Action 생성

Action 생성은 서버를 시작해주는 Action 1개, 중지를 해주는 Action 1개 총 2개를 생성할 것입니다.
(이름, 설명, VPC, Subnet 설정과 같은 부분은 생략했습니다.)

  • 서버 시작

1) 트리거 종류 : cron – 위에서 생성한 서버 시작용 cron 선택
2) 패키지 : 위에서 생성한 Package 선택
3) 언어 : Python 3.7

4) 코드 :

import hashlib
import hmac
import base64
import requests
import time
import json


def main(args):
    
    access_key = args["NCLOUD_ACCESS_KEY"]
    secret_key = args["NCLOUD_SECRET_KEY"]
    REGION = args["REGION"]
    api_server = args["API_URL"]
    api_uri = args["API_URI"]
    server_list = args["SRVLIST"]

    timestamp = int(time.time() * 1000)
    timestamp = str(timestamp)

    secret_key = bytes(secret_key, 'UTF-8')

    method = "GET"

    uri = api_uri + "?regionCode=" + REGION + server_list + "&responseFormatType=json"

    message = method + " " + uri + "\n" + timestamp + "\n" + access_key
    message = bytes(message, 'UTF-8')
    signingKey = base64.b64encode(hmac.new(secret_key, message, digestmod=hashlib.sha256).digest())
    
    http_header = {
            'x-ncp-apigw-signature-v2': signingKey,
            'x-ncp-apigw-timestamp': timestamp,
            'x-ncp-iam-access-key': access_key
            }


    response = requests.get(api_server + uri, headers=http_header)

    data = json.loads(response.text)

    return data

5) 디폴트 파라미터 :

{"API_URI":"/vserver/v2/startServerInstances"}

서버 시작/중지의 디폴트 파라미터 API_URI는 다릅니다.
꼭 확인해서 넣어주세요.

  • 서버 중지

1) 트리거 종류 : cron – 위에서 생성한 서버 중지용 cron 선택
2) 패키지 : 위에서 생성한 Package 선택
3) 언어 : Python 3.7

4) 코드 : (위 서버 시작 부분 코드와 동일)

import hashlib
import hmac
import base64
import requests
import time
import json


def main(args):

    access_key = args["NCLOUD_ACCESS_KEY"]
    secret_key = args["NCLOUD_SECRET_KEY"]
    REGION = args["REGION"]
    api_server = args["API_URL"]
    api_uri = args["API_URI"]
    server_list = args["SRVLIST"]

    timestamp = int(time.time() * 1000)
    timestamp = str(timestamp)

    secret_key = bytes(secret_key, 'UTF-8')

    method = "GET"

    uri = api_uri + "?regionCode=" + REGION + server_list + "&responseFormatType=json"

    message = method + " " + uri + "\n" + timestamp + "\n" + access_key
    message = bytes(message, 'UTF-8')
    signingKey = base64.b64encode(hmac.new(secret_key, message, digestmod=hashlib.sha256).digest())
    
    http_header = {
            'x-ncp-apigw-signature-v2': signingKey,
            'x-ncp-apigw-timestamp': timestamp,
            'x-ncp-iam-access-key': access_key
            }


    response = requests.get(api_server + uri, headers=http_header)

    data = json.loads(response.text)

    return data

5) 디폴트 파라미터 :

{"API_URI":"/vserver/v2/stopServerInstances"}

서버 시작과 중지의 코드는 동일합니다.
두 Action은 생성 시 추가한 디폴트 파라미터 API_URI의 차이로 인해 다르게 동작합니다.

여기까지 잘 따라왔다면 Cloud Function을 이용하여 서버 시작과 중지는 끝입니다.
이제 Trigger에서 생성한 cron의 시간대에 맞춰서 서버가 시작되고 중지될 것입니다.

또한 생성한 Action을 클릭하여 [실행] 버튼을 클릭해 강제로 해당 Action을 실행할 수도 있으며 실행 후 [모니터링] 탭에서 정상적으로 실행되었는지 실패했다면 자세히 보기를 통해 어떠한 이유로 실패했는지 등을 확인할 수도 있습니다.


Personal Comments

웹 서비스의 경우에는 24/7 즉, 하루도 빠짐없이 운영되는 경우가 많지만 그렇지 않은 서버들도 존재합니다.

예를 들어 특정 시간대에 배치 파일이 실행되기만 하는 서버가 있다면 굳이 우리는 이 서버를 하루종일 실행해두어야 할까? 상당히 비용 낭비입니다.

특정 작업이 진행되어야하는 시간 전에 잠시 서버가 시작되었다가 작업 시간이 끝났을 때 서버가 중지된다면 서버가 중지되어있는 시간동안에는 블록 스토리지에 대한 비용만 발생하기에 비용 절감으로 이어지게 됩니다.

클라우드를 도입하면 비용이 절감이 된다는 말을 듣고 클라우드를 사용하는 케이스는 많이 보았지만 실제로 비용을 절감하는 사례는 크게 보지 못했습니다.

최근 [AWS 비용 최적화 바이블]이라는 책이 출간되고 FinOps에 더 많은 관심이 모이는 것같습니다. 위 책을 정독하며 네이버 클라우드에서는 어떻게 비용을 절감할 수 있을지 고민을 해보기도 합니다.

아직 네이버 클라우드에서는 SI, RI, SP과 같은 선택지가 없기때문에 다른 방법으로 비용을 줄일 수 있는 방법을 고려해보아야할 것입니다.
(물론 영업 담당자와 연락해서 장기 계약 등의 보이지 않는 선택지가 있긴하다?)
(+ 무엇보다 국내 클라우드라 환율에 대한 부담이 없다는 건 최고…)

아무튼 개발 영역도 도전해보게 된 거 Python으로 이것저것 만들어봐야겠습니다.

긴 글 읽어주셔서 감사합니다.