'데이터 엔지니어'로 성장하기

정리하는 걸 좋아하고, 남이 읽으면 더 좋아함

AI/MLOps

데이터 잡부의 MLOps도전기 (4) - 모델 배포를 위해 FaaS를 실행해보자_Nuclio

MightyTedKim 2024. 4. 28. 23:45
728x90
반응형

Model의 동적 배포를 위해서, FaaS를 도입한 이야기를 정리하는 중입니다.
nuclio 기본 개념을 더 설명해야할 것 같아서 이번 글은 기초를 설명합니다
 

글의 구조는 아래와 같습니다.

  1. Nuclio 설치 방법
  2. Nuclio 실행 방법 - python hello world
  3. Nuclio 실행 방법 - vision - facebook (Segmenation Anyting Model)

글의 타깃 독자는 아래와 같습니다.

  1. Nuclio 설치가 궁금하신 분
  2. Nuclio hello world가  궁금하신 분

지난 포스팅에서는 아래 3가지를 적었고

  1. Vision MLOps 프로젝트 투입: https://mightytedkim.tistory.com/205
  2. 라벨링 툴로 CVAT을 선택한 이유: https://mightytedkim.tistory.com/206
  3. 모델 배포를 위해 FaaS를 도입한 이유: https://mightytedkim.tistory.com/209

이번에는 `Nuclio'를 코드를 설치부터 적용까지 기초를 정리하려고 해요.


1. Nuclio 설치 방법

설치 방법은 엄청 간단해요. 저희는 hello world니까, docker로 설치해볼게요
 

https://github.com/nuclio/nuclio

명령어를 줄바꿈해서 보면 특별한게 없지만, 에러가 있어요.
 
조심 포인트
1.  docker.sock 의 경우 user 권한을 줘야해요 (sudo usermod -aG docker $USER)
2.  volume mount를 삭제해줘요 docker vesion에 따라 실행이 안될 수 있따고 해요 (https://github.com/nuclio/nuclio/issues/3202)

docker run 
--publish 18070:8070   
--volume /var/run/docker.sock:/var/run/docker.sock  
--name nuclio-dashboard 
quay.io/nuclio/dashboard:stable-amd64

 
실행하면 이렇게 나와요 (2개의 container가 뜨지만 storage는 무시해주세요.)

$ docker ps | grep nuclio
51a1c06fe841   quay.io/nuclio/dashboard:stable-amd64   "/docker-entrypoint.…"   5 minutes ago    Up 6 seconds (healthy)    80/tcp, 0.0.0.0:18070->8070/tcp, :::18070->8070/tcp nuclio-dashboard
6c941d441c66   gcr.io/iguazio/alpine:3.17              "/bin/sh -c '/bin/sl…"   8 minutes ago    Up 8 minutes- nuclio-local-storage-reader

 
dashboard가 18070에 뜨는 것을 확인할 수 있습니다. 옆에 namespace는 k8s 용이니까 가볍게 무시해줍니다.
 

 
설치는 이게 끝입니다. 쉽죠?

2. Nuclio 실습

hello world는 여러개를 해볼게요

2-1.  WEB UI로 Python api 만들기

Hello world 해보겠습니다. 프로젝트를 만들어줘요

 
new funcion을 클릭하면 검색이 있는데, hello world니까 hello 라고 검색해서 python을 선택해요

 
그대로 deploy 버튼을 클릭합니다.

 
초반에 빌드하는데 좀 시간이 걸려요. base 이미지를 pull해야하거든요

 

실제 완료되면 초록색으로 변해요

 

끝입니다. 쉽죠?

 


2-2.  WEB UI로 Python api 만들고 테스트하기

이제 실제 상황에서 어떻게 사용할지 알아볼게요!

옆팀에서 갑자기 간단한 API를 만들어달라고 하네요.

어렵진 않죠.. 어렵진... 휴..

상황

  1. 급하게 api 샘플이 필요함
  2. post body에 특정 key값 필수
    {'sample': 'sample_data_for_test'} 

조치 

  • nuclio dashboard 들어가서 python 코드 작성 끝!

  • 예전이었다면, fastapi로 코드 짜서 배포하며 테스트 했을 거에요.

테스트

  • python으로 실행해봅니다. port는 ui 우측 상단에서 확인할 수 있어요
  • k8s를 위한 FaaS라서 port 자동 할당도 32000번대입니다.
  • 당연히 직접 할당할 수도 있고, ingress 등을 통할 수 있어요
import requests
import json
nuclio_endpoint_url = f"http://192.168.219.249:32769"
data = {'sample': 'mightytedkim'}
response = requests.post(nuclio_endpoint_url,
                         data=json.dumps(data),
                         headers={"Content-Type": "application/json"}
            )
if response.status_code == 200:
    result = response.text  # Assuming the function returns a response
    print(f"{result}")
else:
    print(f"Error: {response.status_code}, {response.text}")

 
결과는 아래처럼 나와요 event.body['sample']로 데이터를 가져오면 되겠군요

2-3.  command line으로 모델 배포하기 (nuctl)

여기서부터 조금 어려워져요. nuctl이라는 cli를 사용해야하거든요

cli 라니

nuctl은  Nuclio's command-line interface (CLI) 의 약자에요. 

설치 방법은 아래와 같아요

curl -s https://api.github.com/repos/nuclio/nuclio/releases/latest \
			| grep -i "browser_download_url.*nuctl.*$(uname)" \
			| cut -d : -f 2,3 \
			| tr -d \" \
			| wget -O nuctl -qi - && chmod +x nuctl

 

build와 deploy 등의 커맨드가 있는데, 빠른 hello world를 위해 스킵하겠습니다.

 

CVAT의 github에 좋은 예시들이 많거든요.

https://github.com/cvat-ai/cvat/blob/develop/serverless/deploy_cpu.sh

 

cvat/serverless/deploy_cpu.sh at develop · cvat-ai/cvat

Annotate better with CVAT, the industry-leading data engine for machine learning. Used and trusted by teams at any scale, for data of any scale. - cvat-ai/cvat

github.com

그래도 간단하게 설명하면, web ui에서 저희가 했던 걸 아래처럼 할 수 있어요

  1. 프로젝트 생성: nuctl create project cvat --platform local
  2. 함수 배포: nuctl deploy --project-name cvat --path "./path" \ --file "./path.yaml" --platform local

설정은 function.yaml, 코드는 직접 main.py 로 구성되고 폴더 구조로는 아래와 같아요

점점 더 어려워지죠.. 조금만 참아요 거의 다 왔어요.

function.yaml에는 k8s deployment yaml과 거의 비슷해요

metadata, spec

main.py는 위의 spec.handler에 있는 값이에요

# Facebook의 Segment Anything Model의 코드 예시에요
import json
import base64
from PIL import Image
import io
from model_handler import ModelHandler

def init_context(context):
    context.logger.info("Init context...  0%")
    model = ModelHandler()
    context.user_data.model = model
    context.logger.info("Init context...100%")

def handler(context, event):
    context.logger.info("call handler")
    data = event.body
    pos_points = data["pos_points"]
    neg_points = data["neg_points"]
    buf = io.BytesIO(base64.b64decode(data["image"]))
    image = Image.open(buf)
    image = image.convert("RGB")  #  to make sure image comes in RGB
    mask, polygon = context.user_data.model.handle(image, pos_points, neg_points)
    return context.Response(body=json.dumps({
            'points': polygon,
            'mask': mask.tolist(),
        }),
        headers={},
        content_type='application/json',
        status_code=200
    )

 

nuctl을 직접 이해하고 실행하는 것은 러닝커브가 있으니까, 오픈소스 CVAT 의 serverless 폴더를 참고할게요.

 $ git clone https://github.com/cvat-ai/cvat/blob/develop/serverless/deploy_cpu.sh 

 $ cd serverless 

 $ ./deploy_cpu.sh ./pytorch/facebookresearch/sam/

 

이제 Facebook의 Segmentation Anythin Model을 배포했습니다ㅎ

 

다음 글은 MLOPS 구성을 위해, API를 이용해 Nuclio를 사용한 사례를 설명하도록 할게요

참고

https://github.com/cvat-ai/cvat/tree/develop/serverless
https://github.com/nuclio/nuclio
 

728x90
반응형