모델 인퍼런스 결과값을 API 콜하여 받을 수 있도록 패키징하여 도커라이징하는 작업이 필요했다. 실제로 민감한 데이터를 기반으로 고객 서버에서 모델을 직접 운영할 수 있도록 API로 감싸 전달하는 경우가 많다. 이런 경우 고객 서버에서 프론트만 따로 만들거나, 사용중인 시스템에 붙여서 사용하기 위해 API + 코드 적재된 컨테이너 형태로 요청하는 경우가 매우 많다.
개발용 컨테이너는 cuda + pyenv + poetry + 테스트 패키지 등이 모두 섞여있어 최초 이미지 사이즈는 약 25G에 달했다. 사실 이렇게 클 것이라 생각하지 못하고 '한번 그대로 말아볼까?' 시도했던 것이다. 낭패였다.
CPU 인퍼런스
python
poetry
위 환경의 도커파일 작성 과정과 그 안에서 배운 것을 하나하나 기록한다.
GPU inference... 득보다 실이 많지 않을지 확실히 따지기(절대적인 속도가 중요하지 않다면 CPU inference를 고려한 Base image로 바꿔보자)
모델링을 진행한 개발 컨테이너는 GPU 자원이 충분했고, Dockerfile의 Base image로 nvidia/cuda 를 사용하였다. (nvidia container toolkit 가이드 활용)
우리가 전달해야할 API의 주요 기능은 일정 기간 데이터와 함께 예측 기능을 호출하면, Best checkpoint model을 기반으로 인퍼런스가 수행되고 그 결과값을 csv로 저장하고 해당 파일의 패스를 리턴하는 것이었다.
그런데 개발 컨테이너 기준으로 API 서버 컨테이너 Dockerfile을 만들어주자니, nvidia/cuda-11.7.1-cudnn8-devel-ubuntu22.04 이미지의 용량이 상당히 큰 것이다.( 무려 7.69G )
허겁지겁 GPU와 CPU 사용 인퍼런스 시간을 각각 체크해보았다.
비교 결과 GPU 추론을 사용할 이유가 없었다. 사실 속도를 비교 전에 해당 API의 사용 목적 측면에서 실시간 추론이 필요하지 않았기 때문에 GPU 사용을 쉽게 포기할 수 있었다.(포기라고 할 것도 없었다. 욕심이 맞을 듯)
자, GPU 사용을 위한 cuda toolkit 고려할 필요가 없으니, 기존에 Dockerfile에 pip install 로 설치했던 python을 아예 Base image로 사용하는 것이 어떨까? 🙆🏻♀️
Official python image 도 종류가 다양하다. 그 중 경량화를 목적으로 주로 사용하는 것은 확인 결과 alpine , slim 정도.
(Official이라 하지만 open source image를 사용하는 것은 보안상 위험하다고 한다. 이 부분은 추가 공부가 필요해보인다. 오늘도 기술 부채가 쌓인다 화이팅!)
개발 서버에서 이미지를 다운받아 용량을 직접 확인해보았다.
python:3.10.6 921MB
python:3.10.6-slim 126MB
python:3.10.6-alpine 48.7MB
"GPU 기반 컨테이너를 사용할 때와 동일하게 동작하는가?"를 기준으로 위 3개 이미지 테스트를 진행했고, 최종적으로 slim image를 선택하였다.
우리가 사용하는 ubuntu 서버에서도 그렇지만, 고객 서버가 alpine linux가 아니었고 실제로 alpine에서는 필요한 패키지가 제대로 설치되지 않았기 때문.
Base Image 변경으로 약 8GB 경량화 성공
poetry add package group 분리 후 필요없는 group 은 poetry install에서 제외하기
RUN poetry install --no-rootRUN poetry install --without dev --no-root
# 또는
RUN poetry install --only mainAPI 서비스에 필요없는 패키지 설치를 줄여 약 2 G 경량화