Programming/Others

BentoML로 모델 서빙하기(우당탕탕 ver.)| BentoML, Docker, k8s, Prometheus 그리고 Grafana

어쩌다통계 2023. 4. 4. 21:32
728x90

이 글이 도움 되셨다면 광고 클릭 부탁드립니다 : )

 

이번 포스트에서는 실제 데이터를 가지고 모델 학습-배포하는 전체 과정을 차근차근 실습해보려고 합니다.

간단하게 보면, 모델학습 -> BentoML로 모델 저장/도커 이미지 생성 -> k8s에 배포 -> Prometheus&Grafana로 모니터링 순으로 진행해 보겠습니다.

 

BentoML로 모델 서빙 전체 Flow

 


0. 준비물

아래 모든 실습 과정은 Virtual Box에서 우분투 이미지로 구축한 리눅스 터미널에서 진행하였습니다.

  • 리눅스 환경
  • docker : containerization(컨테이너화)을 위한 도구
  • k8s : contatiner orchestration을 위한 도구
    • minikube v.1.22.0 : local 환경에서 쿠버네티스를 학습하고 개발하는데 활용하는 것에 포커싱한 로컬용 쿠버네티스
    • kubectl v1.22.1 : kubernetes cluster (server) 에 요청을 간편하게 보내기 위해서 널리 사용되는 client 툴
  • BentoML : 모델을 쉽고 빠르게 배포하는 도구
    • v 1.0.16
    • v 0.13.1과는 많이 다름...!
  • Prometheus : free software application used for event monitoring and alerting(metric 추출)
    • helm v3.7.2 : Kubernetes 패키지 관리를 도와주는 것(패키지매니저)으로, yaml 파일의 모음
    • kube-prometheus-stack Helm Repo 추가
  • Grafana : 시각화 툴(추출된 metric을 받아서 사용자가 보기 쉽게 그래프로 시각화)

 

 

1. 모델 학습

데이터는 Kaggle API를 활용해 fraud detection 데이터를 가져와서 간단한 모델 학습을 진행해 보겠습니다.

Kaggle API활용을 위해서는 Kaggle 사이트에서 API토큰을 받아야 하는데요, kaggle 계정 > account로 들어가면 아래 API > Create New API Token을 누르면 json 파일이 다운로드됩니다.

1.1 캐글 데이터 다운로드

# kaggle api 설치
pip install kaggle

# kaggle 계정의 API 토큰 다운로드해서 ~/.kaggle 경로로 이동 
mkdir -p ~/.kaggle
mv kaggle.json ~/.kaggle/

# 원하는 데이터 다운로드 & unzip
kaggle competitions download -c playground-series-s3e4
unzip playground-series-s3e4.zip

 

1.2 모델 학습 & BentoML로 저장

import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from xgboost import XGBClassifier
from sklearn.preprocessing import StandardScaler

import bentoml

random_seed = 1025

# preprocessing data
df = pd.read_csv('train.csv')
data = df.drop(['Time','id'], axis=1)

X,y = data.drop(['Class'], axis=1), data['Class'] 

# training models
clf_xgb = XGBClassifier(seed=random_seed)
clf_rf = RandomForestClassifier(random_state=random_seed)

clf_xgb.fit(X, y)
clf_rf.fit(X, y)

# saving models with BentoML
saved_xgb = bentoml.xgboost.save_model("clf_xgb", clf_xgb)
print(f"Model saved: {saved_xgb}")
# Model saved: Model(tag="clf_xgb:tzabfwwrookscy5p")
saved_rf = bentoml.sklearn.save_model("clf_rf", clf_rf)
print(f"Model saved: {saved_rf}")
# Model saved: Model(tag="clf_rf:tzabfxgrookscy5p")

아래 커맨드로 모델이 생성된 것을 확인할 수 있습니다.

 

 

2. 모델 서빙을 위한 BentoService 생성

아래와 같이 service_xgb.py을 만들어 REST API를 만들 수 있습니다.

# creating a service for prediction

## service_xgb.py
import numpy as np
import pandas as pd

import bentoml
from bentoml.io import PandasDataFrame, NumpyNdarray

# create a runner from the saved Booster
runner_xgb = bentoml.xgboost.get("clf_xgb:latest").to_runner()

# create a BentoML service
svc = bentoml.Service("fraud_detection_xgb", runners=[runner_xgb])

sample_json = [{"V1":1.7435253512,"V2":-1.6814290864,"V3":-0.5473867184,"V4":-1.0611134734,
"V5":-0.6958249515,"V6":2.4588244846,"V7":-1.6328591849,"V8":1.0735287834,"V9":1.0681825579,
"V10":0.483336796,"V11":0.2745186711,"V12":-0.3465137824,"V13":-0.4095190746,"V14":-0.5646730482,
"V15":-0.1438552978,"V16":1.3348551619,"V17":0.1609014913,"V18":-0.0873564994,"V19":-0.0662640553,
"V20":0.4417884547,"V21":0.5432775994,"V22":1.29457068,"V23":0.309540793,"V24":3.7039246049,
"V25":-0.2425792597,"V26":0.0687079234,"V27":0.002629054,"V28":0.0646899497,"Amount":163.5}]
input_spec = PandasDataFrame.from_sample(pd.DataFrame(sample_json))

# define a new endpoint on the BentoML service
@svc.api(input=input_spec, output=NumpyNdarray())
async def classify_fraud_xgb(input: pd.DataFrame):
    result = runner_xgb.predict.run(input)
    return result
    
## service_rf.py
import numpy as np
import pandas as pd

import bentoml
from bentoml.io import PandasDataFrame, NumpyNdarray

runner_rf = bentoml.sklearn.get("clf_rf:latest").to_runner()

svc = bentoml.Service("fraud_detection_rf", runners=[runner_rf])

sample_json = [{"V1":1.7435253512,"V2":-1.6814290864,"V3":-0.5473867184,"V4":-1.0611134734,
"V5":-0.6958249515,"V6":2.4588244846,"V7":-1.6328591849,"V8":1.0735287834,"V9":1.0681825579,
"V10":0.483336796,"V11":0.2745186711,"V12":-0.3465137824,"V13":-0.4095190746,"V14":-0.5646730482,
"V15":-0.1438552978,"V16":1.3348551619,"V17":0.1609014913,"V18":-0.0873564994,"V19":-0.0662640553,
"V20":0.4417884547,"V21":0.5432775994,"V22":1.29457068,"V23":0.309540793,"V24":3.7039246049,
"V25":-0.2425792597,"V26":0.0687079234,"V27":0.002629054,"V28":0.0646899497,"Amount":163.5}]
input_spec = PandasDataFrame.from_sample(pd.DataFrame(sample_json))

@svc.api(input=input_spec, output=NumpyNdarray())
async def classify_fraud_rf(input: pd.DataFrame):
    result = runner_rf.predict.run(input)
    return result

위에서 생성한 파일을 bentoml로 serve 하게 되면 아래와 같이 REST API가 만들어지고 http://0.0.0.0:3000/classify_fraud_xgb 에서 확인할 수 있습니다.

$ bentoml serve serve_xgb.py

 

여기서 API 호출 테스트도 가능하고 터미널에서도 API 호출 테스트 진행할 수 있습니다.

 

터미널 창에서도 아래와 같이 API 호출 테스트할 수 있고 결과로 [0] 응답하는 것을 확인할 수 있습니다.

curl -X 'POST' \
  'http://0.0.0.0:3000/classify_fraud_xgb' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '[
  {
    "V1": 1.7435253512,"V2": -1.6814290864,"V3": -0.5473867184,"V4": -1.0611134734,"V5": -0.6958249515,
    "V6": 2.4588244846,"V7": -1.6328591849, "V9": 1.0681825579, "V10": 0.483336796,"V11": 0.2745186711,
    "V12": -0.3465137824,"V13": -0.4095190746,"V14": -0.5646730482,"V15": -0.1438552978,"V16": 1.3348551619,
    "V17": 0.1609014913,"V18": -0.0873564994,"V19": -0.0662640553,"V20": 0.4417884547,"V21": 0.5432775994,
    "V22": 1.29457068,"V23": 0.309540793,"V24": 3.7039246049,"V25": -0.2425792597,
    "V26": 0.0687079234,"V27": 0.002629054, "V28": 0.0646899497,"Amount": 163.5
  }
]'

# [0]

 

 

3. Bento 만들고 도커 이미지 생성

위에서 생성한 service를 바탕으로 bentofile을 만든 뒤, 해당 bentofile로 Bento를 만들고 도커 이미지를 만들어보겠습니다.

# creating bentofile.yaml for ML service
## bentofile_xgb.yaml
service: "service_xgb:svc"
include:
- "service_xgb.py"
python:
  packages:
  - numpy
  - pandas
  - xgboost
  - scikit-learn
  
  
## bentofile_rf.yaml
service: "service_rf:svc"
include:
- "service_rf.py"
python:
  packages:
  - numpy
  - pandas
  - xgboost
  - scikit-learn

아래 코드로 Bento를 만들 수 있습니다.

# Build a Bento to lock the model version and dependency tree
bentoml build -f bentofile_xgb.yaml

 

도커 이미지도 만들어주면 아래와 같이 이미지가 생성된 것을 확인할 수 있습니다.

# Ensure docker is installed and running, build a docker image with bentoml containerize
bentoml containerize fraud_detection_xgb:latest

 

잘 생성됐는지 확인하기 위해서 해당 이미지로 도커를 실행해 보겠습니다.

# Test out the docker image built
docker run -it --rm -p 3000:3000 fraud_detection_xgb:xtvs6igrrckscy5p serve --production

아래와 같이 API가 생성되었고 가장 최신 버전의 tag로 API가 생성된 것을 확인할 수 있습니다.

 

 

4.  쿠버네티스에 배포

자 이제 쿠버네티스 배포를 해보겠습니다. 먼저 Service와 Deployment yaml 파일을 만들어 우리가 배포할 상태를 정의해야 합니다........ 에서 막혔습니다 ㅜ.ㅜ

 

성공하는 대로 내용 추가해 보겠습니다!

# start minikube
minikube start --driver=docker --cpus='3' --memory='4g'
# fraud_detection_xgb_dp.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: fraud-detection-xgb
  name: fraud-detection-xgb
spec:
  ports:
  - name: predict
    port: 5000
    targetPort: 5000
  selector:
    app: fraud-detection-xgb
  type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: fraud-detection-xgb
  name: fraud-detection-xgb
spec:
  selector:
    matchLabels:
      app: fraud-detection-xgb
  template:
    metadata:
      labels:
        app: fraud-detection-xgb
    spec:
      containers:
      - image: fraud_detection_xgb:xtvs6igrrckscy5p
        name: fraud-detection-xgb
        ports:
        - containerPort: 5000
# fraud_detection_xgb_dp_test 네임스페이스에 모델 배포
kubectl apply -f fraud_detection_xgb_dp.yaml -n fraud_detection_xgb_dp_test

# 배포된 svc, ip 주소 확인
kubectl get svc/fraud_detection_xgb_dp -n fraud_detection_xgb_dp_test

 

 

5. Prometheus-Grafana 모니터링

먼저 kube-prometheus-stack Helm Repo 추가해 주고, kube-prometheus-stack 설치합니다.

# start minikube
minikube start --driver=docker --cpus='3' --memory='4g'

# helm repo 추가
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts

# helm repo update
helm repo update

# helm install [RELEASE_NAME] prometheus-community/kube-prometheus-stack

helm install prom-stack prometheus-community/kube-prometheus-stack
# 모든 values 는 default 로 생성됨
# https://github.com/prometheus-community/helm-charts/blob/main/charts/kube-prometheus-stack/values.yaml

# 정상 설치 확인
# 최초 설치 시 docker image pull 로 인해 수 분의 시간이 소요될 수 있음
kubectl get pod -w

새로운 터미널을 열어 포트포워딩을 해줍니다.

# for Grafana
kubectl port-forward svc/prom-stack-grafana 9000:80

# for Prometheus
kubectl port-forward svc/prom-stack-kube-prometheus-prometheus 9091:9090

 

그러면 이제 localhost:9091로 Prometheus 접속이 가능합니다.

현재 쿠버네티스에 존재하는 pod들의 상태나 컨테이너 별 메모리 사용 현황 등을 확인할 수 있습니다.

Prometheus

 

Grafana는 localhost:9090에서 접근할 수 있습니다. Prometheus에서 받아온 metric으로 시각화가 가능하고 디폴트로 admin / prom-operator 계정으로 로그인하여 접근이 가능합니다.

Dashboards 탭에서 다양한 기본 대시보드를 확인할 수 있고 수정이 가능합니다. 디폴트로 들어가 있는 Kubernetes/Compute Resources/Namespace(Pods) 를 선택하면 Pod별 컴퓨팅 리소스 확인이 가능합니다.

Grafana

 

Grafana 대시보드 사이트에서 원하는 템플릿을 찾아서 간단하게 추가하여 사용할 수 있으니 아래 사이트 참고해 주세요.

https://grafana.com/grafana/dashboards/

 

Dashboards | Grafana Labs

 

grafana.com

 


 

 

도커, 쿠버네티스와 BentoML에 대한 기본 정보가 필요하시면 아래 포스트 참고 해주세요 : )

https://slowsteadystat.tistory.com/37

 

도커 & 쿠버네티스 설치에 필요한 기본 개념 정리

이 글이 도움 되셨다면 광고 클릭 부탁드립니다 : ) 요즘 모델 서빙을 준비하다 보니 도커와 쿠버네티스 베이스가 필요해 공부하며 정리한 포스트입니다. 참고한 도서는 그림과 실습으로 배우는

slowsteadystat.tistory.com

https://slowsteadystat.tistory.com/38

 

BentoML이란?!

이 글이 도움 되셨다면 광고 클릭 부탁드립니다 : ) BentoML에 대해 찾아보며 알게된 내용을 정리한 포스트입니다. BentoML이란?! 0. BentoML 기본 정보 The Unified Model Serving Framework, BentoML makes it easy to crea

slowsteadystat.tistory.com

 

참고 사이트

공식사이트 튜토리얼

https://docs.bentoml.org/en/latest/tutorial.html

 

Tutorial: Intro to BentoML

time expected: 10 minutes In this tutorial, we will focus on online model serving with BentoML, using a classification model trained with scikit-learn and the Iris dataset. By the end of this tutor...

docs.bentoml.org

공식사이트 example github_fraud_detect

https://github.com/bentoml/BentoML/tree/main/examples/fraud_detection

 

GitHub - bentoml/BentoML: Unified Model Serving Framework 🍱

Unified Model Serving Framework 🍱. Contribute to bentoml/BentoML development by creating an account on GitHub.

github.com

https://www.fosstechnix.com/kubernetes-cluster-monitoring-with-prometheus-and-grafana/

 

Kubernetes cluster Monitoring with Prometheus and Grafana

Kubernetes cluster Monitoring with Prometheus and Grafana, install prometheus and grafana on kubernetes using helm, Install helm on Linux, configure alertmanager.

www.fosstechnix.com

 

반응형