Обслуговування моделей машинного навчання за допомогою Docker та Kubernetes

В швидко змінюваному світі науки про дані та машинного навчання, здатність ефективно розгортати моделі є такою ж важливою, як і створення точних моделей. У моєму недавньому проєкті для DataTalks Machine Learning Zoomcamp я мав можливість використовувати Docker та Kubernetes для розгортання моделі машинного навчання. У цій статті я розповім, як ці технології були використані, з якими труднощами я зіткнувся та що я дізнався на цьому шляху.

Чому Docker та Kubernetes?

Перед тим, як зануритись у деталі проєкту, важливо зрозуміти, чому були обрані Docker та Kubernetes. Спочатку розглянемо загальну мету мого проєкту для Zoomcamp: його завдання — передбачити вартість вживаних автомобілів на основі їхнього року випуску, марки та моделі, використовуючи таблицю FIPE — стандартне посилання для ціноутворення автомобілів у Бразилії.

Основною функцією таблиці FIPE є розрахунок середніх цін на транспортні засоби (автомобілі, мотоцикли та вантажівки) для кожної моделі та версії по всій Бразилії. Вона служить основним орієнтиром для переговорів або оцінок, пропонуючи споживачам орієнтири щодо того, яка ціна є справедливою для купівлі або продажу конкретного транспортного засобу. Ціни оцінюються на основі опитувань цін на автомобілі та оновлюються щомісяця. Ціни відображають середні значення, що обговорюються на ринку, з коригуваннями в залежності від таких змінних, як стан автомобіля, виробник, рік, модель, регіон, опційні функції, колір та інші відповідні фактори. Окрім того, що таблиця FIPE є орієнтиром для роздрібних продавців і дилерів, вона використовується страховими компаніями для розрахунку відшкодувань у разі крадіжки чи повної втрати, а також для розрахунку страхових полісів і податкових нарахувань, таких як IPVA (податок на транспорт).

  1. Таблиця FIPE виражає середні ціни для готівкових угод на ринку перепродажу, орієнтуючись на індивідуальних споживачів по всій Бразилії. Вона призначена як параметр для переговорів або оцінок. Фактичні ціни угод можуть змінюватись залежно від регіону, стану автомобіля, кольору, аксесуарів або інших факторів, що впливають на попит та пропозицію конкретного автомобіля.
  2. Рік випуску автомобіля вказує на модельний рік, виключаючи транспортні засоби, призначені для професійного або спеціального використання.
  3. Ціни виражаються в бразильських реалах (BRL) для вказаного місяця та року.

Тепер, до питання, чому використовувати Docker та Kubernetes:

Docker спрощує процес створення, поширення та запуску додатків у контейнерах — легких, портативних середовищах, які упаковують ваш додаток і його залежності. Kubernetes, з іншого боку, є потужним інструментом оркестрації, який управляє контейнеризованими додатками, забезпечуючи масштабованість, надійність і простоту розгортання. Разом вони складають міцну основу для розгортання моделей машинного навчання.

Як все це організовувалось? Робочий процес був насправді простим: я навчав модель регресії для передбачення результатів на основі структурованого набору даних (це не новина для тих, хто вже знайомий з основами машинного навчання), а потім: контейнеризація за допомогою Docker з використанням Dockerfile, оркестрація з Kubernetes для розгортання контейнеризованого додатку в локальному кластері та масштабування Kubernetes-сервісу за допомогою LoadBalancer, що забезпечує ефективний розподіл трафіку та стійкість до збоїв.
Це був Dockerfile, який я створив для завантаження контейнера. Він використовує полегшену версію Python, завантажує бібліотеки через Poetry, копіює модель, над якою я працював, і потім відкриває порт 8000. API було дуже просто налаштувати за допомогою FastAPI:

FROM python:3.10.9-slim  

RUN apt-get update && apt-get install -y --no-install-recommends \  
 build-essential \  
 && rm -rf /var/lib/apt/lists/*  

RUN pip install poetry  

WORKDIR /app  

COPY ["pyproject.toml", "poetry.lock", "./"]  
RUN poetry config virtualenvs.create false  
RUN poetry install --no-root  
RUN poetry cache clear --all pypi  

COPY ./final_project/final_model.pkl ./  
COPY ./final_project/predict.py ./  

EXPOSE 8000  

ENTRYPOINT ["poetry", "run", "uvicorn", "predict:app", "--host", "0.0.0.0", "--port", "8000"]

Тепер для розгортання на Kubernetes і створення сервісу я використав два yaml файли для створення кластера та подів, а також масштабування за допомогою LoadBalancer з використанням kind і kubectl:

deployment.yaml

apiVersion: apps/v1  
kind: Deployment  
metadata:  
 name: fastapi-deployment  
spec:  
 replicas: 3  
 selector:  
 matchLabels:  
 app: fastapi  
 template:  
 metadata:  
 labels:  
 app: fastapi  
 spec:  
 containers:  
 - name: fastapi-server  
 image: fastapi-server:latest  
 imagePullPolicy: Never  
 ports:  
 - containerPort: 8000

service.yaml

apiVersion: v1  
kind: Service  
metadata:  
 name: fastapi-service  
spec:  
 type: LoadBalancer  
 selector:  
 app: fastapi  
 ports:  
 - port: 80  
 targetPort: 8000

З цього моменту все, що залишалося — це виконання таких команд у терміналі:

  • Зібрати Docker-образ за допомогою docker build -t fastapi-server .
  • Створити кластер за допомогою Kind kind create cluster --name fastapi-cluster
  • Завантажити Docker-образ в Kind kind load docker-image fastapi-server --name fastapi-cluster
  • Застосувати yaml файли через kubectl kubectl apply -f deployment.yaml && kubectl apply -f service.yaml
  • Перевірити статус всього kubectl get pods та kubectl get svc
  • Перенаправити порт для доступу kubectl port-forward service/fastapi-service 8000:80

Підсумкові думки

Спочатку розгортання тестувалося на локальному Kubernetes кластері за допомогою kind, і хоча це працювало добре, було розглянуто можливість масштабування до публічного хмари, такої як AWS EKS, для продакшн-середовища. Однак, щоб уникнути витрат, проєкт залишився локальним. Без хмарного LoadBalancer доступ до програми вимагав перенаправлення портів:

kubectl port-forward service/fastapi-service 8000:80

Це тимчасове рішення дозволило легко тестувати, при цьому залишаючи налаштування ефективними за витратами. Однак налаштування сервісу на AWS EKS є таким же простим, як і здається.

Використання Docker забезпечує портативність, дозволяючи програмі працювати стабільно в різних середовищах, тоді як Kubernetes спрощує оркестрацію та масштабування, забезпечуючи надійність і стійкість до збоїв. Протягом проєкту інтеграція FastAPI для обслуговування моделі та використання Kubernetes’ сервісу LoadBalancer дозволило ефективно управляти трафіком в локальному середовищі. Цей досвід продемонстрував цінність поєднання контейнеризації та інструментів оркестрації в конвеєрі розгортання, забезпечуючи плавну та масштабовану інфраструктуру для моделей машинного навчання.

Перекладено з: Serving ML Models with Docker and Kubernetes

Leave a Reply

Your email address will not be published. Required fields are marked *