MLops 도입기 - 그래서 무엇을 경험했는가?

1년 차의 실패 경험을 딛고 내가 얻은 생각들
Dec 10, 2023
MLops 도입기 - 그래서 무엇을 경험했는가?
본 글은 1년차 때 mlops를 간단하게 도입한 것을 주제로 작성한 글입니다. mlops에 관심있는 분들과 경험을 공유하면 좋을 것 같아서 작성하였습니다.
mlops를 도입하게 된 계기는 다시 생각해보니 작다고 느껴지네요. 현재 재직 중인 회사에 인공지능 연구원이 1명이 있고, 수 십번의 모델 훈련을 통해서 모델 성능을 체크해야 하는데, 매번 flask 서버에 모델 pt 파일 올리고 모델 성능 체크하고 성능을 보고서 형식으로 작성하는 과정을 반복해서 변화를 주고 싶었습니다..!
그래서 올해 4월부터 7월까지 거쳐서 도입을 완료했습니다,, (아직 혼자 무언가를 만든게 별로 없어다 보니 오래 걸렸네요 ,,).
대략적으로 말씀드리자면 kubernetes, kubeflow, mlflow, bentoml 등 을 사용했는데, 그중에서 kubernetes와 bentoml을 도입하는 과정에서 어려움을 많이 느꼈습니다. 엄청 간단한 기능들을 제공한다는 점을 미리 말씀드립니다!
그럼 우선 각각의 툴이 어떤 역할을 맡고 있는지 간단하게 살펴보고 개인적인 의견과 내용을 풀어보겠습니다!
처음으로 혼자서 일정 짜고 프로젝트 기한 맞추느라 우선순위가 다 높음으로 처리한게 이제와서 보니 조금 웃프네요.
처음으로 혼자서 일정 짜고 프로젝트 기한 맞추느라 우선순위가 다 높음으로 처리한게 이제와서 보니 조금 웃프네요.

kubeflow가 맡은 기능

  1. 데이터셋 구성 요소 준비
      • 실제로 모델 학습 시에 사용되는 데이터셋은 kubeflow에서 지원하는 persistent volume을 활용해 독립된 공간에 위치해 있습니다.
      • juypter lab을 persistent volume으로 사용한 이유는 데이터셋 관련 분석이 원활한 환경에서 실험하도록 하기 위해서입니다.
      notion image
  1. 파이프라인 실행 과정
    1. kubeflow pipeline 정의 및 업로드
      1. notion image
        • 위에 보이시는 white block은 각각 model을 학습시키고, 모델을 저장하고, 모델을 배포하는 기능을 수행합니다.
        • 모두 docker image 형태로 배포되기 때문에 모델 실험 과정에서 관리하기 용이합니다.
         
    2. 학습하는 과정에서 필요한 hyperparameter를 UI를 통해 넘겨줄 수 있습니다.
      1. notion image
        • 현재 모델에서 필요로 하는 hyperparameter, 혹은 이 pipeline이 수행하기 위해 필요한 조건들을 직접 넣어줍니다.
        • 실제로 train만 시키고 모델을 서비스로 배포하지 않겠다고 한다면 그 설정을 현재 상황에서 조절할 수 있습니다.
    3. pipeline이 실행하는 과정 중 train component의 동작 과정입니다.
      1. notion image
        • python script에서 print 기능의 코드도 log에 남기에 불편함 없이 log를 추적할 수 있습니다.
    4. 해당 component가 문제 없이 동작한다면 다음 component로 넘어갑니다.
        • 해당 pipeline 자체가 로직의 오류없이 잘 동작하면 아래 소개되는 기능들이 잘 작동돕니다.
        • kubeflow가 진행해야하는 task의 순서와 우선순위를 정해주고 동작하기 때문에 pipeline의 역할을 수행한다고 볼 수 있습니다.
        notion image
       

      mlflow가 맡은 기능

    5. kubeflow 학습된 모델 저장 기능
    6. notion image
      • experiment를 명시함으로써 kubeflow에서 train component를 통해 학습된 모델의 결과(가중치, 라이브러리 환경)을 저장할 수 있습니다.
    7. 모델 저장 기능
    8. notion image
      • 모델의 버전을 업데이트할 수 있는 기능을 활용하여 배포할 모델을 정합니다.
      • production level로 결정된 version을 실제 serving에 사용됩니다.
       

      yatai, bentoml가 맡은 기능

    9. 배포 기능
        • mlflow에 저장된 model을 활용해 bentoml 모델 이미지로 build를 진행합니다.
        • 이후 kubectl cli 기능을 사용해 자동으로 배포할 수 있도록 설계했습니다.
          • 새로운 모델 추론 서버를 올리고 싶을 때 : yaml 파일을 deploy합니다.
          • 이전에 있던 모델을 새로 학습시키고, 모델 성능이 더 나아졌을 때 : kubernetes deployment의 bentoml 모델 이미지를 새로운 이미지로 변경합니다.
       
    10. swagger ui를 통한 실험 기능
        • 배포된 모델 추론 서버를 swagger를 통해 실험할 수 있습니다.
        • swagger를 사용하면 비개발자들도 쉽게 모델의 성능 테스트해 볼 수 있기 때문에 이 점을 중요하게 생각해서 bentoml을 사용했습니다.
        notion image

      jenkins 기능

    11. 이미지 빌드 기능 (CI)
        • docker 이미지 기반으로 kubeflow의 component를 동작하기 때문에 continuous integration 기능을 지원하는 jenkins를 사용했습니다.
        • docker hub 에 빌드된 docker image를 업로드하고, kubeflow에서도 docker hub에 접근해서 docker image를 가져옵니다.
        notion image
        notion image
    12. pipeline 업로드 자동화 기능
        • 사용자의 편리성을 위해 docker image들이 build 된 후, kubeflow pipeline을 자동으로 업로드 후 pipeline을 자동으로 실행합니다. 덕분에 kubeflow pipeline이 자동으로 실행하여 수동적인 작업이 들어가지 않습니다.
        notion image
 

도입 과정에서 겪은 문제들을 뽑자면!

  1. on-premise 환경에서 kubeflow juypter notebook 접속 이슈
    1. 원격 서버에서 설치한 kubeflow 환경에서 CSRF token 문제가 발생할 경우, metallb_config에서 처음에 잘못 설정해줬다면 이를 고치면 해결할 수 있다는 것을 볼 수 있었습니다다. 하지만, 이 방법이 적용이 안될 경우, jupyter notebook의 설치 과정에서 securefalse로 바꾸는 것도 방법임을 확인할 수 있었습니다.
  1. bentoml의 버전 이슈
    1. # bentoml github Bentoml/src/bentoml/_internal/cloud/client.py in latest (1.1.6) # In version 1.0.15, path that needs to be compared is # BentoML-1.0.15/src/bentoml/_internal/yatai_rest_api_client/yatai.py def _is_not_found(self, resp: requests.Response) -> bool: # We used to return 400 for record not found, handle both cases return ( resp.status_code == 404 or resp.status_code == 400 and "record not found" in resp.text )
      • 기존에 1.0.15버전을 활용해서 bentoml의 배포 기능을 활용하려고 했는데, 모델이 yatai를 통해 서비스화 되지 않는 문제를 만난 적이 있습니다. 소스코드를 뜯어보니 1.0.15를 쓰고 있는 현재 404 에러에 대한 처리가 없어서 계속 예외처리로 빠지는 것으로 확인할 수 있었습니다. 이 문제는 1.0.19에서도 문제가 발생되는 것을 확인했고, 1.1.6 에서는 문제가 없음을 확인하여 버전을 올려서 사용할 수 있었습니다.

아쉬웠던 점

  • Q. 간단한 기능인데 여기서 Level 3로 만들려면 어떤 게 필요하려나?
    • 아직 정확한 방법을 떠오르진 못했는데 무엇보다 continuous training이 가능해야 할거 같다고 생각합니다. concept drift나 data drift 를 먼저 감지하면 production level에서 들어오는 데이터 input들을 모델을 retrain에 쓰여야 하는 상황입니다. 저희 팀에서 현재 활용하고 있는 모델은 cnn 모델이고 label data가 필요하기 때문에 이미지 label 작업이 필요하여 continuous training 도입을 보류한 상황입니다.
  • Q. 그래서 도입을 완료했나?
    • 환경을 모두 구성했지만 현재 회사에서 활발히 사용하고 있는 단계는 아닙니다. 도입을 하기 전에도 저는 기술부채를 최대한 줄이고자 노력했고, 그 과정에서도 우선 팀원들이 사용하기 편하게 end to end로 모델 학습부터 배포를 가능하게끔 만들었습니다.
    • 하지만 아직은 유저가 활발히 들어오는 서비스로 성장하지 못했고, 특정 기관에서만 활용할 예정으로 확정이 나면서 kubernetes의 도입 이유도 흐려진 상황입니다.
    • 그리고 연구 과정에서 모델의 크기도 줄어들어 모델의 추론이 1초 내로 감소하여 bentoml를 활용하지 않아도 유저 단에서 delay도 줄어들어 bentoml의 필요성도 줄었습니다.
    • 이런 과정에서 저는 제가 지난 시간동안 도입한 환경에 대한 필요성을 냉정히 바라보아 완벽히 서비스로 만들기 전까지 활용을 보류하는 것으로 팀에게 건의했습니다.
  • Q. 그렇다면 나는 이번 경험을 통해 어떤 점들을 배웠을까?
    • 다시 한 번 기술 부채에 대해 진지하게 생각해볼 수 있었습니다. 아직은 적은 경험을 갖고 있는 저로서는 어떤 인프라를 도입해보는 것은 매력적이라고 생각했고 회사에서 현재 필요한 것인지 냉정히 판단하기에는 미숙했다고 생각합니다.
    • 제 자신을 한계에 밀어붙인 경험을 해봤다고 생각합니다. 퇴근 후에는 kubernetes에 대해 공부하며 몰랐던 내용들을 배웠고, 주말에도 오류 수정하는데 시간을 투자해서 4달을 안 넘길 수 있었다고 생각합니다.
    • 마지막으로 팀 단위의 소통이 정말 중요하다는 것을 느꼈습니다. 현재 재직중인 회사에 소프트웨어 팀은 한 명당 2개의 프로젝트를 다루고 있다 보니 프로젝트의 피드백을 받기 어려운 게 제일 아쉽습니다. 만일 서로의 업무 프로세스를 적극적으로 공유했다면 도입 전에 피드백을 받아 기술부채의 아쉬움을 줄일 수 있지 않았을까라는 생각이 드네요. 회사에서 근무한다면 우선순위로 개발팀의 팀 문화를 보자는 생각도 할 수 있었어요.
  • Q. TMI
    • 해당 경험을 다른 ML 엔지니어들과 경험을 공유하니, cnn 계열 모델이 애초에 작기 때문에 모델의 추론이 오래 걸리지 않는 편이라고 의견을 준 적이 있습니다. 현재 LLM이 등장하고 난 이후로 모델의 크기를 논하자면 절대적으로 작은 편이라고 저도 생각합니다. 그런 면에서 보았을 때, 모델의 추론 최적화를 먼저 진행하고 나서 모델 추론에 쓰일 툴을 그 다음에 결정하는 것이 더 적절한 프로세스라고 생각이 들었습니다.
    • kubernetes는 물리적으로 gpu를 공유하여 사용할 수 없다는 점들과 같은 사실들을 고려해서 최적화 작업을 먼저 진행하면서 모델의 서빙 프레임워크를 선택하는 것이 도입 과정에서 어려움을 덜 수 있다고 생각합니다.
Share article

allaboutml