Обслуживание моделей машинного обучения для прогнозирования в реальном времени — горячая тема, и существует множество решений. Самый простой — использовать полностью управляемый сервис, такой как Amazon Sagemaker, который берет на себя всю операционную нагрузку по развертыванию и масштабированию за вас.

Помимо этого, помимо Kubernetes существуют проекты по обслуживанию моделей, такие как KFServing и Seldon Core. Эти решения позволяют развертывать модели в кластере Kubernetes и интегрировать их с распространенными платформами машинного обучения.

Наконец, есть возможность обернуть ваши модели с помощью REST API, что дает больше свободы и настроек. Де-факто способ их развертывания заключается в использовании службы контейнеров, такой как Amazon ECS, которая управляет контейнерами вместо вас, или Amazon EKS, которая управляет кластером Kubernetes вместо вас.

Наше решение для обслуживания моделей машинного обучения — это REST API на основе Fast API, использующий MLflow для упаковки моделей. Amazon EKS использовался в Insider с момента предварительного просмотра сервиса, поэтому мы выбрали именно его для развертывания, поскольку у нас уже были запущенные и работающие кластеры. Будут также публикации об архитектуре службы обслуживания моделей.

Масштабирование в Kubernetes

Автомасштабирование в Kubernetes достигается с помощью Horizontal Pod Autoscaler (HPA) с масштабируемым ресурсом, таким как развертывание или набор с отслеживанием состояния. HPA запрашивает Сервер метрик, который собирает метрики с запущенных модулей через kubelet, чтобы получить метрики, которые можно использовать для мониторинга и масштабирования развертываний. Kubernetes по умолчанию предоставляет метрики ЦП и модулей памяти. Для любого другого ресурса вам необходимо использовать Пользовательские показатели, которые позволяют масштабировать любой определенный вами показатель.

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: model-serving-deployment
  minReplicas: 1
  maxReplicas: 50
  metrics:
    - type: Resource
        resource:
          name: cpu
          target:
            type: Utilization
            averageUtilization: 75

Выше приведен пример конфигурации HPA для ресурса развертывания с именем model-serving-deployment. Целевая метрика — это средняя загрузка ЦП, а целевое значение — 75. Это означает, что мы хотим, чтобы HPA пытался поддерживать среднюю загрузку ЦП на уровне около 75 % путем увеличения и уменьшения масштаба между 1–50 модулями.

Масштабирование по пользовательской метрике

Целевая метрика является важной конфигурацией для HPA, так как использование несвязанной/неправильной метрики может привести к недостаточному или чрезмерному масштабированию развертывания и ухудшению работоспособности службы. Предоставленных метрик недостаточно для нашего варианта использования; модель обслуживания. Потому что узким местом является не использование ЦП и памяти, а задержка. Наши нагрузочные тесты показали, что задержка резко возрастает после достижения порога запросов в секунду (RPS), в то время как загрузка ЦП и памяти не достигла 100%. Поэтому мы выбрали пропускную способность запроса в качестве показателя масштабирования.

Можно получить метрику запросов в секунду для ingress, однако сырых метрик ingress нам было недостаточно. Потому что у нас есть развертывание для каждого приложения, и мы хотим масштабировать каждое приложение в соответствии с пропускной способностью их запросов. Поэтому нам пришлось использовать API пользовательских метрик, чтобы обеспечить метрику количества запросов в секунду для каждого приложения.

Реализация сервера пользовательских метрик

Чтобы HPA мог считывать целевую метрику из API пользовательских метрик, должна быть реализована реализация сервера пользовательских метрик для считывания и обслуживания требуемых данных метрик. В нашем случае Адаптер Prometheus выполняет эту работу, поскольку мы уже передавали Prometheus метрики запросов Nginx.

Адаптер Prometheus легко устанавливается через Helm, см. файл values.yaml. Конфигурации адаптера Prometheus должны включать строку подключения Prometheus и пользовательские правила. Эти правила извлекают значения метрик из Prometheus и предоставляют их на сервере пользовательских метрик для использования HPA для масштабирования.

Для деталей реализации; прочтите здесь для конфигураций обнаружения, здесь для пошагового руководства по настройке и здесь для полного пошагового руководства по автомасштабированию с использованием пользовательских метрик. Также есть хороший файл README другой реализации, в котором объясняется, как работает Custom Metrics Server в Kubernetes.

rules:
  default: false
  custom:
    - seriesQuery: 'nginx_ingress_controller_requests{namespace!="",service!=""}'
      resources:
        overrides:
          namespace:
            resource: "namespace"
          service:
            resource: "service"
      name:
        matches: "nginx_ingress_controller_requests"
        as: "nginx_ingress_requests_per_second"
      metricsQuery: 'sum(rate(<<.Series>>{<<.LabelMatchers>>}[5m])) by (<<.GroupBy>>)'

Приведенное выше специальное правило извлекает серию nginx_ingress_controller_requests из Prometheus, объединяет ее по пространству имен/службе и возвращает запросов в секунду, измеренных за последние 5 минут, используя скорость. функция запроса Prometheus. Переименование в конце позволяет нам использовать выходные данные запроса как nginx_ingress_requests_per_second в конфигурациях HPA.

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: model-serving-deployment
  minReplicas: 1
  maxReplicas: 50
  metrics:
    - type: Object
      object:
        metric:
          name: nginx_ingress_requests_per_second
        describedObject:
          kind: Service
          name: model-serving-deployment
          apiVersion: v1
        target:
          type: AverageValue
          averageValue: 20000m

Последним шагом является развертывание HPA, нацеленного на развертывание (model-serving-deployment в конфигурации) с использованием нашей пользовательской метрики nginx_ingress_requests_per_second. Обратите внимание, что spec.scaleTargetRef используется для таргетинга развертывания для HPA, а spec.metrics.object.desiredObject используется для получения правильных метрик службы из Custom Metrics API.

Используя AverageValue в качестве целевого типа, мы запрашиваем усреднение метрики по всем модулям в службе. Установив для параметра spec.metrics.object.target.averageValue значение 20 000 м, мы требуем, чтобы HPA увеличивалось и уменьшалось, чтобы поддерживать среднее количество запросов в секунду между модулями на уровне около 20 RPS в пределах 1 – Ограничение на 50 реплик pod.

Конечно, поскольку это пример, количество реплик и целевое значение должны быть настроены в соответствии с ограничениями вашего приложения, которые можно измерить, выполнив нагрузочный тест.

Заключение

Существует множество способов развертывания моделей машинного обучения в рабочей среде, и оболочка API — один из них. Удобным способом развертывания контейнерных приложений является использование Amazon EKS для управляемого кластера Kubernetes. Каждое приложение имеет свое узкое место и, следовательно, требует различных стратегий для увеличения и уменьшения масштаба или даже масштабирования вверх и вниз. Пропускная способность сети является надежной метрикой для масштабирования сервисов API, и ее также можно использовать в Kubernetes. Для масштабирования каждой службы в соответствии с пропускной способностью их сети можно определить пользовательскую метрику. Простое решение для реализации пользовательских метрик — использовать адаптер Prometheus, если вы используете Prometheus для журналов временных рядов входных запросов. Затем вы можете использовать заданную пользовательскую метрику для масштабирования любого развертывания в вашем кластере Kubernetes.