본문 바로가기

MLOps

AWS Serverless 1편

1. Serverless Architecture

서버리스 아키텍처는 개발자가 서버를 관리할 필요 없이 애플리케이션을 구축하고 실행하는 방식이다. "Serverless"라고 해서 서버가 없는 것이 아니다. 애플리케이션은 여전히 서버에서 실행되지만 모든 서버 관리는 AWS가 해준다. 개발자는 애플리케이션의 핵심 기능을 위한 코드 작성에만 집중하게 되고 프로비저닝, 확장 및 유지 등 서버 리소스 관리에는 신경 쓸 필요가 없다. 따라서 서버리스 아키텍처를 사용하면 개발자는 시간과 에너지를 절약하면서 서비스 안정성을 확보할 수 있다.

참고 링크 : https://aws.amazon.com/ko/serverless/ 

서버리스 애플리케이션은 기본적으로 AWS Lambda에서 시작된다. 앞으로 두 편에 걸쳐 AWS Lambda와 AWS API Gateway를 이용하여 기본적인 서버리스 애플리케이션을 작성해볼 것이다.

 

2. AWS Lambda

AWS Lambda는 서버를 프로비저닝 또는 관리하지 않고 코드를 실행할 수 있는 이벤트 중심의 서버리스 컴퓨팅 서비스이다. 개발자가 함수를 작성하고 등록하면 이를 트리거할 때마다 코드가 실행되고 사용료가 지불된다. AWS의 각종 서비스들이 AWS Lambda 함수를 트리거할 수 있고 또 역으로 Lambda 함수로 다른 서비스들에 접근할 수 있기 때문에 Lambda는 AWS에서 범용적으로 쓰인다.

참고 링크 : https://aws.amazon.com/ko/lambda/ 

 

3. AWS API Gateway

AWS API Gateway는 개발자가 API를 손쉽게 생성 및 게시할 수 있도록 하는 완전관리형 서비스다. API는 애플리케이션이 백엔드 서비스의 데이터 혹은 비즈니스 로직에 접근할 수 있는 "정문" 역할을 한다. AWS API Gateway는 실시간 양방향 통신이 가능하도록 하는 RESTful API와 WebSocket API를 지원한다.

참고 링크 : https://aws.amazon.com/ko/api-gateway/ 

 

4. 나만의 애플리케이션 만들기

AWS API Gateway와 Lambda만으로 누구나 손쉽게 애플리케이션을 만들 수 있다. (1편) AWS API Gateway로 RESTful API를 만들고 (2편) AWS Lambda에 애플리케이션 기능을 구현하는 실습을 해보자. 우리의 API는 AWS 외부에서 REST 호출이 가능하고 호출되면 Lambda를 트리거하여 우리가 원하는 기능이 실행될 것이다.

참고로 AWS 콘솔에서 API Gateway와 Lambda를 생성하는 방법도 있지만 많은 경우 회사에서는 코드를 통한 배포를 요구하기 때문에 우리는 코드로 실습할 것이다.

다음은 API Gateway와 Lambda 함수를 생성하기 위한 cloudformation 템플릿 yaml 코드다. 파일 이름을 template.yml이라고 하자. 

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Parameters:
  LogLevel:
    Default: info
    Type: String
    AllowedValues:
      - info
      - warning
      - debug
      - error
  StageName:
    Type: String
    AllowedValues:
      - dev
      - beta
      - prod
            
Resources:
  ApiFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName:
        Fn::Sub: ${StageName}-mlops-api-function
      Handler: lambda_invoke.lambda_handler
      Runtime: python3.7
      CodeUri: s3://your-bucket/serverless/code.zip
      Environment:
        Variables:
          LOG_LEVEL:
            Ref: LogLevel
          STAGE_NAME:
            Ref: StageName
      Timeout: 60
      MemorySize: 768
      Policies:
        - Statement:
          - Sid: PolicyInvokeSageMakerEndpoint
            Effect: Allow
            Action:
              - sagemaker:InvokeEndpoint
              - sagemaker:DescribeEndpoint
            Resource:
              Fn::Sub: arn:aws:sagemaker:${AWS::Region}:${AWS::AccountId}:endpoint/*
  RestApi:
    Type: AWS::Serverless::Api
    Properties:
      Name:
        Fn::Sub: ${StageName}-mlops-api
      StageName:
        Ref: StageName
      EndpointConfiguration:
        Type: PRIVATE
        VPCEndpointIds:
          - vpce-1234567890abcdefg
      DefinitionBody:
        swagger: 2.0
        info:
          title:
            Ref: AWS::StackName
        schemes:
          - https
        paths:
          /{proxy+}:
            x-amazon-apigateway-any-method:
              x-amazon-apigateway-integration:
                type: AWS_PROXY
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ApiFunction.Arn}/invocations
                httpMethod: POST
        x-amazon-apigateway-policy:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Principal: "*"
              Action: execute-api:Invoke
              Resource:
                Fn::Sub: arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:*
  ApiPermissionToLambda:
    Type: AWS::Lambda::Permission
    DependsOn: ApiFunction
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::Sub: ${StageName}-mlops-api-function
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Sub: arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*

 

맨 위의 두 줄은 AWS Serverless Application Model(AWS SAM) 템플릿으로 확장한다는 의미이다.

Resources 아래에 보면 본격적으로 우리의 Lambda "ApiFunction"과 API Gateway "RestApi"의 스펙을 확인할 수 있다.

  • ApiFunction
    • Type : AWS::Serverless::Function으로 AWS SAM에서 AWS Lambda 함수를 의미한다.
    • Properties :
      • Handler : Lambda 함수의 기능을 정의한 파일과 함수 이름을 적어주는 곳이다. 이 부분은 2편에서 구체적으로 다루겠다. 
      • Runtime : Lambda 함수를 실행할 언어를 적어주는 곳이다. 우리는 2편에서 python 3.7로 lambda 함수를 작성할 것이다.
      • CodeUri : s3에 코드를 저장한 위치다. 해당 zip 파일 안에 우리가 작성한 코드가 있을 것이다. 이 부분 역시 2편에서 다시 살펴보자.
      • Environment :
        • Variables : 여기에서 값을 지정한 변수들은 Lambda 함수 안에서 사용할 수 있다.
      • Timeout : 초단위로 Lambda 함수의 최대 실행 시간이다. 본 예제에서는 60으로 지정했기 때문에 Lambda 트리거 후 60초가 지나면 중단된다. 이 Timeout 값은 최대 900까지 가능하기 때문에 Lambda 함수는 최대 15분까지만 실행 가능하다. 이 점을 꼭 주의해야할 필요가 있다. 기본적으로 실행 혹은 대기 시간이 긴 프로그램은 Lambda로 수행하기 부적합하다는 것을 의미한다.
      • MemorySize : 메모리 할당 크기 (MB)
      • Policies : AWS의 타 서비스들에 대한 접근 권한을 선언하는 곳이다. 2편에서 우리는 Lambda로 SageMaker Endpoint에 머신러닝 모델 추론 결과를 요청하는 코드를 작성할 것이기 때문에 SageMaker Endpoint를 Invoke하는 권한을 부여했다.
  • RestApi
    • Type : AWS::Serverless::Api로 AWS SAM에서 AWS API Gateway를 의미한다.
    • Properties :
      • StageName : 배포 단계(ex. dev, prod, beta, ...)를 명시하는 곳이다. 이 부분은 필수다. API Gateway의 host name 뒤에 스테이지 이름이 반드시 붙게 된다.
      • EndpointConfiguration : Public한 api gateway의 경우 이 부분은 생략해도 된다. 하지만 만약 api gateway가 특정 vpc endpoint로만 접근 가능하도록 하고 싶으면 타입을 private으로 지정하고 접근을 허용할 vpc endpoint들의 ID를 적어야 한다. VPC Endpoint ID를 찾기 위해서는 AWS 콘솔에서 "vpc"를 검색하고 들어가서 좌측 바에서 "엔드포인트"를 클릭한다. 그리고 서비스 이름이 "com.amazonaws.ap-northeast-2.execute-api"인 엔드포인트의 ID를 찾는다. VPC 엔드포인트 ID는 "vpce-"로 시작한다.
      • DefinitionBody :
        • paths : 각 url 경로에 어떤 로직을 수행할 것인지 입력하는 곳이다. 예시에서는 proxy integration 방식을 채택했다. 이에 따라 우리의 Lambda 함수 "ApiFunction"에서 각 경로별 수행할 로직을 판별한다.
  • ApiPermissionToLambda : 마지막으로 우리의 API Gateway "RestApi"가 "ApiFunction"을 호출(invoke)할 수 있는 권한을 부여해야 된다. 이 부분을 하지 않으면 분명 Api Gateway에 요청을 보냈는데 아무 로직이 수행되지 않고 메시지도 남지 않아 헤맬 수가 있다.

이제 템플릿을 다 작성했으니 한 번 생성해보자. 우선 template.yml을 s3에 저장해놓자.

aws s3 cp your-local-path/template.yml s3://your-bucket/serverless/template.yml

그 다음 template.yml을 기반으로 cloudformation stack을 생성한다. 배포 단계는 dev라고 하자.

aws cloudformation create-stack \
    --stack-name your-stack-name \
    --template-url https://your-bucket.s3.ap-northeast-2.amazonaws.com/serverless/template.yml \
    --parameters ParameterKey=StageName,ParameterValue=dev \
    --capabilities CAPABILITY_AUTO_EXPAND CAPABILITY_IAM \

콘솔에서 cloudformation을 검색하고 들어가자. 스택이 생성 중인 것이 보일 것이다. 생성 완료 상태가 되면 결과를 확인해볼 때가 된 것이다.

 

5. 결과 확인

콘솔에서 "api gateway"를 검색하고 들어가면 지금껏 생성한 API Gateway의 목록이 보일 것이다. 각 API Gateway마다 ID가 있다. AWS에서는 이 ID들로 같은 계정 내의 서로 다른 API Gateway들을 구분한다.

Public API Gateway

Endpoint configuration을 따로 지정하지 않았거나 public 지정한 경우 다음 url로 요청을 보내면 된다.

  • {your-api-gateway-ID}.execute-api.ap-northeast-2.amazonaws.com/dev/{custom-path}

Private API Gateway

Private로 지정한 경우 허용된 VPC Endpoint를 통해야 한다. 다시 콘솔에서 "vpc"를 검색하고 들어가서 좌측 바에서 "엔드포인트"를 클릭한다. 템플릿에 ID를 적은 엔드포인트를 찾아서 클릭하면 하단에 해당 엔드포인트의 정보를 볼 수 있다. 이 중 "DNS 이름" 밑에서 "vpce-"로 시작하는 호스트 네임을 찾는다. 이를 HOST-NAME이라고 하면 요청은 다음 url로 보내면 된다.

  • {HOST-NAME}/dev/{custom-path}

그리고 다음 헤더를 추가해야된다.

  • x-apigw-api-id : {your-api-gateway-ID}

2편에서는 Lambda에서 머신러닝 모델에 추론 요청을 보내는 코드를 작성해보고 api의 url과 응답이 어떻게 되는지 구체적으로 알아보자.

 

 

 

 

'MLOps' 카테고리의 다른 글

NVIDIA Triton 한 눈에 알아보기  (0) 2023.01.09
AWS Serverless 2편  (1) 2023.01.05
Amazon SageMaker  (0) 2022.04.25
Multi-Armed Bandit with Seldon Core  (0) 2022.02.20
Ensemble with Seldon Core  (0) 2022.02.19